diff --git a/engine/src/Rendering/Execution/CameraRenderer.cpp b/engine/src/Rendering/Execution/CameraRenderer.cpp index cf4491e1..e1331cec 100644 --- a/engine/src/Rendering/Execution/CameraRenderer.cpp +++ b/engine/src/Rendering/Execution/CameraRenderer.cpp @@ -839,6 +839,353 @@ bool RecordFullscreenPassSequenceStage( return true; } +struct CameraFrameStageGraphBuildState { + CameraFrameStage stage = CameraFrameStage::MainScene; + Containers::String stageName = {}; + RenderPassSequence* stageSequence = nullptr; + RenderSurface surfaceTemplate = {}; + bool hasSourceSurface = false; + RenderSurface sourceSurfaceTemplate = {}; + RHI::RHIResourceView* sourceColorView = nullptr; + RHI::ResourceStates sourceColorState = RHI::ResourceStates::Common; + RenderGraphImportedSurface sourceSurface = {}; + RenderGraphImportedSurface outputSurface = {}; + RenderGraphTextureHandle outputColor = {}; +}; + +RenderPassContext BuildCameraFrameStageGraphPassContext( + const CameraFramePlan& plan, + const CameraFrameStageGraphBuildState& stageState, + const RenderSceneData& sceneData) { + return { + plan.request.context, + stageState.surfaceTemplate, + sceneData, + stageState.hasSourceSurface + ? &stageState.sourceSurfaceTemplate + : nullptr, + stageState.sourceColorView, + stageState.sourceColorState + }; +} + +CameraFrameStageGraphBuildState BuildCameraFrameStageGraphBuildState( + CameraFrameStage stage, + const CameraFramePlan& plan, + const DirectionalShadowExecutionState& shadowState, + const RenderSceneData& sceneData, + RenderGraphBuilder& graphBuilder, + RenderGraphImportedTextureRegistry& importedTextures) { + CameraFrameStageGraphBuildState stageState = {}; + stageState.stage = stage; + stageState.stageName = Containers::String(GetCameraFrameStageName(stage)); + stageState.stageSequence = plan.GetPassSequence(stage); + + const RenderPassContext stagePassContext = + BuildFrameStagePassContext(stage, plan, shadowState, sceneData); + stageState.surfaceTemplate = stagePassContext.surface; + stageState.hasSourceSurface = stagePassContext.sourceSurface != nullptr; + if (stageState.hasSourceSurface) { + stageState.sourceSurfaceTemplate = *stagePassContext.sourceSurface; + } + stageState.sourceColorView = stagePassContext.sourceColorView; + stageState.sourceColorState = stagePassContext.sourceColorState; + stageState.sourceSurface = + ImportRenderGraphSurface( + graphBuilder, + importedTextures, + stageState.stageName + ".Source", + stagePassContext.sourceSurface, + RenderGraphSurfaceImportUsage::Source, + IsCameraFrameFullscreenSequenceStage(stage)); + stageState.outputSurface = + ImportRenderGraphSurface( + graphBuilder, + importedTextures, + stageState.stageName + ".Output", + &stagePassContext.surface, + RenderGraphSurfaceImportUsage::Output, + DoesCameraFrameStageGraphOwnColorTransitions(stage), + DoesCameraFrameStageGraphOwnDepthTransitions(stage)); + stageState.outputColor = + ResolveStageOutputColorHandle( + stage, + plan, + stageState.stageName, + stagePassContext, + stageState.outputSurface, + graphBuilder); + return stageState; +} + +void PublishCameraFrameStageGraphBuildState( + const CameraFrameStageGraphBuildState& stageState, + const DirectionalShadowExecutionState& shadowState, + CameraFrameRenderGraphResources& frameResources) { + if (stageState.stage == CameraFrameStage::ShadowCaster && + shadowState.HasShadowSampling() && + stageState.outputSurface.depthTexture.IsValid()) { + frameResources.mainDirectionalShadow = stageState.outputSurface.depthTexture; + } + + WriteCameraFrameRenderGraphStageSurfaceResources( + frameResources, + stageState.stage, + stageState.outputColor, + stageState.outputSurface.depthTexture); +} + +bool TryRecordCameraFrameStageSequence( + const CameraFrameStageGraphBuildState& stageState, + const CameraFramePlan& plan, + const RenderSceneData& sceneData, + CameraFrameExecutionState& executionState, + RenderGraphBuilder& graphBuilder, + RenderGraphBlackboard& blackboard, + bool& stageExecutionSucceeded, + bool& handled) { + if (stageState.stageSequence == nullptr) { + handled = false; + return true; + } + + handled = true; + const RenderPassContext stagePassContext = + BuildCameraFrameStageGraphPassContext(plan, stageState, sceneData); + const bool recordResult = + IsCameraFrameFullscreenSequenceStage(stageState.stage) + ? RecordFullscreenPassSequenceStage( + stageState.stage, + stageState.stageName, + stagePassContext, + ResolveCameraFrameFullscreenStageGraphSourceBinding( + plan, + stageState.stage, + stageState.surfaceTemplate, + stagePassContext.sourceSurface, + stagePassContext.sourceColorView, + stagePassContext.sourceColorState, + GetPrimaryColorTexture(stageState.sourceSurface), + &blackboard), + stageState.outputColor, + sceneData, + stageState.stageSequence, + executionState, + graphBuilder, + blackboard, + stageExecutionSucceeded) + : RecordRegularPassSequenceStage( + stageState.stage, + stageState.stageName, + stagePassContext, + stageState.outputSurface, + sceneData, + stageState.stageSequence, + executionState, + graphBuilder, + blackboard, + stageExecutionSucceeded); + if (!recordResult) { + Debug::Logger::Get().Error( + Debug::LogCategory::Rendering, + Containers::String("CameraRenderer::Render failed: pass-sequence graph recording returned false for ") + + stageState.stageName); + return false; + } + + return true; +} + +bool TryRecordCameraFrameStageStandaloneRenderGraphPass( + const CameraFrameStageGraphBuildState& stageState, + const CameraFramePlan& plan, + const DirectionalShadowExecutionState& shadowState, + const RenderSceneData& sceneData, + CameraFrameExecutionState& executionState, + RenderGraphBuilder& graphBuilder, + RenderGraphBlackboard& blackboard, + bool& stageExecutionSucceeded, + bool& handled) { + RenderPass* const standaloneStagePass = + ResolveStandaloneStagePass(stageState.stage, executionState); + if (standaloneStagePass == nullptr || + !standaloneStagePass->SupportsRenderGraph()) { + handled = false; + return true; + } + + handled = true; + const RenderSceneData stageSceneData = + BuildStandaloneStageSceneData( + stageState.stage, + plan, + shadowState, + sceneData, + stageState.surfaceTemplate); + const RenderPassGraphBeginCallback beginStandalonePass = + [&, standaloneStagePass](const RenderPassContext&) -> bool { + if (!InitializeStandalonePass( + standaloneStagePass, + plan.request.context)) { + stageExecutionSucceeded = false; + return false; + } + + return true; + }; + const RenderPassRenderGraphContext standalonePassContext = { + graphBuilder, + stageState.stageName, + plan.request.context, + stageSceneData, + stageState.surfaceTemplate, + stageState.hasSourceSurface + ? &stageState.sourceSurfaceTemplate + : nullptr, + stageState.sourceColorView, + stageState.sourceColorState, + GetPrimaryColorTexture(stageState.sourceSurface), + std::vector{ stageState.outputColor }, + stageState.outputSurface.depthTexture, + &stageExecutionSucceeded, + beginStandalonePass, + {}, + &blackboard + }; + if (!standaloneStagePass->RecordRenderGraph(standalonePassContext)) { + Debug::Logger::Get().Error( + Debug::LogCategory::Rendering, + Containers::String("CameraRenderer::Render failed: RenderPass::RecordRenderGraph returned false for ") + + stageState.stageName); + return false; + } + + return true; +} + +bool TryRecordCameraFrameMainSceneGraphPass( + const CameraFrameStageGraphBuildState& stageState, + const CameraFramePlan& plan, + const RenderSceneData& sceneData, + CameraFrameExecutionState& executionState, + RenderGraphBuilder& graphBuilder, + RenderGraphBlackboard& blackboard, + bool& stageExecutionSucceeded, + bool& handled) { + if (stageState.stage != CameraFrameStage::MainScene || + executionState.pipeline == nullptr || + !executionState.pipeline->SupportsMainSceneRenderGraph()) { + handled = false; + return true; + } + + handled = true; + const RenderPipelineMainSceneRenderGraphContext mainSceneContext = { + graphBuilder, + stageState.stageName, + plan.request.context, + sceneData, + stageState.surfaceTemplate, + stageState.hasSourceSurface + ? &stageState.sourceSurfaceTemplate + : nullptr, + stageState.sourceColorView, + stageState.sourceColorState, + std::vector{ stageState.outputColor }, + stageState.outputSurface.depthTexture, + &stageExecutionSucceeded, + &blackboard + }; + if (!executionState.pipeline->RecordMainSceneRenderGraph(mainSceneContext)) { + Debug::Logger::Get().Error( + Debug::LogCategory::Rendering, + "CameraRenderer::Render failed: RenderPipeline::RecordMainSceneRenderGraph returned false"); + return false; + } + + return true; +} + +void AddCameraFrameStageFallbackRasterPass( + const CameraFrameStageGraphBuildState& stageState, + const CameraFramePlan& plan, + const DirectionalShadowExecutionState& shadowState, + const RenderSceneData& sceneData, + CameraFrameExecutionState& executionState, + RenderGraphBuilder& graphBuilder, + bool& stageExecutionSucceeded) { + const CameraFrameStageGraphBuildState capturedStageState = stageState; + graphBuilder.AddRasterPass( + capturedStageState.stageName, + [&, capturedStageState](RenderGraphPassBuilder& passBuilder) { + if (IsCameraFrameFullscreenSequenceStage(capturedStageState.stage)) { + ReadRenderGraphColorSurface(passBuilder, capturedStageState.sourceSurface); + WriteRenderGraphColorSurface(passBuilder, capturedStageState.outputSurface); + } else { + ReadRenderGraphSurface(passBuilder, capturedStageState.sourceSurface); + WriteRenderGraphSurface(passBuilder, capturedStageState.outputSurface); + } + passBuilder.SetExecuteCallback( + [&, capturedStageState]( + const RenderGraphExecutionContext& executionContext) { + if (!stageExecutionSucceeded) { + return; + } + + const RenderSurface* resolvedSourceSurface = + capturedStageState.hasSourceSurface + ? &capturedStageState.sourceSurfaceTemplate + : nullptr; + RHI::RHIResourceView* resolvedSourceColorView = + capturedStageState.sourceColorView; + RHI::ResourceStates resolvedSourceColorState = + capturedStageState.sourceColorState; + RenderSurface graphManagedSourceSurface = {}; + if (IsCameraFrameFullscreenSequenceStage(capturedStageState.stage) && + capturedStageState.hasSourceSurface && + CanUseGraphManagedImportedSurface( + capturedStageState.sourceSurface, + executionContext)) { + graphManagedSourceSurface = + BuildGraphManagedImportedSurface( + capturedStageState.sourceSurfaceTemplate, + RHI::ResourceStates::PixelShaderResource, + RHI::ResourceStates::PixelShaderResource); + resolvedSourceSurface = &graphManagedSourceSurface; + resolvedSourceColorState = RHI::ResourceStates::PixelShaderResource; + } + + const RenderSurface* resolvedOutputSurface = + &capturedStageState.surfaceTemplate; + RenderSurface graphManagedOutputSurface = {}; + if (CanUseGraphManagedImportedSurface( + capturedStageState.outputSurface, + executionContext)) { + graphManagedOutputSurface = + BuildGraphManagedPassSurface( + capturedStageState.surfaceTemplate); + resolvedOutputSurface = &graphManagedOutputSurface; + } + + const RenderPassContext passContextOverride = { + plan.request.context, + *resolvedOutputSurface, + sceneData, + resolvedSourceSurface, + resolvedSourceColorView, + resolvedSourceColorState + }; + stageExecutionSucceeded = ExecuteRecordedFrameStage( + capturedStageState.stage, + plan, + shadowState, + sceneData, + executionState, + passContextOverride); + }); + }); +} + bool ExecuteRenderGraphPlan( const CameraFramePlan& plan, const DirectionalShadowExecutionState& shadowState, @@ -858,239 +1205,74 @@ bool ExecuteRenderGraphPlan( continue; } - const CameraFrameStage stage = stageInfo.stage; - const Containers::String stageName(GetCameraFrameStageName(stageInfo.stage)); - RenderPassSequence* const stageSequence = plan.GetPassSequence(stage); - - const RenderPassContext stagePassContext = - BuildFrameStagePassContext(stage, plan, shadowState, sceneData); - const RenderGraphImportedSurface sourceSurface = - ImportRenderGraphSurface( - graphBuilder, - importedTextures, - stageName + ".Source", - stagePassContext.sourceSurface, - RenderGraphSurfaceImportUsage::Source, - IsCameraFrameFullscreenSequenceStage(stage)); - const RenderGraphImportedSurface outputSurface = - ImportRenderGraphSurface( - graphBuilder, - importedTextures, - stageName + ".Output", - &stagePassContext.surface, - RenderGraphSurfaceImportUsage::Output, - DoesCameraFrameStageGraphOwnColorTransitions(stage), - DoesCameraFrameStageGraphOwnDepthTransitions(stage)); - const RenderGraphTextureHandle stageOutputColor = - ResolveStageOutputColorHandle( - stage, + const CameraFrameStageGraphBuildState stageState = + BuildCameraFrameStageGraphBuildState( + stageInfo.stage, plan, - stageName, - stagePassContext, - outputSurface, - graphBuilder); - if (stage == CameraFrameStage::ShadowCaster && - shadowState.HasShadowSampling() && - outputSurface.depthTexture.IsValid()) { - frameResources.mainDirectionalShadow = outputSurface.depthTexture; - } - WriteCameraFrameRenderGraphStageSurfaceResources( - frameResources, - stage, - stageOutputColor, - outputSurface.depthTexture); - const RenderSurface stageSurfaceTemplate = stagePassContext.surface; - const bool hasStageSourceSurface = stagePassContext.sourceSurface != nullptr; - const RenderSurface stageSourceSurfaceTemplate = - hasStageSourceSurface - ? *stagePassContext.sourceSurface - : RenderSurface(); - const RHI::RHIResourceView* const stageSourceColorView = stagePassContext.sourceColorView; - const RHI::ResourceStates stageSourceColorState = stagePassContext.sourceColorState; - - if (stageSequence != nullptr) { - const bool recordResult = - IsCameraFrameFullscreenSequenceStage(stage) - ? RecordFullscreenPassSequenceStage( - stage, - stageName, - stagePassContext, - ResolveCameraFrameFullscreenStageGraphSourceBinding( - plan, - stage, - stagePassContext.surface, - stagePassContext.sourceSurface, - stagePassContext.sourceColorView, - stagePassContext.sourceColorState, - GetPrimaryColorTexture(sourceSurface), - &blackboard), - stageOutputColor, - sceneData, - stageSequence, - executionState, - graphBuilder, - blackboard, - stageExecutionSucceeded) - : RecordRegularPassSequenceStage( - stage, - stageName, - stagePassContext, - outputSurface, - sceneData, - stageSequence, - executionState, - graphBuilder, - blackboard, - stageExecutionSucceeded); - if (!recordResult) { - Debug::Logger::Get().Error( - Debug::LogCategory::Rendering, - Containers::String("CameraRenderer::Render failed: pass-sequence graph recording returned false for ") + - stageName); - return false; - } - - continue; - } - - RenderPass* const standaloneStagePass = - ResolveStandaloneStagePass(stage, executionState); - if (standaloneStagePass != nullptr && - standaloneStagePass->SupportsRenderGraph()) { - const RenderSceneData stageSceneData = - BuildStandaloneStageSceneData( - stage, - plan, - shadowState, - sceneData, - stageSurfaceTemplate); - const RenderPassGraphBeginCallback beginStandalonePass = - [&, standaloneStagePass](const RenderPassContext&) -> bool { - if (!InitializeStandalonePass( - standaloneStagePass, - plan.request.context)) { - stageExecutionSucceeded = false; - return false; - } - - return true; - }; - const RenderPassRenderGraphContext standalonePassContext = { - graphBuilder, - stageName, - plan.request.context, - stageSceneData, - stageSurfaceTemplate, - hasStageSourceSurface ? &stageSourceSurfaceTemplate : nullptr, - const_cast(stageSourceColorView), - stageSourceColorState, - GetPrimaryColorTexture(sourceSurface), - std::vector{ stageOutputColor }, - outputSurface.depthTexture, - &stageExecutionSucceeded, - beginStandalonePass, - {}, - &blackboard - }; - if (!standaloneStagePass->RecordRenderGraph(standalonePassContext)) { - Debug::Logger::Get().Error( - Debug::LogCategory::Rendering, - Containers::String("CameraRenderer::Render failed: RenderPass::RecordRenderGraph returned false for ") + - stageName); - return false; - } - continue; - } - - if (stage == CameraFrameStage::MainScene && - executionState.pipeline != nullptr && - executionState.pipeline->SupportsMainSceneRenderGraph()) { - const RenderPipelineMainSceneRenderGraphContext mainSceneContext = { - graphBuilder, - stageName, - plan.request.context, + shadowState, sceneData, - stageSurfaceTemplate, - hasStageSourceSurface ? &stageSourceSurfaceTemplate : nullptr, - const_cast(stageSourceColorView), - stageSourceColorState, - std::vector{ stageOutputColor }, - outputSurface.depthTexture, - &stageExecutionSucceeded, - &blackboard - }; - if (!executionState.pipeline->RecordMainSceneRenderGraph(mainSceneContext)) { - Debug::Logger::Get().Error( - Debug::LogCategory::Rendering, - "CameraRenderer::Render failed: RenderPipeline::RecordMainSceneRenderGraph returned false"); - return false; - } + graphBuilder, + importedTextures); + PublishCameraFrameStageGraphBuildState( + stageState, + shadowState, + frameResources); + + bool stageHandled = false; + if (!TryRecordCameraFrameStageSequence( + stageState, + plan, + sceneData, + executionState, + graphBuilder, + blackboard, + stageExecutionSucceeded, + stageHandled)) { + return false; + } + if (stageHandled) { continue; } - graphBuilder.AddRasterPass( - stageName, - [&, sourceSurface, outputSurface, stage, stageSurfaceTemplate, hasStageSourceSurface, stageSourceSurfaceTemplate, stageSourceColorView, stageSourceColorState]( - RenderGraphPassBuilder& passBuilder) { - if (IsCameraFrameFullscreenSequenceStage(stage)) { - ReadRenderGraphColorSurface(passBuilder, sourceSurface); - WriteRenderGraphColorSurface(passBuilder, outputSurface); - } else { - ReadRenderGraphSurface(passBuilder, sourceSurface); - WriteRenderGraphSurface(passBuilder, outputSurface); - } - passBuilder.SetExecuteCallback( - [&, stage, sourceSurface, outputSurface, stageSurfaceTemplate, hasStageSourceSurface, stageSourceSurfaceTemplate, stageSourceColorView, stageSourceColorState]( - const RenderGraphExecutionContext& executionContext) { - if (!stageExecutionSucceeded) { - return; - } + if (!TryRecordCameraFrameStageStandaloneRenderGraphPass( + stageState, + plan, + shadowState, + sceneData, + executionState, + graphBuilder, + blackboard, + stageExecutionSucceeded, + stageHandled)) { + return false; + } + if (stageHandled) { + continue; + } - const RenderSurface* resolvedSourceSurface = - hasStageSourceSurface - ? &stageSourceSurfaceTemplate - : nullptr; - RHI::RHIResourceView* resolvedSourceColorView = - const_cast(stageSourceColorView); - RHI::ResourceStates resolvedSourceColorState = stageSourceColorState; - RenderSurface graphManagedSourceSurface = {}; - if (IsCameraFrameFullscreenSequenceStage(stage) && - hasStageSourceSurface && - CanUseGraphManagedImportedSurface(sourceSurface, executionContext)) { - graphManagedSourceSurface = - BuildGraphManagedImportedSurface( - stageSourceSurfaceTemplate, - RHI::ResourceStates::PixelShaderResource, - RHI::ResourceStates::PixelShaderResource); - resolvedSourceSurface = &graphManagedSourceSurface; - resolvedSourceColorState = RHI::ResourceStates::PixelShaderResource; - } + if (!TryRecordCameraFrameMainSceneGraphPass( + stageState, + plan, + sceneData, + executionState, + graphBuilder, + blackboard, + stageExecutionSucceeded, + stageHandled)) { + return false; + } + if (stageHandled) { + continue; + } - const RenderSurface* resolvedOutputSurface = &stageSurfaceTemplate; - RenderSurface graphManagedOutputSurface = {}; - if (CanUseGraphManagedImportedSurface(outputSurface, executionContext)) { - graphManagedOutputSurface = - BuildGraphManagedPassSurface(stageSurfaceTemplate); - resolvedOutputSurface = &graphManagedOutputSurface; - } - - const RenderPassContext passContextOverride = { - plan.request.context, - *resolvedOutputSurface, - sceneData, - resolvedSourceSurface, - resolvedSourceColorView, - resolvedSourceColorState - }; - stageExecutionSucceeded = ExecuteRecordedFrameStage( - stage, - plan, - shadowState, - sceneData, - executionState, - passContextOverride); - }); - }); + AddCameraFrameStageFallbackRasterPass( + stageState, + plan, + shadowState, + sceneData, + executionState, + graphBuilder, + stageExecutionSucceeded); } CompiledRenderGraph compiledGraph = {};