From a67f8597ba33b92e1a75eeca4147f5e0d0dd43e9 Mon Sep 17 00:00:00 2001 From: ssdfasd <2156608475@qq.com> Date: Tue, 14 Apr 2026 22:17:12 +0800 Subject: [PATCH] Extract camera frame render-graph stage policy helpers --- .../CameraFrameRenderGraphStagePolicy.h | 100 +++++++++++++ .../Rendering/Execution/CameraRenderer.cpp | 135 +++++------------- tests/Rendering/unit/CMakeLists.txt | 1 + ...camera_frame_render_graph_stage_policy.cpp | 124 ++++++++++++++++ 4 files changed, 257 insertions(+), 103 deletions(-) create mode 100644 engine/include/XCEngine/Rendering/Execution/CameraFrameRenderGraphStagePolicy.h create mode 100644 tests/Rendering/unit/test_camera_frame_render_graph_stage_policy.cpp diff --git a/engine/include/XCEngine/Rendering/Execution/CameraFrameRenderGraphStagePolicy.h b/engine/include/XCEngine/Rendering/Execution/CameraFrameRenderGraphStagePolicy.h new file mode 100644 index 00000000..6f758a7a --- /dev/null +++ b/engine/include/XCEngine/Rendering/Execution/CameraFrameRenderGraphStagePolicy.h @@ -0,0 +1,100 @@ +#pragma once + +#include +#include + +namespace XCEngine { +namespace Rendering { + +struct CameraFrameRenderGraphSourceBinding { + const RenderSurface* sourceSurfaceTemplate = nullptr; + RHI::RHIResourceView* sourceColorView = nullptr; + RHI::ResourceStates sourceColorState = RHI::ResourceStates::Common; + RenderGraphTextureHandle sourceColor = {}; +}; + +inline bool IsCameraFrameFullscreenSequenceStage( + CameraFrameStage stage) { + return stage == CameraFrameStage::PostProcess || + stage == CameraFrameStage::FinalOutput; +} + +inline bool DoesCameraFrameStageGraphOwnColorTransitions( + CameraFrameStage stage) { + return stage == CameraFrameStage::MainScene || + stage == CameraFrameStage::PostProcess || + stage == CameraFrameStage::FinalOutput || + stage == CameraFrameStage::ObjectId; +} + +inline bool DoesCameraFrameStageGraphOwnDepthTransitions( + CameraFrameStage stage) { + return stage == CameraFrameStage::ShadowCaster || + stage == CameraFrameStage::DepthOnly || + stage == CameraFrameStage::MainScene || + stage == CameraFrameStage::ObjectId; +} + +inline bool UsesCameraFrameStageGraphManagedOutputColor( + const CameraFramePlan& plan, + CameraFrameStage stage) { + switch (stage) { + case CameraFrameStage::MainScene: + return plan.usesGraphManagedMainSceneColor; + case CameraFrameStage::PostProcess: + return plan.usesGraphManagedPostProcessColor; + default: + return false; + } +} + +inline CameraFrameColorSource ResolveCameraFrameStageGraphManagedColorSource( + const CameraFramePlan& plan, + CameraFrameStage stage) { + switch (stage) { + case CameraFrameStage::PostProcess: + return plan.postProcessSource; + case CameraFrameStage::FinalOutput: + return plan.finalOutputSource; + default: + return CameraFrameColorSource::ExplicitSurface; + } +} + +inline CameraFrameRenderGraphSourceBinding ResolveCameraFrameFullscreenStageGraphSourceBinding( + const CameraFramePlan& plan, + CameraFrameStage stage, + const RenderSurface& stageSurfaceTemplate, + const RenderSurface* explicitSourceSurfaceTemplate, + RHI::RHIResourceView* explicitSourceColorView, + RHI::ResourceStates explicitSourceColorState, + RenderGraphTextureHandle explicitSourceColor, + const RenderGraphBlackboard* blackboard) { + CameraFrameRenderGraphSourceBinding binding = {}; + binding.sourceSurfaceTemplate = explicitSourceSurfaceTemplate; + binding.sourceColorView = explicitSourceColorView; + binding.sourceColorState = explicitSourceColorState; + binding.sourceColor = explicitSourceColor; + + const CameraFrameColorSource graphManagedSource = + ResolveCameraFrameStageGraphManagedColorSource(plan, stage); + if (graphManagedSource != CameraFrameColorSource::ExplicitSurface) { + binding.sourceSurfaceTemplate = &stageSurfaceTemplate; + binding.sourceColorView = nullptr; + binding.sourceColorState = RHI::ResourceStates::PixelShaderResource; + binding.sourceColor = + ResolveCameraFrameRenderGraphColorSource( + blackboard, + graphManagedSource); + } + + if (binding.sourceSurfaceTemplate == nullptr && + binding.sourceColor.IsValid()) { + binding.sourceSurfaceTemplate = &stageSurfaceTemplate; + } + + return binding; +} + +} // namespace Rendering +} // namespace XCEngine diff --git a/engine/src/Rendering/Execution/CameraRenderer.cpp b/engine/src/Rendering/Execution/CameraRenderer.cpp index 4586b7cd..cf4491e1 100644 --- a/engine/src/Rendering/Execution/CameraRenderer.cpp +++ b/engine/src/Rendering/Execution/CameraRenderer.cpp @@ -1,6 +1,7 @@ #include "Rendering/Execution/CameraRenderer.h" #include "Components/CameraComponent.h" +#include "Rendering/Execution/CameraFrameRenderGraphStagePolicy.h" #include "Rendering/Execution/DirectionalShadowExecutionState.h" #include "Rendering/Graph/RenderGraph.h" #include "Rendering/Graph/RenderGraphCompiler.h" @@ -256,12 +257,6 @@ void WriteRenderGraphColorSurface( } } -bool IsFullscreenSequenceStage( - CameraFrameStage stage) { - return stage == CameraFrameStage::PostProcess || - stage == CameraFrameStage::FinalOutput; -} - Containers::String BuildRenderGraphSequencePassName( const Containers::String& stageName, size_t passIndex) { @@ -530,14 +525,6 @@ RenderSurface BuildGraphManagedPassSurface( return surface; } -struct FullscreenStageGraphBinding { - const RenderSurface* sourceSurfaceTemplate = nullptr; - RHI::RHIResourceView* sourceColorView = nullptr; - RHI::ResourceStates sourceColorState = RHI::ResourceStates::Common; - RenderGraphTextureHandle sourceColor = {}; - RenderGraphTextureHandle outputColor = {}; -}; - const RenderSurface* ResolveFrameStageOutputSurface( CameraFrameStage stage, const CameraFramePlan& plan, @@ -560,22 +547,6 @@ const RenderSurface* ResolveFrameStageOutputSurface( } } -bool ShouldGraphOwnStageColorTransitions( - CameraFrameStage stage) { - return stage == CameraFrameStage::MainScene || - stage == CameraFrameStage::PostProcess || - stage == CameraFrameStage::FinalOutput || - stage == CameraFrameStage::ObjectId; -} - -bool ShouldGraphOwnStageDepthTransitions( - CameraFrameStage stage) { - return stage == CameraFrameStage::ShadowCaster || - stage == CameraFrameStage::DepthOnly || - stage == CameraFrameStage::MainScene || - stage == CameraFrameStage::ObjectId; -} - bool CanUseGraphManagedImportedSurface( const RenderGraphImportedSurface& surface, const RenderGraphExecutionContext& graphContext) { @@ -609,69 +580,24 @@ RenderGraphTextureHandle ResolveStageOutputColorHandle( const RenderPassContext& stagePassContext, const RenderGraphImportedSurface& outputSurface, RenderGraphBuilder& graphBuilder) { - if (stage == CameraFrameStage::MainScene && - plan.usesGraphManagedMainSceneColor) { - return graphBuilder.CreateTransientTexture( - stageName + ".Color", - BuildImportedTextureDesc( - stagePassContext.surface, - kRenderGraphImportedColorFormat)); - } - - if (stage == CameraFrameStage::PostProcess && - plan.usesGraphManagedPostProcessColor) { - return graphBuilder.CreateTransientTexture( - stageName + ".Color", - BuildFullscreenTransientTextureDesc(stagePassContext.surface)); - } - - return GetPrimaryColorTexture(outputSurface); -} - -FullscreenStageGraphBinding ResolveFullscreenStageGraphBinding( - CameraFrameStage stage, - const CameraFramePlan& plan, - const RenderPassContext& stagePassContext, - const RenderGraphImportedSurface& sourceSurface, - RenderGraphTextureHandle outputColor, - const RenderGraphBlackboard* blackboard) { - FullscreenStageGraphBinding binding = {}; - binding.sourceSurfaceTemplate = stagePassContext.sourceSurface; - binding.sourceColorView = stagePassContext.sourceColorView; - binding.sourceColorState = stagePassContext.sourceColorState; - binding.sourceColor = GetPrimaryColorTexture(sourceSurface); - binding.outputColor = outputColor; - - if (stage == CameraFrameStage::PostProcess && - plan.postProcessSource == CameraFrameColorSource::MainSceneColor) { - binding.sourceSurfaceTemplate = &stagePassContext.surface; - binding.sourceColorView = nullptr; - binding.sourceColorState = RHI::ResourceStates::PixelShaderResource; - binding.sourceColor = - ResolveCameraFrameRenderGraphColorSource( - blackboard, - plan.postProcessSource); - } - - if (stage == CameraFrameStage::FinalOutput) { - if (plan.finalOutputSource == CameraFrameColorSource::MainSceneColor || - plan.finalOutputSource == CameraFrameColorSource::PostProcessColor) { - binding.sourceSurfaceTemplate = &stagePassContext.surface; - binding.sourceColorView = nullptr; - binding.sourceColorState = RHI::ResourceStates::PixelShaderResource; - binding.sourceColor = - ResolveCameraFrameRenderGraphColorSource( - blackboard, - plan.finalOutputSource); + if (UsesCameraFrameStageGraphManagedOutputColor(plan, stage)) { + switch (stage) { + case CameraFrameStage::MainScene: + return graphBuilder.CreateTransientTexture( + stageName + ".Color", + BuildImportedTextureDesc( + stagePassContext.surface, + kRenderGraphImportedColorFormat)); + case CameraFrameStage::PostProcess: + return graphBuilder.CreateTransientTexture( + stageName + ".Color", + BuildFullscreenTransientTextureDesc(stagePassContext.surface)); + default: + break; } } - if (binding.sourceSurfaceTemplate == nullptr && - binding.sourceColor.IsValid()) { - binding.sourceSurfaceTemplate = &stagePassContext.surface; - } - - return binding; + return GetPrimaryColorTexture(outputSurface); } RenderPassContext BuildFrameStagePassContext( @@ -816,7 +742,8 @@ bool RecordFullscreenPassSequenceStage( CameraFrameStage stage, const Containers::String& stageName, const RenderPassContext& stagePassContext, - const FullscreenStageGraphBinding& binding, + const CameraFrameRenderGraphSourceBinding& binding, + RenderGraphTextureHandle finalOutputColor, const RenderSceneData& sceneData, RenderPassSequence* stageSequence, CameraFrameExecutionState& executionState, @@ -846,7 +773,6 @@ bool RecordFullscreenPassSequenceStage( }; RenderGraphTextureHandle currentSourceColor = binding.sourceColor; - const RenderGraphTextureHandle finalOutputColor = binding.outputColor; const RenderGraphTextureDesc transientDesc = BuildFullscreenTransientTextureDesc(stagePassContext.surface); @@ -945,7 +871,7 @@ bool ExecuteRenderGraphPlan( stageName + ".Source", stagePassContext.sourceSurface, RenderGraphSurfaceImportUsage::Source, - IsFullscreenSequenceStage(stage)); + IsCameraFrameFullscreenSequenceStage(stage)); const RenderGraphImportedSurface outputSurface = ImportRenderGraphSurface( graphBuilder, @@ -953,8 +879,8 @@ bool ExecuteRenderGraphPlan( stageName + ".Output", &stagePassContext.surface, RenderGraphSurfaceImportUsage::Output, - ShouldGraphOwnStageColorTransitions(stage), - ShouldGraphOwnStageDepthTransitions(stage)); + DoesCameraFrameStageGraphOwnColorTransitions(stage), + DoesCameraFrameStageGraphOwnDepthTransitions(stage)); const RenderGraphTextureHandle stageOutputColor = ResolveStageOutputColorHandle( stage, @@ -984,18 +910,21 @@ bool ExecuteRenderGraphPlan( if (stageSequence != nullptr) { const bool recordResult = - IsFullscreenSequenceStage(stage) + IsCameraFrameFullscreenSequenceStage(stage) ? RecordFullscreenPassSequenceStage( stage, stageName, stagePassContext, - ResolveFullscreenStageGraphBinding( - stage, + ResolveCameraFrameFullscreenStageGraphSourceBinding( plan, - stagePassContext, - sourceSurface, - stageOutputColor, + stage, + stagePassContext.surface, + stagePassContext.sourceSurface, + stagePassContext.sourceColorView, + stagePassContext.sourceColorState, + GetPrimaryColorTexture(sourceSurface), &blackboard), + stageOutputColor, sceneData, stageSequence, executionState, @@ -1103,7 +1032,7 @@ bool ExecuteRenderGraphPlan( stageName, [&, sourceSurface, outputSurface, stage, stageSurfaceTemplate, hasStageSourceSurface, stageSourceSurfaceTemplate, stageSourceColorView, stageSourceColorState]( RenderGraphPassBuilder& passBuilder) { - if (IsFullscreenSequenceStage(stage)) { + if (IsCameraFrameFullscreenSequenceStage(stage)) { ReadRenderGraphColorSurface(passBuilder, sourceSurface); WriteRenderGraphColorSurface(passBuilder, outputSurface); } else { @@ -1125,7 +1054,7 @@ bool ExecuteRenderGraphPlan( const_cast(stageSourceColorView); RHI::ResourceStates resolvedSourceColorState = stageSourceColorState; RenderSurface graphManagedSourceSurface = {}; - if (IsFullscreenSequenceStage(stage) && + if (IsCameraFrameFullscreenSequenceStage(stage) && hasStageSourceSurface && CanUseGraphManagedImportedSurface(sourceSurface, executionContext)) { graphManagedSourceSurface = diff --git a/tests/Rendering/unit/CMakeLists.txt b/tests/Rendering/unit/CMakeLists.txt index e6cf5cf8..3a97fc6f 100644 --- a/tests/Rendering/unit/CMakeLists.txt +++ b/tests/Rendering/unit/CMakeLists.txt @@ -7,6 +7,7 @@ set(RENDERING_UNIT_TEST_SOURCES test_object_id_encoding.cpp test_builtin_forward_pipeline.cpp test_builtin_gaussian_splat_pass_resources.cpp + test_camera_frame_render_graph_stage_policy.cpp test_camera_scene_renderer.cpp test_scene_render_request_planner.cpp test_scene_render_request_utils.cpp diff --git a/tests/Rendering/unit/test_camera_frame_render_graph_stage_policy.cpp b/tests/Rendering/unit/test_camera_frame_render_graph_stage_policy.cpp new file mode 100644 index 00000000..98543583 --- /dev/null +++ b/tests/Rendering/unit/test_camera_frame_render_graph_stage_policy.cpp @@ -0,0 +1,124 @@ +#include + +#include + +using namespace XCEngine::Rendering; + +namespace { + +RenderSurface CreateColorSurface( + uint32_t width, + uint32_t height, + XCEngine::RHI::RHIResourceView* colorAttachment) { + RenderSurface surface(width, height); + surface.SetColorAttachment(colorAttachment); + return surface; +} + +} // namespace + +TEST(CameraFrameRenderGraphStagePolicy_Test, ReportsStageFullscreenAndTransitionPolicies) { + EXPECT_TRUE(IsCameraFrameFullscreenSequenceStage(CameraFrameStage::PostProcess)); + EXPECT_TRUE(IsCameraFrameFullscreenSequenceStage(CameraFrameStage::FinalOutput)); + EXPECT_FALSE(IsCameraFrameFullscreenSequenceStage(CameraFrameStage::MainScene)); + + EXPECT_TRUE(DoesCameraFrameStageGraphOwnColorTransitions(CameraFrameStage::MainScene)); + EXPECT_TRUE(DoesCameraFrameStageGraphOwnColorTransitions(CameraFrameStage::FinalOutput)); + EXPECT_FALSE(DoesCameraFrameStageGraphOwnColorTransitions(CameraFrameStage::ShadowCaster)); + + EXPECT_TRUE(DoesCameraFrameStageGraphOwnDepthTransitions(CameraFrameStage::MainScene)); + EXPECT_TRUE(DoesCameraFrameStageGraphOwnDepthTransitions(CameraFrameStage::ShadowCaster)); + EXPECT_FALSE(DoesCameraFrameStageGraphOwnDepthTransitions(CameraFrameStage::FinalOutput)); +} + +TEST(CameraFrameRenderGraphStagePolicy_Test, ReportsGraphManagedOutputColorStagesFromPlan) { + CameraFramePlan plan = {}; + plan.usesGraphManagedMainSceneColor = true; + plan.usesGraphManagedPostProcessColor = true; + + EXPECT_TRUE(UsesCameraFrameStageGraphManagedOutputColor(plan, CameraFrameStage::MainScene)); + EXPECT_TRUE(UsesCameraFrameStageGraphManagedOutputColor(plan, CameraFrameStage::PostProcess)); + EXPECT_FALSE(UsesCameraFrameStageGraphManagedOutputColor(plan, CameraFrameStage::FinalOutput)); +} + +TEST(CameraFrameRenderGraphStagePolicy_Test, KeepsExplicitFullscreenSourceBindingUntouched) { + CameraFramePlan plan = {}; + RenderSurface stageSurface(320, 180); + RenderSurface explicitSourceSurface = + CreateColorSurface( + 320, + 180, + reinterpret_cast(11)); + XCEngine::RHI::RHIResourceView* const explicitSourceColorView = + reinterpret_cast(12); + + const CameraFrameRenderGraphSourceBinding binding = + ResolveCameraFrameFullscreenStageGraphSourceBinding( + plan, + CameraFrameStage::PostProcess, + stageSurface, + &explicitSourceSurface, + explicitSourceColorView, + XCEngine::RHI::ResourceStates::CopySrc, + RenderGraphTextureHandle{ 21u }, + nullptr); + + EXPECT_EQ(binding.sourceSurfaceTemplate, &explicitSourceSurface); + EXPECT_EQ(binding.sourceColorView, explicitSourceColorView); + EXPECT_EQ(binding.sourceColorState, XCEngine::RHI::ResourceStates::CopySrc); + EXPECT_EQ(binding.sourceColor.index, 21u); +} + +TEST(CameraFrameRenderGraphStagePolicy_Test, ResolvesGraphManagedPostProcessSourceFromBlackboard) { + CameraFramePlan plan = {}; + plan.postProcessSource = CameraFrameColorSource::MainSceneColor; + + RenderGraphBlackboard blackboard = {}; + CameraFrameRenderGraphResources& frameResources = + blackboard.Emplace(); + frameResources.mainScene.color = RenderGraphTextureHandle{ 31u }; + + RenderSurface stageSurface(640, 360); + const CameraFrameRenderGraphSourceBinding binding = + ResolveCameraFrameFullscreenStageGraphSourceBinding( + plan, + CameraFrameStage::PostProcess, + stageSurface, + nullptr, + reinterpret_cast(41), + XCEngine::RHI::ResourceStates::Common, + {}, + &blackboard); + + EXPECT_EQ(binding.sourceSurfaceTemplate, &stageSurface); + EXPECT_EQ(binding.sourceColorView, nullptr); + EXPECT_EQ(binding.sourceColorState, XCEngine::RHI::ResourceStates::PixelShaderResource); + EXPECT_EQ(binding.sourceColor.index, 31u); +} + +TEST(CameraFrameRenderGraphStagePolicy_Test, ResolvesGraphManagedFinalOutputSourceFromBlackboard) { + CameraFramePlan plan = {}; + plan.finalOutputSource = CameraFrameColorSource::PostProcessColor; + + RenderGraphBlackboard blackboard = {}; + CameraFrameRenderGraphResources& frameResources = + blackboard.Emplace(); + frameResources.postProcess.color = RenderGraphTextureHandle{ 51u }; + + RenderSurface stageSurface(800, 600); + const CameraFrameRenderGraphSourceBinding binding = + ResolveCameraFrameFullscreenStageGraphSourceBinding( + plan, + CameraFrameStage::FinalOutput, + stageSurface, + nullptr, + reinterpret_cast(61), + XCEngine::RHI::ResourceStates::Common, + {}, + &blackboard); + + EXPECT_EQ(binding.sourceSurfaceTemplate, &stageSurface); + EXPECT_EQ(binding.sourceColorView, nullptr); + EXPECT_EQ(binding.sourceColorState, XCEngine::RHI::ResourceStates::PixelShaderResource); + EXPECT_EQ(binding.sourceColor.index, 51u); +}