#include #include "Debug/Logger.h" #include "Rendering/Pipelines/Internal/BuiltinForwardSceneSetup.h" #include #include #include #include #include #include #include namespace XCEngine { namespace Rendering { namespace Pipelines { struct BuiltinForwardSceneRecorderState { bool initialized = false; }; namespace { bool ScenePhaseSamplesMainDirectionalShadow(ScenePhase scenePhase) { return scenePhase == ScenePhase::Opaque || scenePhase == ScenePhase::Transparent; } } // namespace BuiltinForwardSceneRecorder::BuiltinForwardSceneRecorder( BuiltinForwardPipeline& pipeline, const RenderPipelineStageRenderGraphContext& context) : m_pipeline(pipeline) , m_context(context) , m_graphManagedSurface( BuildRenderGraphManagedSurfaceTemplate(context.surfaceTemplate)) , m_state(std::make_shared()) { const CameraFrameRenderGraphResources* const frameResources = TryGetCameraFrameRenderGraphResources(context.blackboard); if (frameResources != nullptr) { m_mainDirectionalShadowTexture = frameResources->mainDirectionalShadow; } } BuiltinForwardSceneRecorder::~BuiltinForwardSceneRecorder() = default; SceneRenderFeaturePassBeginCallback BuiltinForwardSceneRecorder::BuildBeginRecordedPassCallback( bool* executionSucceeded) const { BuiltinForwardPipeline& pipeline = m_pipeline; const std::shared_ptr state = m_state; return [&pipeline, state, executionSucceeded]( const RenderPassContext& passContext, bool clearAttachments) -> bool { if (executionSucceeded != nullptr && !(*executionSucceeded)) { return false; } if (!state->initialized) { if (!pipeline.Initialize(passContext.renderContext)) { Debug::Logger::Get().Error( Debug::LogCategory::Rendering, "BuiltinForwardSceneRecorder failed during execution: Initialize returned false"); if (executionSucceeded != nullptr) { *executionSucceeded = false; } return false; } const FrameExecutionContext executionContext( passContext.renderContext, passContext.surface, passContext.sceneData, passContext.sourceSurface, passContext.sourceColorView, passContext.sourceColorState); if (!pipeline.m_forwardSceneFeatureHost.Prepare(executionContext)) { Debug::Logger::Get().Error( Debug::LogCategory::Rendering, "BuiltinForwardSceneRecorder failed during execution: SceneRenderFeatureHost::Prepare returned false"); if (executionSucceeded != nullptr) { *executionSucceeded = false; } return false; } state->initialized = true; } if (!pipeline.BeginForwardScenePass( passContext, clearAttachments)) { Debug::Logger::Get().Error( Debug::LogCategory::Rendering, "BuiltinForwardSceneRecorder failed during execution: BeginForwardScenePass returned false"); if (executionSucceeded != nullptr) { *executionSucceeded = false; } return false; } return true; }; } SceneRenderFeaturePassEndCallback BuiltinForwardSceneRecorder::BuildEndRecordedPassCallback() const { BuiltinForwardPipeline& pipeline = m_pipeline; return [&pipeline](const RenderPassContext& passContext) { pipeline.EndForwardScenePass(passContext); }; } bool BuiltinForwardSceneRecorder::RecordDefaultScene() { if (m_context.stage != CameraFrameStage::MainScene) { return false; } for (const Internal::ForwardSceneStep& step : Internal::GetBuiltinForwardSceneSteps()) { if (step.type == Internal::ForwardSceneStepType::InjectionPoint) { if (!RecordInjectionPoint(step.injectionPoint)) { return false; } continue; } if (!RecordScenePhase(step.scenePhase)) { return false; } } return true; } bool BuiltinForwardSceneRecorder::RecordScenePhase( ScenePhase scenePhase) { if (m_context.stage != CameraFrameStage::MainScene) { return false; } const RenderPipelineStageRenderGraphContext graphContext = BuildGraphContext(); const bool clearAttachments = m_clearAttachments; const SceneRenderFeaturePassBeginCallback beginRecordedPass = BuildBeginRecordedPassCallback(graphContext.executionSucceeded); const SceneRenderFeaturePassEndCallback endRecordedPass = BuildEndRecordedPassCallback(); const RenderPassGraphBeginCallback beginPhasePass = [beginRecordedPass, clearAttachments]( const RenderPassContext& passContext) { return beginRecordedPass( passContext, clearAttachments); }; const std::vector additionalReadTextures = ScenePhaseSamplesMainDirectionalShadow(scenePhase) && m_mainDirectionalShadowTexture.IsValid() ? std::vector{ m_mainDirectionalShadowTexture } : std::vector{}; if (!::XCEngine::Rendering::RecordRenderPipelineStagePhasePass( graphContext, scenePhase, [&pipeline = m_pipeline, scenePhase]( const RenderPassContext& passContext) { const FrameExecutionContext executionContext( passContext.renderContext, passContext.surface, passContext.sceneData, passContext.sourceSurface, passContext.sourceColorView, passContext.sourceColorState); const ScenePhaseExecutionContext scenePhaseExecutionContext = pipeline.BuildScenePhaseExecutionContext( executionContext, scenePhase); return pipeline.ExecuteBuiltinScenePhase( scenePhaseExecutionContext); }, beginPhasePass, endRecordedPass, additionalReadTextures)) { return false; } m_clearAttachments = false; return true; } bool BuiltinForwardSceneRecorder::RecordInjectionPoint( SceneRenderInjectionPoint injectionPoint) { if (m_context.stage != CameraFrameStage::MainScene) { return false; } const RenderPipelineStageRenderGraphContext graphContext = BuildGraphContext(); const SceneRenderFeaturePassBeginCallback beginRecordedPass = BuildBeginRecordedPassCallback(graphContext.executionSucceeded); const SceneRenderFeaturePassEndCallback endRecordedPass = BuildEndRecordedPassCallback(); bool recordedAnyPass = false; if (!::XCEngine::Rendering::RecordRenderPipelineStageFeaturePasses( graphContext, m_pipeline.m_forwardSceneFeatureHost, injectionPoint, m_clearAttachments, beginRecordedPass, endRecordedPass, &recordedAnyPass)) { return false; } if (recordedAnyPass) { m_clearAttachments = false; } return true; } RenderPipelineStageRenderGraphContext BuiltinForwardSceneRecorder::BuildGraphContext() const { const RenderGraphRecordingContext baseRecordingContext = BuildRenderGraphRecordingContext(m_context); RenderGraphRecordingContextBuildParams recordingParams = {}; recordingParams.surface = &m_graphManagedSurface; recordingParams.overrideSourceBinding = true; recordingParams.sourceBinding = BuildRenderGraphRecordingSourceBinding(baseRecordingContext); const RenderGraphRecordingContext recordingContext = BuildRenderGraphRecordingContext( baseRecordingContext, std::move(recordingParams)); return BuildRenderPipelineStageRenderGraphContext( recordingContext, m_context.stage); } } // namespace Pipelines } // namespace Rendering } // namespace XCEngine