#include "Rendering/Pipelines/ScriptableRenderPipelineHost.h" #include "Rendering/Passes/BuiltinDepthOnlyPass.h" #include "Rendering/Passes/BuiltinObjectIdPass.h" #include "Rendering/Passes/BuiltinShadowCasterPass.h" #include "Rendering/Pipelines/BuiltinForwardPipeline.h" namespace XCEngine { namespace Rendering { namespace Pipelines { namespace { std::shared_ptr CreateDefaultPipelineRendererAsset() { static const std::shared_ptr s_defaultRendererAsset = std::make_shared(); return s_defaultRendererAsset; } std::unique_ptr CreatePipelineRendererFromAsset( const std::shared_ptr& pipelineRendererAsset) { const std::shared_ptr resolvedAsset = pipelineRendererAsset != nullptr ? pipelineRendererAsset : CreateDefaultPipelineRendererAsset(); if (resolvedAsset != nullptr) { if (std::unique_ptr pipeline = resolvedAsset->CreatePipeline()) { return pipeline; } } return std::make_unique(); } void InstallDefaultStandaloneStagePasses(RenderPipeline& pipeline) { pipeline.SetCameraFrameStandalonePass( CameraFrameStage::ObjectId, std::make_unique()); pipeline.SetCameraFrameStandalonePass( CameraFrameStage::DepthOnly, std::make_unique()); pipeline.SetCameraFrameStandalonePass( CameraFrameStage::ShadowCaster, std::make_unique()); } } // namespace ScriptableRenderPipelineHost::ScriptableRenderPipelineHost() : ScriptableRenderPipelineHost(CreateDefaultPipelineRendererAsset()) { } ScriptableRenderPipelineHost::ScriptableRenderPipelineHost( std::unique_ptr pipelineRenderer) { InstallDefaultStandaloneStagePasses(*this); ResetPipelineRenderer(std::move(pipelineRenderer)); } ScriptableRenderPipelineHost::ScriptableRenderPipelineHost( std::shared_ptr pipelineRendererAsset) : m_pipelineRendererAsset( pipelineRendererAsset != nullptr ? std::move(pipelineRendererAsset) : CreateDefaultPipelineRendererAsset()) { InstallDefaultStandaloneStagePasses(*this); ResetPipelineRenderer( CreatePipelineRendererFromAsset(m_pipelineRendererAsset)); } ScriptableRenderPipelineHost::~ScriptableRenderPipelineHost() { Shutdown(); } void ScriptableRenderPipelineHost::SetStageRecorder( std::unique_ptr stageRecorder) { ResetStageRecorder(std::move(stageRecorder)); } void ScriptableRenderPipelineHost::SetPipelineRenderer( std::unique_ptr pipelineRenderer) { m_pipelineRendererAsset.reset(); ResetPipelineRenderer(std::move(pipelineRenderer)); } void ScriptableRenderPipelineHost::SetPipelineRendererAsset( std::shared_ptr pipelineRendererAsset) { m_pipelineRendererAsset = pipelineRendererAsset != nullptr ? std::move(pipelineRendererAsset) : CreateDefaultPipelineRendererAsset(); ResetPipelineRenderer( CreatePipelineRendererFromAsset(m_pipelineRendererAsset)); } bool ScriptableRenderPipelineHost::Initialize(const RenderContext& context) { return EnsureInitialized(context); } void ScriptableRenderPipelineHost::Shutdown() { if (m_stageRecorder != nullptr) { m_stageRecorder->Shutdown(); } if (m_pipelineRenderer != nullptr) { m_pipelineRenderer->Shutdown(); } ShutdownCameraFrameStandalonePasses(); ResetInitializationState(); } bool ScriptableRenderPipelineHost::SupportsStageRenderGraph( CameraFrameStage stage) const { return (m_stageRecorder != nullptr && m_stageRecorder->SupportsStageRenderGraph(stage)) || (m_pipelineRenderer != nullptr && m_pipelineRenderer->SupportsStageRenderGraph(stage)); } bool ScriptableRenderPipelineHost::RecordStageRenderGraph( const RenderPipelineStageRenderGraphContext& context) { if (!EnsureInitialized(context.renderContext)) { return false; } if (m_stageRecorder != nullptr && m_stageRecorder->SupportsStageRenderGraph(context.stage)) { return m_stageRecorder->RecordStageRenderGraph(context); } return m_pipelineRenderer != nullptr && m_pipelineRenderer->RecordStageRenderGraph(context); } bool ScriptableRenderPipelineHost::Render( const FrameExecutionContext& executionContext) { if (!EnsureInitialized(executionContext.renderContext)) { return false; } return m_pipelineRenderer != nullptr && m_pipelineRenderer->Render(executionContext); } bool ScriptableRenderPipelineHost::Render( const RenderContext& context, const RenderSurface& surface, const RenderSceneData& sceneData) { if (!EnsureInitialized(context)) { return false; } return m_pipelineRenderer != nullptr && m_pipelineRenderer->Render(context, surface, sceneData); } bool ScriptableRenderPipelineHost::EnsureInitialized(const RenderContext& context) { if (!context.IsValid() || m_pipelineRenderer == nullptr) { return false; } const bool hasInitializationContext = m_initializedDevice != nullptr || m_pipelineRendererInitialized || m_stageRecorderInitialized; if (hasInitializationContext && (m_initializedDevice != context.device || m_initializedBackendType != context.backendType)) { ShutdownInitializedComponents(); } if (!m_pipelineRendererInitialized) { if (!m_pipelineRenderer->Initialize(context)) { m_pipelineRenderer->Shutdown(); ClearInitializationContextIfNoComponentsAreInitialized(); return false; } m_pipelineRendererInitialized = true; m_initializedDevice = context.device; m_initializedBackendType = context.backendType; } if (m_stageRecorder != nullptr && !m_stageRecorderInitialized) { if (!m_stageRecorder->Initialize(context)) { m_stageRecorder->Shutdown(); ShutdownInitializedComponents(); return false; } m_stageRecorderInitialized = true; m_initializedDevice = context.device; m_initializedBackendType = context.backendType; } return true; } void ScriptableRenderPipelineHost::ShutdownInitializedComponents() { if (m_stageRecorderInitialized && m_stageRecorder != nullptr) { m_stageRecorder->Shutdown(); } if (m_pipelineRendererInitialized && m_pipelineRenderer != nullptr) { m_pipelineRenderer->Shutdown(); } ResetInitializationState(); } void ScriptableRenderPipelineHost::ResetInitializationState() { m_initializedDevice = nullptr; m_initializedBackendType = RHI::RHIType::D3D12; m_pipelineRendererInitialized = false; m_stageRecorderInitialized = false; } void ScriptableRenderPipelineHost::ClearInitializationContextIfNoComponentsAreInitialized() { if (!m_pipelineRendererInitialized && !m_stageRecorderInitialized) { m_initializedDevice = nullptr; m_initializedBackendType = RHI::RHIType::D3D12; } } void ScriptableRenderPipelineHost::ResetStageRecorder( std::unique_ptr stageRecorder) { if (m_stageRecorder != nullptr) { m_stageRecorder->Shutdown(); } m_stageRecorder = std::move(stageRecorder); m_stageRecorderInitialized = false; ClearInitializationContextIfNoComponentsAreInitialized(); } void ScriptableRenderPipelineHost::ResetPipelineRenderer( std::unique_ptr pipelineRenderer) { if (m_pipelineRenderer != nullptr) { m_pipelineRenderer->Shutdown(); } m_pipelineRenderer = std::move(pipelineRenderer); if (m_pipelineRenderer == nullptr) { if (m_pipelineRendererAsset == nullptr) { m_pipelineRendererAsset = CreateDefaultPipelineRendererAsset(); } m_pipelineRenderer = CreatePipelineRendererFromAsset(m_pipelineRendererAsset); } m_pipelineRendererInitialized = false; ClearInitializationContextIfNoComponentsAreInitialized(); } ScriptableRenderPipelineHostAsset::ScriptableRenderPipelineHostAsset() : ScriptableRenderPipelineHostAsset(CreateDefaultPipelineRendererAsset()) { } ScriptableRenderPipelineHostAsset::ScriptableRenderPipelineHostAsset( std::shared_ptr pipelineRendererAsset) : m_pipelineRendererAsset( pipelineRendererAsset != nullptr ? std::move(pipelineRendererAsset) : CreateDefaultPipelineRendererAsset()) { } std::unique_ptr ScriptableRenderPipelineHostAsset::CreatePipeline() const { return std::make_unique( m_pipelineRendererAsset); } FinalColorSettings ScriptableRenderPipelineHostAsset::GetDefaultFinalColorSettings() const { return m_pipelineRendererAsset != nullptr ? m_pipelineRendererAsset->GetDefaultFinalColorSettings() : FinalColorSettings{}; } } // namespace Pipelines } // namespace Rendering } // namespace XCEngine