2022-05-09 09:50:28 -04:00
|
|
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
#include "Containers/Array.h"
|
|
|
|
|
#include "Containers/Map.h"
|
|
|
|
|
#include "HAL/CriticalSection.h"
|
2023-09-22 15:01:07 -04:00
|
|
|
#include "Tasks/Pipe.h"
|
|
|
|
|
|
|
|
|
|
#include "MetasoundFrontendDataTypeRegistry.h"
|
2023-12-15 13:21:12 -05:00
|
|
|
#include "MetasoundFrontendRegistryContainer.h"
|
2022-05-09 09:50:28 -04:00
|
|
|
#include "MetasoundFrontendRegistryTransaction.h"
|
|
|
|
|
|
2023-09-22 15:01:07 -04:00
|
|
|
struct FMetasoundFrontendDocument;
|
|
|
|
|
|
2022-05-09 09:50:28 -04:00
|
|
|
namespace Metasound
|
|
|
|
|
{
|
2023-09-22 15:01:07 -04:00
|
|
|
class FProxyDataCache;
|
|
|
|
|
class FGraph;
|
|
|
|
|
|
2022-05-09 09:50:28 -04:00
|
|
|
namespace Frontend
|
|
|
|
|
{
|
2023-09-22 15:01:07 -04:00
|
|
|
struct FNodeClassInfo;
|
|
|
|
|
|
2022-05-09 09:50:28 -04:00
|
|
|
using FNodeRegistryTransactionBuffer = TTransactionBuffer<FNodeRegistryTransaction>;
|
|
|
|
|
using FNodeRegistryTransactionStream = TTransactionStream<FNodeRegistryTransaction>;
|
|
|
|
|
|
2022-08-12 14:22:05 -04:00
|
|
|
/** INodeRegistryTemplateEntry declares the interface for a node registry entry.
|
2022-08-10 14:18:10 -04:00
|
|
|
* Each node class in the registry must satisfy this interface.
|
|
|
|
|
*/
|
2022-08-12 14:22:05 -04:00
|
|
|
class INodeRegistryTemplateEntry
|
2022-08-10 14:18:10 -04:00
|
|
|
{
|
|
|
|
|
public:
|
2022-08-12 14:22:05 -04:00
|
|
|
virtual ~INodeRegistryTemplateEntry() = default;
|
2022-08-10 14:18:10 -04:00
|
|
|
|
|
|
|
|
/** Return FNodeClassInfo for the node class.
|
|
|
|
|
*
|
|
|
|
|
* Implementations of method should avoid any expensive operations
|
|
|
|
|
* (e.g. loading from disk, allocating memory) as this method is called
|
|
|
|
|
* frequently when querying nodes.
|
|
|
|
|
*/
|
|
|
|
|
virtual const FNodeClassInfo& GetClassInfo() const = 0;
|
|
|
|
|
|
|
|
|
|
/** Return a FMetasoundFrontendClass which describes the node. */
|
|
|
|
|
virtual const FMetasoundFrontendClass& GetFrontendClass() const = 0;
|
|
|
|
|
};
|
|
|
|
|
|
2022-05-09 09:50:28 -04:00
|
|
|
// Registry container private implementation.
|
2023-09-22 15:01:07 -04:00
|
|
|
class FRegistryContainerImpl
|
|
|
|
|
: public FMetasoundFrontendRegistryContainer
|
2022-05-09 09:50:28 -04:00
|
|
|
{
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
using FConverterNodeRegistryKey = ::Metasound::Frontend::FConverterNodeRegistryKey;
|
|
|
|
|
using FConverterNodeRegistryValue = ::Metasound::Frontend::FConverterNodeRegistryValue;
|
|
|
|
|
using FConverterNodeInfo = ::Metasound::Frontend::FConverterNodeInfo;
|
|
|
|
|
|
|
|
|
|
using FNodeRegistryKey = Metasound::Frontend::FNodeRegistryKey;
|
|
|
|
|
|
|
|
|
|
using FDataTypeRegistryInfo = Metasound::Frontend::FDataTypeRegistryInfo;
|
|
|
|
|
using FNodeClassMetadata = Metasound::FNodeClassMetadata;
|
|
|
|
|
using IEnumDataTypeInterface = Metasound::Frontend::IEnumDataTypeInterface;
|
|
|
|
|
|
|
|
|
|
FRegistryContainerImpl();
|
|
|
|
|
|
|
|
|
|
FRegistryContainerImpl(const FRegistryContainerImpl&) = delete;
|
|
|
|
|
FRegistryContainerImpl& operator=(const FRegistryContainerImpl&) = delete;
|
|
|
|
|
|
|
|
|
|
static FRegistryContainerImpl& Get();
|
|
|
|
|
static void Shutdown();
|
|
|
|
|
|
|
|
|
|
virtual ~FRegistryContainerImpl() = default;
|
|
|
|
|
|
|
|
|
|
// Add a function to the init command array.
|
|
|
|
|
virtual bool EnqueueInitCommand(TUniqueFunction<void()>&& InFunc) override;
|
|
|
|
|
|
2023-09-22 15:01:07 -04:00
|
|
|
virtual void SetObjectReferencer(TUniquePtr<IObjectReferencer> InReferencer) override;
|
|
|
|
|
|
2022-05-09 09:50:28 -04:00
|
|
|
// This is called on module startup. This invokes any registration commands enqueued by our registration macros.
|
|
|
|
|
virtual void RegisterPendingNodes() override;
|
|
|
|
|
|
2023-09-22 15:01:07 -04:00
|
|
|
// Wait for async graph registration to complete for a specific graph
|
2023-12-15 13:21:12 -05:00
|
|
|
virtual void WaitForAsyncGraphRegistration(const FGraphRegistryKey& InRegistryKey) const override;
|
2023-10-10 11:32:28 -04:00
|
|
|
|
2023-09-22 15:01:07 -04:00
|
|
|
// Retrieve a registered graph.
|
|
|
|
|
//
|
|
|
|
|
// If the graph is registered asynchronously, this will wait until the registration task has completed.
|
2023-12-15 13:21:12 -05:00
|
|
|
virtual TSharedPtr<const FGraph> GetGraph(const FGraphRegistryKey& InRegistryKey) const override;
|
2023-09-22 15:01:07 -04:00
|
|
|
|
2022-05-09 09:50:28 -04:00
|
|
|
/** Register external node with the frontend.
|
|
|
|
|
*
|
2023-12-15 13:21:12 -05:00
|
|
|
* @param InEntry - Entry to register.
|
2022-05-09 09:50:28 -04:00
|
|
|
*
|
|
|
|
|
* @return True on success.
|
|
|
|
|
*/
|
2022-08-10 14:18:10 -04:00
|
|
|
virtual FNodeRegistryKey RegisterNode(TUniquePtr<Metasound::Frontend::INodeRegistryEntry>&& InEntry) override;
|
|
|
|
|
|
2022-05-09 09:50:28 -04:00
|
|
|
virtual bool UnregisterNode(const FNodeRegistryKey& InKey) override;
|
|
|
|
|
virtual bool IsNodeRegistered(const FNodeRegistryKey& InKey) const override;
|
2023-12-15 13:21:12 -05:00
|
|
|
virtual bool IsGraphRegistered(const FGraphRegistryKey& InKey) const override;
|
2022-05-09 09:50:28 -04:00
|
|
|
virtual bool IsNodeNative(const FNodeRegistryKey& InKey) const override;
|
|
|
|
|
|
|
|
|
|
virtual bool RegisterConversionNode(const FConverterNodeRegistryKey& InNodeKey, const FConverterNodeInfo& InNodeInfo) override;
|
|
|
|
|
|
|
|
|
|
virtual void IterateRegistry(Metasound::FIterateMetasoundFrontendClassFunction InIterFunc, EMetasoundFrontendClassType InClassType = EMetasoundFrontendClassType::Invalid) const override;
|
|
|
|
|
|
2023-06-22 14:51:42 -04:00
|
|
|
// Find Frontend class data.
|
2022-05-09 09:50:28 -04:00
|
|
|
virtual bool FindFrontendClassFromRegistered(const FNodeRegistryKey& InKey, FMetasoundFrontendClass& OutClass) override;
|
2023-10-19 17:47:21 -04:00
|
|
|
|
|
|
|
|
UE_DEPRECATED(5.4, "This implementation of FindImplementedInterfacesFromRegistered(...). Please use bool FindImplementedInterfacesFromRegistered(const Metasound::Frontend::FNodeRegistryKey& InKey, TSet<FMetasoundFrontendVersion>& OutInterfacVersion)")
|
2023-06-22 14:51:42 -04:00
|
|
|
virtual const TSet<FMetasoundFrontendVersion>* FindImplementedInterfacesFromRegistered(const Metasound::Frontend::FNodeRegistryKey& InKey) const override;
|
2023-10-12 16:37:45 -04:00
|
|
|
|
2023-10-19 17:47:21 -04:00
|
|
|
virtual bool FindImplementedInterfacesFromRegistered(const Metasound::Frontend::FNodeRegistryKey& InKey, TSet<FMetasoundFrontendVersion>& OutInterfaceVersions) const override;
|
|
|
|
|
|
2023-10-12 16:37:45 -04:00
|
|
|
UE_DEPRECATED(5.4, "Use FindFrontendClassFromRegistered instead")
|
2022-05-09 09:50:28 -04:00
|
|
|
virtual bool FindNodeClassInfoFromRegistered(const Metasound::Frontend::FNodeRegistryKey& InKey, FNodeClassInfo& OutInfo) override;
|
2022-07-18 17:14:25 -04:00
|
|
|
virtual bool FindInputNodeRegistryKeyForDataType(const FName& InDataTypeName, const EMetasoundFrontendVertexAccessType InAccessType, FNodeRegistryKey& OutKey) override;
|
2022-05-09 09:50:28 -04:00
|
|
|
virtual bool FindVariableNodeRegistryKeyForDataType(const FName& InDataTypeName, FNodeRegistryKey& OutKey) override;
|
2022-07-18 17:14:25 -04:00
|
|
|
virtual bool FindOutputNodeRegistryKeyForDataType(const FName& InDataTypeName, const EMetasoundFrontendVertexAccessType InAccessType, FNodeRegistryKey& OutKey) override;
|
2022-05-09 09:50:28 -04:00
|
|
|
|
|
|
|
|
// Create a new instance of a C++ implemented node from the registry.
|
|
|
|
|
virtual TUniquePtr<Metasound::INode> CreateNode(const FNodeRegistryKey& InKey, const Metasound::FNodeInitData& InInitData) const override;
|
|
|
|
|
virtual TUniquePtr<INode> CreateNode(const FNodeRegistryKey& InKey, FDefaultLiteralNodeConstructorParams&&) const override;
|
|
|
|
|
virtual TUniquePtr<INode> CreateNode(const FNodeRegistryKey& InKey, FDefaultNamedVertexNodeConstructorParams&&) const override;
|
|
|
|
|
virtual TUniquePtr<INode> CreateNode(const FNodeRegistryKey& InKey, FDefaultNamedVertexWithLiteralNodeConstructorParams&&) const override;
|
|
|
|
|
|
|
|
|
|
// Returns a list of possible nodes to use to convert from FromDataType to ToDataType.
|
|
|
|
|
// Returns an empty array if none are available.
|
|
|
|
|
virtual TArray<FConverterNodeInfo> GetPossibleConverterNodes(const FName& FromDataType, const FName& ToDataType) override;
|
|
|
|
|
|
2023-12-15 13:21:12 -05:00
|
|
|
// Register a graph from an IMetaSoundDocumentInterface
|
2024-04-24 10:36:28 -04:00
|
|
|
FGraphRegistryKey RegisterGraph(const TScriptInterface<IMetaSoundDocumentInterface>& InDocumentInterface);
|
2023-12-15 13:21:12 -05:00
|
|
|
|
|
|
|
|
// Unregister a graph
|
2024-04-24 10:36:28 -04:00
|
|
|
bool UnregisterGraph(const FGraphRegistryKey& InRegistryKey, const TScriptInterface<IMetaSoundDocumentInterface>& InDocumentInterface);
|
2023-12-15 13:21:12 -05:00
|
|
|
|
2022-08-10 14:18:10 -04:00
|
|
|
// Private implementation until hardened and used for template nodes other than reroutes.
|
2022-08-12 14:22:05 -04:00
|
|
|
FNodeRegistryKey RegisterNodeTemplate(TUniquePtr<Metasound::Frontend::INodeRegistryTemplateEntry>&& InEntry);
|
2022-08-10 14:18:10 -04:00
|
|
|
bool UnregisterNodeTemplate(const FNodeRegistryKey& InKey);
|
|
|
|
|
|
2022-05-09 09:50:28 -04:00
|
|
|
// Create a transaction stream for any newly transactions
|
|
|
|
|
TUniquePtr<FNodeRegistryTransactionStream> CreateTransactionStream();
|
|
|
|
|
|
|
|
|
|
private:
|
2023-12-15 13:21:12 -05:00
|
|
|
struct FActiveRegistrationTaskInfo
|
|
|
|
|
{
|
|
|
|
|
FNodeRegistryTransaction::ETransactionType TransactionType = FNodeRegistryTransaction::ETransactionType::NodeRegistration;
|
|
|
|
|
UE::Tasks::FTask Task;
|
|
|
|
|
FTopLevelAssetPath AssetPath;
|
|
|
|
|
};
|
|
|
|
|
|
2024-08-13 14:58:36 -04:00
|
|
|
void BuildAndRegisterGraphFromDocument(const FMetasoundFrontendDocument& InDocument, const FProxyDataCache& InProxyDataCache, FNodeClassInfo&& InNodeClassInfo);
|
2023-12-15 13:21:12 -05:00
|
|
|
|
|
|
|
|
void AddRegistrationTask(const FGraphRegistryKey& InKey, FActiveRegistrationTaskInfo&& TaskInfo);
|
|
|
|
|
void RemoveRegistrationTask(const FGraphRegistryKey& InKey, FNodeRegistryTransaction::ETransactionType TransactionType);
|
|
|
|
|
|
|
|
|
|
// Adds reference to document's owning UObject to internal ObjectReferencer,
|
|
|
|
|
// indicating async registration/unregistration task(s) are depending on it.
|
|
|
|
|
void AddDocumentReference(TScriptInterface<IMetaSoundDocumentInterface> DocumentInterface);
|
|
|
|
|
|
|
|
|
|
// Removes reference to document's owning UObject from internal ObjectReferencer,
|
|
|
|
|
// indicating async registration/unregistration task(s) are no longer depending on it.
|
|
|
|
|
void RemoveDocumentReference(TScriptInterface<IMetaSoundDocumentInterface> DocumentInterface);
|
|
|
|
|
|
|
|
|
|
bool UnregisterNodeInternal(const FNodeRegistryKey& InKey, FNodeClassInfo* OutClassInfo = nullptr);
|
|
|
|
|
FNodeRegistryKey RegisterNodeInternal(TUniquePtr<INodeRegistryEntry>&& InEntry);
|
2023-09-22 15:01:07 -04:00
|
|
|
|
2022-05-09 09:50:28 -04:00
|
|
|
static FRegistryContainerImpl* LazySingleton;
|
|
|
|
|
|
2023-12-15 13:21:12 -05:00
|
|
|
void WaitForAsyncRegistrationInternal(const FNodeRegistryKey& InRegistryKey, const FTopLevelAssetPath* InAssetPath) const;
|
2023-10-10 11:32:28 -04:00
|
|
|
|
2023-12-15 13:21:12 -05:00
|
|
|
void RegisterGraphInternal(const FGraphRegistryKey& InKey, TSharedPtr<const FGraph> InGraph);
|
|
|
|
|
bool UnregisterGraphInternal(const FGraphRegistryKey& InKey);
|
2023-10-10 11:32:28 -04:00
|
|
|
|
2023-10-19 17:47:21 -04:00
|
|
|
// Access a node entry safely. Node entries can be added/removed asynchronously. Functions passed to this method will be
|
|
|
|
|
// executed in a manner where access to the node registry entry is safe from threading issues.
|
|
|
|
|
//
|
|
|
|
|
// @returns true if a node registry entry was found and the function executed. False if the entry was not
|
|
|
|
|
// found and the function not executed.
|
|
|
|
|
bool AccessNodeEntryThreadSafe(const FNodeRegistryKey& InKey, TFunctionRef<void(const INodeRegistryEntry&)> InFunc) const;
|
2022-05-09 09:50:28 -04:00
|
|
|
|
2022-08-12 14:22:05 -04:00
|
|
|
const INodeRegistryTemplateEntry* FindNodeTemplateEntry(const FNodeRegistryKey& InKey) const;
|
2022-05-09 09:50:28 -04:00
|
|
|
|
2023-09-22 15:01:07 -04:00
|
|
|
|
2022-05-09 09:50:28 -04:00
|
|
|
// This buffer is used to enqueue nodes and datatypes to register when the module has been initialized,
|
|
|
|
|
// in order to avoid bad behavior with ensures, logs, etc. on static initialization.
|
|
|
|
|
// The bad news is that TInlineAllocator is the safest allocator to use on static init.
|
|
|
|
|
// The good news is that none of these lambdas typically have captures, so this should have low memory overhead.
|
|
|
|
|
static constexpr int32 MaxNumNodesAndDatatypesToInitialize = 2048;
|
|
|
|
|
TArray<TUniqueFunction<void()>, TInlineAllocator<MaxNumNodesAndDatatypesToInitialize>> LazyInitCommands;
|
|
|
|
|
|
|
|
|
|
FCriticalSection LazyInitCommandCritSection;
|
|
|
|
|
|
|
|
|
|
// Registry in which we keep all information about nodes implemented in C++.
|
2023-10-10 11:32:28 -04:00
|
|
|
TMultiMap<FNodeRegistryKey, TSharedRef<INodeRegistryEntry, ESPMode::ThreadSafe>> RegisteredNodes;
|
2022-05-09 09:50:28 -04:00
|
|
|
|
2022-08-10 14:18:10 -04:00
|
|
|
// Registry in which we keep all information about dynamically-generated templated nodes via in C++.
|
2022-08-12 14:22:05 -04:00
|
|
|
TMap<FNodeRegistryKey, TSharedRef<INodeRegistryTemplateEntry, ESPMode::ThreadSafe>> RegisteredNodeTemplates;
|
2022-08-10 14:18:10 -04:00
|
|
|
|
2023-10-10 11:32:28 -04:00
|
|
|
// Map of all registered graphs
|
|
|
|
|
TMap<FGraphRegistryKey, TSharedPtr<const FGraph>> RegisteredGraphs;
|
2023-09-22 15:01:07 -04:00
|
|
|
|
2022-05-09 09:50:28 -04:00
|
|
|
// Registry in which we keep lists of possible nodes to use to convert between two datatypes
|
|
|
|
|
TMap<FConverterNodeRegistryKey, FConverterNodeRegistryValue> ConverterNodeRegistry;
|
|
|
|
|
|
|
|
|
|
TSharedRef<FNodeRegistryTransactionBuffer> TransactionBuffer;
|
2023-09-22 15:01:07 -04:00
|
|
|
|
|
|
|
|
mutable FCriticalSection RegistryMapsCriticalSection;
|
|
|
|
|
mutable FCriticalSection ActiveRegistrationTasksCriticalSection;
|
2023-12-15 13:21:12 -05:00
|
|
|
mutable FCriticalSection ObjectReferencerCriticalSection;
|
|
|
|
|
|
2023-09-22 15:01:07 -04:00
|
|
|
UE::Tasks::FPipe AsyncRegistrationPipe;
|
2023-12-15 13:21:12 -05:00
|
|
|
TMap<FNodeRegistryKey, TArray<FActiveRegistrationTaskInfo>> ActiveRegistrationTasks;
|
2023-09-22 15:01:07 -04:00
|
|
|
TUniquePtr<FMetasoundFrontendRegistryContainer::IObjectReferencer> ObjectReferencer;
|
2022-05-09 09:50:28 -04:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|