#include "Rendering/Internal/RenderPipelineFactory.h" #include "Rendering/Pipelines/BuiltinForwardPipeline.h" #include "Rendering/Pipelines/ManagedScriptableRenderPipelineAsset.h" #include "Rendering/Pipelines/ScriptableRenderPipelineHost.h" #include #include #include namespace XCEngine { namespace Rendering { namespace Internal { namespace { std::shared_ptr CreateBuiltinForwardPipelineRendererAsset() { static const std::shared_ptr s_builtinForwardPipelineAsset = std::make_shared(); return s_builtinForwardPipelineAsset; } using PipelineRendererAssetRegistry = std::unordered_map; PipelineRendererAssetRegistry& GetPipelineRendererAssetRegistry() { static PipelineRendererAssetRegistry registry = {}; return registry; } std::unordered_set& GetBuiltinPipelineRendererAssetKeys() { static std::unordered_set builtinKeys = {}; return builtinKeys; } std::mutex& GetPipelineRendererAssetRegistryMutex() { static std::mutex mutex; return mutex; } void EnsureBuiltinPipelineRendererAssetRegistryInitialized() { static const bool initialized = []() { PipelineRendererAssetRegistry& registry = GetPipelineRendererAssetRegistry(); registry.emplace( "BuiltinForward", &CreateBuiltinForwardPipelineRendererAsset); GetBuiltinPipelineRendererAssetKeys().insert("BuiltinForward"); return true; }(); (void)initialized; } std::unique_ptr TryCreateNativeSceneRendererFromAsset( const std::shared_ptr& asset) { if (asset == nullptr) { return nullptr; } std::unique_ptr pipeline = asset->CreatePipeline(); if (pipeline == nullptr) { return nullptr; } NativeSceneRenderer* const sceneRenderer = dynamic_cast(pipeline.get()); if (sceneRenderer == nullptr) { return nullptr; } (void)pipeline.release(); return std::unique_ptr(sceneRenderer); } } // namespace std::shared_ptr CreateConfiguredRenderPipelineAsset() { return Pipelines::CreateConfiguredManagedRenderPipelineAsset(); } std::shared_ptr CreateFallbackRenderPipelineAsset() { return std::make_shared(); } bool RegisterPipelineRendererAssetFactory( const std::string& key, PipelineRendererAssetFactory factory) { if (key.empty() || !factory) { return false; } EnsureBuiltinPipelineRendererAssetRegistryInitialized(); std::lock_guard lock( GetPipelineRendererAssetRegistryMutex()); PipelineRendererAssetRegistry& registry = GetPipelineRendererAssetRegistry(); if (registry.find(key) != registry.end()) { return false; } registry.emplace(key, std::move(factory)); return true; } bool UnregisterPipelineRendererAssetFactory(const std::string& key) { if (key.empty()) { return false; } EnsureBuiltinPipelineRendererAssetRegistryInitialized(); std::lock_guard lock( GetPipelineRendererAssetRegistryMutex()); if (GetBuiltinPipelineRendererAssetKeys().find(key) != GetBuiltinPipelineRendererAssetKeys().end()) { return false; } PipelineRendererAssetRegistry& registry = GetPipelineRendererAssetRegistry(); return registry.erase(key) != 0u; } std::shared_ptr CreatePipelineRendererAssetByKey( const std::string& key) { if (key.empty()) { return nullptr; } EnsureBuiltinPipelineRendererAssetRegistryInitialized(); std::lock_guard lock( GetPipelineRendererAssetRegistryMutex()); const PipelineRendererAssetRegistry& registry = GetPipelineRendererAssetRegistry(); const auto it = registry.find(key); if (it == registry.end() || !it->second) { return nullptr; } return it->second(); } std::shared_ptr ResolveRenderPipelineAssetOrDefault( std::shared_ptr preferredAsset) { if (preferredAsset != nullptr) { return std::move(preferredAsset); } if (std::shared_ptr configuredAsset = CreateConfiguredRenderPipelineAsset(); configuredAsset != nullptr) { return configuredAsset; } return CreateFallbackRenderPipelineAsset(); } std::unique_ptr CreateRenderPipelineOrDefault( const std::shared_ptr& preferredAsset, std::shared_ptr* outResolvedAsset) { const std::shared_ptr resolvedAsset = ResolveRenderPipelineAssetOrDefault(preferredAsset); if (resolvedAsset != nullptr) { if (std::unique_ptr pipeline = resolvedAsset->CreatePipeline()) { if (outResolvedAsset != nullptr) { *outResolvedAsset = resolvedAsset; } return pipeline; } } const std::shared_ptr defaultAsset = ResolveRenderPipelineAssetOrDefault(nullptr); if (defaultAsset != nullptr && defaultAsset != resolvedAsset) { if (std::unique_ptr pipeline = defaultAsset->CreatePipeline()) { if (outResolvedAsset != nullptr) { *outResolvedAsset = defaultAsset; } return pipeline; } } const std::shared_ptr fallbackAsset = CreateFallbackRenderPipelineAsset(); if (fallbackAsset != nullptr && fallbackAsset != resolvedAsset && fallbackAsset != defaultAsset) { if (std::unique_ptr pipeline = fallbackAsset->CreatePipeline()) { if (outResolvedAsset != nullptr) { *outResolvedAsset = fallbackAsset; } return pipeline; } } if (outResolvedAsset != nullptr) { *outResolvedAsset = fallbackAsset != nullptr ? fallbackAsset : (defaultAsset != nullptr ? defaultAsset : resolvedAsset); } return std::make_unique(); } std::unique_ptr CreateNativeSceneRendererFromAsset( const std::shared_ptr& preferredAsset, std::shared_ptr* outResolvedAsset) { if (std::unique_ptr sceneRenderer = TryCreateNativeSceneRendererFromAsset(preferredAsset)) { if (outResolvedAsset != nullptr) { *outResolvedAsset = preferredAsset; } return sceneRenderer; } if (outResolvedAsset != nullptr) { outResolvedAsset->reset(); } return CreateDefaultNativeSceneRenderer(); } std::unique_ptr CreateDefaultNativeSceneRenderer() { return std::make_unique(); } } // namespace Internal } // namespace Rendering } // namespace XCEngine