From 8798e63e32c66ea3444b462f392b1bdad0951107 Mon Sep 17 00:00:00 2001 From: ssdfasd <2156608475@qq.com> Date: Wed, 15 Apr 2026 20:46:00 +0800 Subject: [PATCH] refactor(rendering): formalize native graph recording helpers --- ...enderGraphBuilder与NativePass正式化_2026-04-15.md | 0 .../Graph/RenderGraphRecordingContext.h | 94 ++++++++++++++ .../CameraFrameGraph/StageContract.cpp | 23 ++-- .../BuiltinForwardStageGraphBuilder.cpp | 28 ++--- .../RenderPipelineStageGraphContract.cpp | 12 +- .../src/Rendering/SceneRenderFeaturePass.cpp | 24 ++-- .../test_render_graph_recording_context.cpp | 119 ++++++++++++++++++ 7 files changed, 258 insertions(+), 42 deletions(-) rename docs/{plan => used}/Renderer_C++层第六阶段计划_RenderGraphBuilder与NativePass正式化_2026-04-15.md (100%) diff --git a/docs/plan/Renderer_C++层第六阶段计划_RenderGraphBuilder与NativePass正式化_2026-04-15.md b/docs/used/Renderer_C++层第六阶段计划_RenderGraphBuilder与NativePass正式化_2026-04-15.md similarity index 100% rename from docs/plan/Renderer_C++层第六阶段计划_RenderGraphBuilder与NativePass正式化_2026-04-15.md rename to docs/used/Renderer_C++层第六阶段计划_RenderGraphBuilder与NativePass正式化_2026-04-15.md diff --git a/engine/include/XCEngine/Rendering/Graph/RenderGraphRecordingContext.h b/engine/include/XCEngine/Rendering/Graph/RenderGraphRecordingContext.h index e43aa00a..356e9fde 100644 --- a/engine/include/XCEngine/Rendering/Graph/RenderGraphRecordingContext.h +++ b/engine/include/XCEngine/Rendering/Graph/RenderGraphRecordingContext.h @@ -3,6 +3,8 @@ #include #include +#include + namespace XCEngine { namespace Rendering { @@ -39,6 +41,73 @@ struct RenderGraphRecordingContextOverrides { RenderGraphTextureHandle depthTarget = {}; }; +struct RenderGraphRecordingSourceBinding { + const RenderSurface* sourceSurface = nullptr; + RHI::RHIResourceView* sourceColorView = nullptr; + RHI::ResourceStates sourceColorState = RHI::ResourceStates::Common; + RenderGraphTextureHandle sourceColorTexture = {}; +}; + +inline RenderGraphRecordingSourceBinding MakeRenderGraphRecordingSourceBinding( + const RenderSurface* sourceSurface = nullptr, + RHI::RHIResourceView* sourceColorView = nullptr, + RHI::ResourceStates sourceColorState = RHI::ResourceStates::Common, + RenderGraphTextureHandle sourceColorTexture = {}) { + return { + sourceSurface, + sourceColorView, + sourceColorState, + sourceColorTexture + }; +} + +inline RenderGraphRecordingSourceBinding BuildRenderGraphRecordingSourceBinding( + const RenderGraphRecordingContext& context) { + return MakeRenderGraphRecordingSourceBinding( + context.sourceSurface, + context.sourceColorView, + context.sourceColorState, + context.sourceColorTexture); +} + +inline RenderGraphRecordingSourceBinding ResolveRenderGraphRecordingSourceBinding( + const RenderGraphRecordingContext& context, + const RenderSurface* fallbackSourceSurfaceTemplate, + RenderSurface* resolvedSourceSurfaceStorage = nullptr) { + RenderGraphRecordingSourceBinding binding = + BuildRenderGraphRecordingSourceBinding(context); + if (binding.sourceSurface == nullptr && + fallbackSourceSurfaceTemplate != nullptr && + binding.sourceColorTexture.IsValid()) { + if (resolvedSourceSurfaceStorage != nullptr) { + *resolvedSourceSurfaceStorage = *fallbackSourceSurfaceTemplate; + binding.sourceSurface = resolvedSourceSurfaceStorage; + } else { + binding.sourceSurface = fallbackSourceSurfaceTemplate; + } + } + + return binding; +} + +inline RenderSurface BuildRenderGraphManagedSurfaceTemplate( + const RenderSurface& templateSurface) { + RenderSurface surface = templateSurface; + surface.SetAutoTransitionEnabled(false); + return surface; +} + +struct RenderGraphRecordingContextBuildParams { + const Containers::String* passName = nullptr; + const RenderSurface* surface = nullptr; + bool overrideSourceBinding = false; + RenderGraphRecordingSourceBinding sourceBinding = {}; + bool overrideColorTargets = false; + std::vector colorTargets = {}; + bool overrideDepthTarget = false; + RenderGraphTextureHandle depthTarget = {}; +}; + inline RenderGraphRecordingContext CloneRenderGraphRecordingContext( const RenderGraphRecordingContext& context, const RenderGraphRecordingContextOverrides& overrides) { @@ -71,6 +140,31 @@ inline RenderGraphRecordingContext CloneRenderGraphRecordingContext( overrides); } +inline RenderGraphRecordingContext BuildRenderGraphRecordingContext( + const RenderGraphRecordingContext& context, + RenderGraphRecordingContextBuildParams params) { + RenderGraphRecordingContextOverrides overrides = {}; + overrides.passName = params.passName; + overrides.surface = params.surface; + if (params.overrideSourceBinding) { + overrides.overrideSourceSurface = true; + overrides.sourceSurface = params.sourceBinding.sourceSurface; + overrides.overrideSourceColorView = true; + overrides.sourceColorView = params.sourceBinding.sourceColorView; + overrides.overrideSourceColorState = true; + overrides.sourceColorState = params.sourceBinding.sourceColorState; + overrides.overrideSourceColorTexture = true; + overrides.sourceColorTexture = params.sourceBinding.sourceColorTexture; + } + overrides.overrideColorTargets = params.overrideColorTargets; + overrides.colorTargets = std::move(params.colorTargets); + overrides.overrideDepthTarget = params.overrideDepthTarget; + overrides.depthTarget = params.depthTarget; + return CloneRenderGraphRecordingContext( + context, + overrides); +} + inline RenderGraphRecordingContext BuildRenderGraphRecordingContext( const RenderPassRenderGraphContext& context) { return { diff --git a/engine/src/Rendering/Execution/Internal/CameraFrameGraph/StageContract.cpp b/engine/src/Rendering/Execution/Internal/CameraFrameGraph/StageContract.cpp index 432f07b7..22e7df7e 100644 --- a/engine/src/Rendering/Execution/Internal/CameraFrameGraph/StageContract.cpp +++ b/engine/src/Rendering/Execution/Internal/CameraFrameGraph/StageContract.cpp @@ -425,19 +425,26 @@ RenderGraphRecordingContext BuildCameraFrameStageGraphRecordingContext( const CameraFrameRenderGraphSourceBinding& sourceBinding, std::vector colorTargets, RenderGraphTextureHandle depthTarget) { - RenderGraphRecordingContextOverrides overrides = {}; - overrides.passName = &passName; - overrides.overrideColorTargets = true; - overrides.colorTargets = std::move(colorTargets); - overrides.overrideDepthTarget = true; - overrides.depthTarget = depthTarget; - return CloneRenderGraphRecordingContext( + RenderGraphRecordingContextBuildParams recordingParams = {}; + recordingParams.passName = &passName; + recordingParams.overrideSourceBinding = true; + recordingParams.sourceBinding = + MakeRenderGraphRecordingSourceBinding( + sourceBinding.sourceSurfaceTemplate, + sourceBinding.sourceColorView, + sourceBinding.sourceColorState, + sourceBinding.sourceColor); + recordingParams.overrideColorTargets = true; + recordingParams.colorTargets = std::move(colorTargets); + recordingParams.overrideDepthTarget = true; + recordingParams.depthTarget = depthTarget; + return BuildRenderGraphRecordingContext( BuildCameraFrameStageGraphRecordingContext( context, stageState, sceneData, sourceBinding), - overrides); + std::move(recordingParams)); } RenderGraphRecordingContext BuildCameraFrameStageGraphRecordingContext( diff --git a/engine/src/Rendering/Pipelines/Internal/BuiltinForwardStageGraphBuilder.cpp b/engine/src/Rendering/Pipelines/Internal/BuiltinForwardStageGraphBuilder.cpp index 2adb3777..3f1802fb 100644 --- a/engine/src/Rendering/Pipelines/Internal/BuiltinForwardStageGraphBuilder.cpp +++ b/engine/src/Rendering/Pipelines/Internal/BuiltinForwardStageGraphBuilder.cpp @@ -17,12 +17,6 @@ namespace Internal { namespace { -RenderSurface BuildGraphManagedForwardSceneSurface(const RenderSurface& templateSurface) { - RenderSurface surface = templateSurface; - surface.SetAutoTransitionEnabled(false); - return surface; -} - struct ForwardSceneGraphExecutionState { bool initialized = false; }; @@ -38,18 +32,18 @@ bool BuiltinForwardStageGraphBuilder::Record( BuiltinForwardPipeline& pipeline, const RenderPipelineStageRenderGraphContext& context) { const RenderSurface graphManagedSurface = - BuildGraphManagedForwardSceneSurface(context.surfaceTemplate); - const bool hasSourceSurface = context.sourceSurface != nullptr; - const RenderSurface sourceSurface = - hasSourceSurface ? *context.sourceSurface : RenderSurface(); - RenderGraphRecordingContextOverrides overrides = {}; - overrides.surface = &graphManagedSurface; - overrides.overrideSourceSurface = true; - overrides.sourceSurface = hasSourceSurface ? &sourceSurface : nullptr; + BuildRenderGraphManagedSurfaceTemplate(context.surfaceTemplate); + const RenderGraphRecordingContext baseRecordingContext = + BuildRenderGraphRecordingContext(context); + RenderGraphRecordingContextBuildParams recordingParams = {}; + recordingParams.surface = &graphManagedSurface; + recordingParams.overrideSourceBinding = true; + recordingParams.sourceBinding = + BuildRenderGraphRecordingSourceBinding(baseRecordingContext); RenderGraphRecordingContext recordingContext = - CloneRenderGraphRecordingContext( - BuildRenderGraphRecordingContext(context), - overrides); + BuildRenderGraphRecordingContext( + baseRecordingContext, + std::move(recordingParams)); const CameraFrameRenderGraphResources* const frameResources = TryGetCameraFrameRenderGraphResources(recordingContext.blackboard); diff --git a/engine/src/Rendering/RenderPipelineStageGraphContract.cpp b/engine/src/Rendering/RenderPipelineStageGraphContract.cpp index 5a867041..7b987228 100644 --- a/engine/src/Rendering/RenderPipelineStageGraphContract.cpp +++ b/engine/src/Rendering/RenderPipelineStageGraphContract.cpp @@ -48,13 +48,17 @@ bool RecordRenderPipelineStagePhasePass( RenderPassGraphBeginCallback beginPassCallback, RenderPassGraphEndCallback endPassCallback, std::vector additionalReadTextures) { + const Containers::String phasePassName = + BuildRenderPipelineStagePhasePassName( + context.passName, + scenePhase); + RenderGraphRecordingContextBuildParams recordingParams = {}; + recordingParams.passName = &phasePassName; const RenderPassRenderGraphContext passContext = BuildRenderPassRenderGraphContext( - CloneRenderGraphRecordingContext( + BuildRenderGraphRecordingContext( BuildRenderGraphRecordingContext(context), - BuildRenderPipelineStagePhasePassName( - context.passName, - scenePhase)), + std::move(recordingParams)), beginPassCallback, endPassCallback); return RecordColorDepthCallbackRasterPass( diff --git a/engine/src/Rendering/SceneRenderFeaturePass.cpp b/engine/src/Rendering/SceneRenderFeaturePass.cpp index 6ffcb37c..fed3a8c3 100644 --- a/engine/src/Rendering/SceneRenderFeaturePass.cpp +++ b/engine/src/Rendering/SceneRenderFeaturePass.cpp @@ -10,22 +10,20 @@ namespace Rendering { bool SceneRenderFeaturePass::RecordRenderGraph( const SceneRenderFeaturePassRenderGraphContext& context) { - const bool usesSourceColor = context.sourceColorTexture.IsValid(); const RenderGraphRecordingContext baseRecordingContext = BuildRenderGraphRecordingContext(context); - const RenderSurface sourceSurfaceTemplate = - baseRecordingContext.sourceSurface != nullptr - ? *baseRecordingContext.sourceSurface - : (usesSourceColor ? context.surface : RenderSurface()); - RenderGraphRecordingContextOverrides overrides = {}; - overrides.overrideSourceSurface = - baseRecordingContext.sourceSurface == nullptr && usesSourceColor; - overrides.sourceSurface = - overrides.overrideSourceSurface ? &sourceSurfaceTemplate : nullptr; - const RenderGraphRecordingContext recordingContext = - CloneRenderGraphRecordingContext( + RenderSurface sourceSurfaceTemplate = {}; + RenderGraphRecordingContextBuildParams recordingParams = {}; + recordingParams.overrideSourceBinding = true; + recordingParams.sourceBinding = + ResolveRenderGraphRecordingSourceBinding( baseRecordingContext, - overrides); + &baseRecordingContext.surface, + &sourceSurfaceTemplate); + const RenderGraphRecordingContext recordingContext = + BuildRenderGraphRecordingContext( + baseRecordingContext, + std::move(recordingParams)); const RenderPassGraphBeginCallback beginPassCallback = context.beginPassCallback diff --git a/tests/Rendering/unit/test_render_graph_recording_context.cpp b/tests/Rendering/unit/test_render_graph_recording_context.cpp index 1bb284f8..36a1dd67 100644 --- a/tests/Rendering/unit/test_render_graph_recording_context.cpp +++ b/tests/Rendering/unit/test_render_graph_recording_context.cpp @@ -393,6 +393,125 @@ TEST(RenderGraphRecordingContext_Test, CloneOverridesSelectedRecordingContextFie EXPECT_EQ(overriddenContext.blackboard, &blackboard); } +TEST(RenderGraphRecordingContext_Test, ResolvesSourceBindingWithFallbackSurfaceWhenOnlySourceTextureExists) { + RenderGraph graph = {}; + RenderGraphBuilder builder(graph); + RenderGraphBlackboard blackboard = {}; + RenderContext renderContext = {}; + RenderSceneData sceneData = {}; + RenderSurface surface(800u, 600u); + surface.SetRenderArea(XCEngine::Math::RectInt(10, 20, 400, 300)); + RenderSurface sourceSurface(400u, 300u); + bool executionSucceeded = false; + RenderGraphRecordingContext commonContext = + BuildCommonContext( + builder, + blackboard, + renderContext, + sceneData, + surface, + sourceSurface, + executionSucceeded); + commonContext.sourceSurface = nullptr; + + RenderSurface fallbackSourceSurface = {}; + const RenderGraphRecordingSourceBinding binding = + ResolveRenderGraphRecordingSourceBinding( + commonContext, + &commonContext.surface, + &fallbackSourceSurface); + + ASSERT_NE(binding.sourceSurface, nullptr); + EXPECT_EQ(binding.sourceSurface, &fallbackSourceSurface); + EXPECT_EQ(binding.sourceSurface->GetWidth(), 800u); + EXPECT_EQ(binding.sourceSurface->GetHeight(), 600u); + EXPECT_EQ(binding.sourceSurface->GetRenderAreaWidth(), 400u); + EXPECT_EQ(binding.sourceSurface->GetRenderAreaHeight(), 300u); + EXPECT_EQ( + binding.sourceColorView, + reinterpret_cast(0x1234)); + EXPECT_EQ( + binding.sourceColorState, + XCEngine::RHI::ResourceStates::PixelShaderResource); + EXPECT_EQ(binding.sourceColorTexture.index, 3u); +} + +TEST(RenderGraphRecordingContext_Test, BuildsRecordingContextFromFormalBuildParams) { + RenderGraph graph = {}; + RenderGraphBuilder builder(graph); + RenderGraphBlackboard blackboard = {}; + RenderContext renderContext = {}; + RenderSceneData sceneData = {}; + RenderSurface surface(800u, 600u); + RenderSurface sourceSurface(400u, 300u); + bool executionSucceeded = false; + const RenderGraphRecordingContext commonContext = + BuildCommonContext( + builder, + blackboard, + renderContext, + sceneData, + surface, + sourceSurface, + executionSucceeded); + + const XCEngine::Containers::String overriddenPassName("Recording.Built"); + RenderSurface overriddenSurface(1024u, 576u); + RenderSurface overriddenSourceSurface(512u, 288u); + RenderGraphRecordingContextBuildParams params = {}; + params.passName = &overriddenPassName; + params.surface = &overriddenSurface; + params.overrideSourceBinding = true; + params.sourceBinding = + MakeRenderGraphRecordingSourceBinding( + &overriddenSourceSurface, + reinterpret_cast(0x4321), + XCEngine::RHI::ResourceStates::CopySrc, + RenderGraphTextureHandle{ 12u }); + params.overrideColorTargets = true; + params.colorTargets = { { 13u } }; + params.overrideDepthTarget = true; + params.depthTarget = { 14u }; + + const RenderGraphRecordingContext overriddenContext = + BuildRenderGraphRecordingContext( + commonContext, + std::move(params)); + + EXPECT_EQ(overriddenContext.passName, overriddenPassName); + EXPECT_EQ(overriddenContext.surface.GetWidth(), 1024u); + EXPECT_EQ(overriddenContext.surface.GetHeight(), 576u); + ASSERT_NE(overriddenContext.sourceSurface, nullptr); + EXPECT_EQ(overriddenContext.sourceSurface->GetWidth(), 512u); + EXPECT_EQ( + overriddenContext.sourceColorView, + reinterpret_cast(0x4321)); + EXPECT_EQ( + overriddenContext.sourceColorState, + XCEngine::RHI::ResourceStates::CopySrc); + EXPECT_EQ(overriddenContext.sourceColorTexture.index, 12u); + ASSERT_EQ(overriddenContext.colorTargets.size(), 1u); + EXPECT_EQ(overriddenContext.colorTargets[0].index, 13u); + EXPECT_EQ(overriddenContext.depthTarget.index, 14u); + EXPECT_EQ(overriddenContext.executionSucceeded, &executionSucceeded); + EXPECT_EQ(overriddenContext.blackboard, &blackboard); +} + +TEST(RenderGraphRecordingContext_Test, BuildsGraphManagedSurfaceTemplateWithoutAutoTransitions) { + RenderSurface templateSurface(960u, 540u); + templateSurface.SetAutoTransitionEnabled(true); + templateSurface.SetRenderArea(XCEngine::Math::RectInt(4, 5, 320, 200)); + + const RenderSurface graphManagedSurface = + BuildRenderGraphManagedSurfaceTemplate(templateSurface); + + EXPECT_EQ(graphManagedSurface.GetWidth(), 960u); + EXPECT_EQ(graphManagedSurface.GetHeight(), 540u); + EXPECT_EQ(graphManagedSurface.GetRenderAreaWidth(), 320u); + EXPECT_EQ(graphManagedSurface.GetRenderAreaHeight(), 200u); + EXPECT_FALSE(graphManagedSurface.IsAutoTransitionEnabled()); +} + TEST(RenderGraphRecordingContext_Test, BuildsSharedRecordingDataFromPipelineStageContext) { RenderGraph graph = {}; RenderGraphBuilder builder(graph);