From 08ff505b67f752bad766e209caa29eda60b1e688 Mon Sep 17 00:00:00 2001 From: ssdfasd <2156608475@qq.com> Date: Wed, 22 Apr 2026 00:07:10 +0800 Subject: [PATCH] refactor(srp): add depth-aware managed fullscreen raster graph bridge --- ...eenDepthSurfacePlan_2026-04-21_完成归档.md | 107 ++++++++++++++++++ .../Rendering/RenderPassGraphContract.h | 9 +- .../src/Rendering/RenderPassGraphContract.cpp | 11 +- .../src/Scripting/Mono/MonoScriptRuntime.cpp | 74 +++++++++++- managed/XCEngine.ScriptCore/InternalCalls.cs | 14 +++ .../Graph/RenderGraphRasterPassBuilder.cs | 50 ++++++++ 6 files changed, 258 insertions(+), 7 deletions(-) create mode 100644 docs/used/SRP_URP_ManagedRenderGraphFullscreenDepthSurfacePlan_2026-04-21_完成归档.md diff --git a/docs/used/SRP_URP_ManagedRenderGraphFullscreenDepthSurfacePlan_2026-04-21_完成归档.md b/docs/used/SRP_URP_ManagedRenderGraphFullscreenDepthSurfacePlan_2026-04-21_完成归档.md new file mode 100644 index 00000000..d84eb1b0 --- /dev/null +++ b/docs/used/SRP_URP_ManagedRenderGraphFullscreenDepthSurfacePlan_2026-04-21_完成归档.md @@ -0,0 +1,107 @@ +# SRP / URP Managed Render Graph Fullscreen Depth Surface Plan + +Date: 2026-04-21 + +## Background + +The current SRP / URP managed render-graph surface is usable, but still too +thin in one important place: + +- managed fullscreen raster passes can read source color +- managed fullscreen raster passes can write color targets +- managed fullscreen raster passes cannot explicitly declare depth-texture reads +- managed fullscreen raster passes cannot explicitly keep or override a depth + attachment + +That is an architectural gap, not just a convenience issue. + +If a C# renderer feature wants to implement a depth-aware fullscreen effect +(for example edge detection, fog composition, SSAO-style composition, depth +conditioned blur, or custom outline logic), it currently has no correct managed +API surface to describe that dependency to the native render graph. + +So even though the native render graph already supports depth texture access, +the managed SRP surface still under-expresses the dependency graph. + +## Goal + +Close the first managed render-graph execution-surface gap by making managed +fullscreen raster recording depth-aware. + +After this stage: + +- managed C# fullscreen raster passes can declare depth texture reads +- managed C# fullscreen raster passes can explicitly set a depth attachment when + needed +- the Mono bridge preserves those declarations into the native render graph +- native graph recording uses depth-as-depth semantics instead of treating every + read texture as color + +## Scope + +Included: + +- `managed/XCEngine.ScriptCore/Rendering/Core/ScriptableRenderContext.cs` +- `managed/XCEngine.ScriptCore/Rendering/Graph/RenderGraphRasterPassBuilder.cs` +- `managed/XCEngine.ScriptCore/InternalCalls.cs` +- `engine/src/Scripting/Mono/MonoScriptRuntime.cpp` +- `engine/include/XCEngine/Rendering/RenderPassGraphContract.h` +- `engine/src/Rendering/RenderPassGraphContract.cpp` + +Not included: + +- deferred renderer work +- moving shadow / gaussian / volumetric runtime ownership in this phase +- generic managed compute-pass authoring in this phase +- editor / new_editor work + +## Implementation Plan + +1. Extend managed raster-pass builder with depth read / depth attachment APIs +2. Extend Mono internal calls and pending managed fullscreen-pass request state +3. Preserve depth reads separately from color reads through native bridge flush +4. Teach native raster-pass graph recording to issue depth reads with correct + render-graph aspect semantics +5. Rebuild old `XCEditor` +6. Run old editor smoke for at least 10 seconds and verify `SceneReady` +7. Archive the plan, commit, and push + +## Exit Criteria + +- managed code can call APIs equivalent to: + - `UseDepthTexture(...)` + - `SetDepthAttachment(...)` +- native bridge stores depth reads independently from color reads +- native render-graph recording emits `ReadDepthTexture(...)` for managed depth + inputs +- old `XCEditor` Debug build succeeds +- old editor smoke succeeds + +## Why This Stage First + +This is the right next step because it improves the managed SRP execution +surface without prematurely expanding into deferred rendering or feature +migration. + +It makes the current managed URP layer materially more useful for real custom +renderer features, while keeping the change scoped and architecture-driven. + +## Result + +Completed on 2026-04-21. + +- extended managed fullscreen raster-pass authoring with: + - `UseDepthTexture(...)` + - `SetDepthAttachment(...)` +- extended Mono internal-call bridge to preserve fullscreen managed depth reads + and optional depth attachment overrides +- extended native raster-pass graph recording to emit depth reads with + `ReadDepthTexture(...)` instead of treating all managed read dependencies as + color +- preserved existing fullscreen source-color path and final-output behavior + +## Verification + +- `cmake --build . --config Debug --target XCEditor` +- old editor smoke passed +- `SceneReady elapsed_ms=5621 first_frame_ms=602` diff --git a/engine/include/XCEngine/Rendering/RenderPassGraphContract.h b/engine/include/XCEngine/Rendering/RenderPassGraphContract.h index 94980ec9..74e775c7 100644 --- a/engine/include/XCEngine/Rendering/RenderPassGraphContract.h +++ b/engine/include/XCEngine/Rendering/RenderPassGraphContract.h @@ -52,7 +52,8 @@ bool RecordCallbackRasterRenderPass( const RenderPassRenderGraphContext& context, const RenderPassGraphIO& io, RenderPassGraphExecutePassCallback executePassCallback, - std::vector additionalReadTextures = {}); + std::vector additionalReadTextures = {}, + std::vector additionalReadDepthTextures = {}); bool RecordRasterRenderPass( RenderPass& pass, @@ -100,12 +101,14 @@ inline bool RecordSourceColorFullscreenCallbackRasterPass( inline bool RecordColorDepthCallbackRasterPass( const RenderPassRenderGraphContext& context, RenderPassGraphExecutePassCallback executePassCallback, - std::vector additionalReadTextures = {}) { + std::vector additionalReadTextures = {}, + std::vector additionalReadDepthTextures = {}) { return RecordCallbackRasterRenderPass( context, BuildColorDepthRasterPassGraphIO(), std::move(executePassCallback), - std::move(additionalReadTextures)); + std::move(additionalReadTextures), + std::move(additionalReadDepthTextures)); } } // namespace Rendering diff --git a/engine/src/Rendering/RenderPassGraphContract.cpp b/engine/src/Rendering/RenderPassGraphContract.cpp index d1bd8616..38cd77fe 100644 --- a/engine/src/Rendering/RenderPassGraphContract.cpp +++ b/engine/src/Rendering/RenderPassGraphContract.cpp @@ -152,7 +152,8 @@ bool RecordCallbackRasterRenderPass( const RenderPassRenderGraphContext& context, const RenderPassGraphIO& io, RenderPassGraphExecutePassCallback executePassCallback, - std::vector additionalReadTextures) { + std::vector additionalReadTextures, + std::vector additionalReadDepthTextures) { if (!executePassCallback) { return false; } @@ -191,6 +192,7 @@ bool RecordCallbackRasterRenderPass( endPassCallback, executePassCallback, additionalReadTextures, + additionalReadDepthTextures, io]( RenderGraphPassBuilder& passBuilder) { if (io.readSourceColor && sourceColorTexture.IsValid()) { @@ -203,6 +205,13 @@ bool RecordCallbackRasterRenderPass( } } + for (RenderGraphTextureHandle readDepthTexture : + additionalReadDepthTextures) { + if (readDepthTexture.IsValid()) { + passBuilder.ReadDepthTexture(readDepthTexture); + } + } + if (io.writeColor) { for (RenderGraphTextureHandle colorTarget : colorTargets) { if (colorTarget.IsValid()) { diff --git a/engine/src/Scripting/Mono/MonoScriptRuntime.cpp b/engine/src/Scripting/Mono/MonoScriptRuntime.cpp index 1c7f5a03..1c1e4ad2 100644 --- a/engine/src/Scripting/Mono/MonoScriptRuntime.cpp +++ b/engine/src/Scripting/Mono/MonoScriptRuntime.cpp @@ -118,7 +118,9 @@ struct ManagedScriptableRenderContextState { Rendering::FullscreenPassDesc passDesc = {}; Rendering::RenderGraphTextureHandle sourceColorTexture = {}; std::vector readTextures = {}; + std::vector readDepthTextures = {}; std::vector colorTargets = {}; + Rendering::RenderGraphTextureHandle depthTarget = {}; }; uint64_t nextPendingRasterPassHandle = 1u; std::unordered_map @@ -420,6 +422,8 @@ bool RecordManagedFullscreenRasterPass( Rendering::RenderGraphTextureHandle sourceColorTexture, std::vector colorTargets, std::vector additionalReadTextures, + std::vector additionalReadDepthTextures, + Rendering::RenderGraphTextureHandle depthTarget, const Containers::String& passName) { if (!Rendering::IsCameraFrameFullscreenSequenceStage(stageContext.stage) || !sourceColorTexture.IsValid() || @@ -442,7 +446,7 @@ bool RecordManagedFullscreenRasterPass( params.overrideColorTargets = true; params.colorTargets = std::move(colorTargets); params.overrideDepthTarget = true; - params.depthTarget = {}; + params.depthTarget = depthTarget; const Rendering::RenderGraphRecordingContext recordingContext = Rendering::BuildRenderGraphRecordingContext( @@ -451,14 +455,18 @@ bool RecordManagedFullscreenRasterPass( const Rendering::RenderPassRenderGraphContext renderGraphContext = Rendering::BuildRenderPassRenderGraphContext(recordingContext); Rendering::RenderPass* const passPtr = &pass; + Rendering::RenderPassGraphIO io = + Rendering::BuildSourceColorFullscreenRasterPassGraphIO(); + io.writeDepth = depthTarget.IsValid(); return Rendering::RecordCallbackRasterRenderPass( renderGraphContext, - Rendering::BuildSourceColorFullscreenRasterPassGraphIO(), + io, [passPtr](const Rendering::RenderPassContext& passContext) { return passPtr != nullptr && passPtr->Execute(passContext); }, - std::move(additionalReadTextures)); + std::move(additionalReadTextures), + std::move(additionalReadDepthTextures)); } bool RecordManagedFullscreenPassToTexture( @@ -473,6 +481,8 @@ bool RecordManagedFullscreenPassToTexture( sourceColorTexture, { outputColorTexture }, {}, + {}, + {}, passName); } @@ -1934,6 +1944,8 @@ private: resolvedSourceColor, resolvedColorTargets, request.readTextures, + request.readDepthTextures, + request.depthTarget, resolvedPassName)) { return false; } @@ -4691,6 +4703,33 @@ InternalCall_Rendering_ScriptableRenderContext_AddRasterPassReadTexture( return 1; } +mono_bool +InternalCall_Rendering_ScriptableRenderContext_AddRasterPassReadDepthTexture( + uint64_t nativeHandle, + uint64_t rasterPassHandle, + int32_t textureHandle) { + ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + ManagedScriptableRenderContextState::RasterPassRecordRequest* + const request = + FindPendingManagedRasterPassRecordRequest( + state, + rasterPassHandle); + if (request == nullptr) { + return 0; + } + + const Rendering::RenderGraphTextureHandle readDepthTexture = + DecodeManagedRenderGraphTextureHandle( + textureHandle); + if (!readDepthTexture.IsValid()) { + return 0; + } + + request->readDepthTextures.push_back(readDepthTexture); + return 1; +} + mono_bool InternalCall_Rendering_ScriptableRenderContext_SetRasterPassColorAttachment( uint64_t nativeHandle, @@ -4727,6 +4766,33 @@ InternalCall_Rendering_ScriptableRenderContext_SetRasterPassColorAttachment( return 1; } +mono_bool +InternalCall_Rendering_ScriptableRenderContext_SetRasterPassDepthAttachment( + uint64_t nativeHandle, + uint64_t rasterPassHandle, + int32_t textureHandle) { + ManagedScriptableRenderContextState* const state = + FindManagedScriptableRenderContextState(nativeHandle); + ManagedScriptableRenderContextState::RasterPassRecordRequest* + const request = + FindPendingManagedRasterPassRecordRequest( + state, + rasterPassHandle); + if (request == nullptr) { + return 0; + } + + const Rendering::RenderGraphTextureHandle depthAttachment = + DecodeManagedRenderGraphTextureHandle( + textureHandle); + if (!depthAttachment.IsValid()) { + return 0; + } + + request->depthTarget = depthAttachment; + return 1; +} + mono_bool InternalCall_Rendering_ScriptableRenderContext_SetRasterPassColorScaleFullscreenExecution( uint64_t nativeHandle, @@ -6313,7 +6379,9 @@ void RegisterInternalCalls() { mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_BeginRasterPass", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_BeginRasterPass)); mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_SetRasterPassSourceColorTexture", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_SetRasterPassSourceColorTexture)); mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_AddRasterPassReadTexture", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_AddRasterPassReadTexture)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_AddRasterPassReadDepthTexture", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_AddRasterPassReadDepthTexture)); mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_SetRasterPassColorAttachment", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_SetRasterPassColorAttachment)); + mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_SetRasterPassDepthAttachment", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_SetRasterPassDepthAttachment)); mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_SetRasterPassColorScaleFullscreenExecution", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_SetRasterPassColorScaleFullscreenExecution)); mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_SetRasterPassShaderVectorFullscreenExecution", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_SetRasterPassShaderVectorFullscreenExecution)); mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_SetRasterPassFinalColorFullscreenExecution", reinterpret_cast(&InternalCall_Rendering_ScriptableRenderContext_SetRasterPassFinalColorFullscreenExecution)); diff --git a/managed/XCEngine.ScriptCore/InternalCalls.cs b/managed/XCEngine.ScriptCore/InternalCalls.cs index 49a0a0bd..4685b8d2 100644 --- a/managed/XCEngine.ScriptCore/InternalCalls.cs +++ b/managed/XCEngine.ScriptCore/InternalCalls.cs @@ -486,6 +486,13 @@ namespace XCEngine ulong rasterPassHandle, int textureHandle); + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern bool + Rendering_ScriptableRenderContext_AddRasterPassReadDepthTexture( + ulong nativeHandle, + ulong rasterPassHandle, + int textureHandle); + [MethodImpl(MethodImplOptions.InternalCall)] internal static extern bool Rendering_ScriptableRenderContext_SetRasterPassColorAttachment( @@ -494,6 +501,13 @@ namespace XCEngine int colorAttachmentIndex, int textureHandle); + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern bool + Rendering_ScriptableRenderContext_SetRasterPassDepthAttachment( + ulong nativeHandle, + ulong rasterPassHandle, + int textureHandle); + [MethodImpl(MethodImplOptions.InternalCall)] internal static extern bool Rendering_ScriptableRenderContext_SetRasterPassColorScaleFullscreenExecution( diff --git a/managed/XCEngine.ScriptCore/Rendering/Graph/RenderGraphRasterPassBuilder.cs b/managed/XCEngine.ScriptCore/Rendering/Graph/RenderGraphRasterPassBuilder.cs index 6f72bcb5..662097fa 100644 --- a/managed/XCEngine.ScriptCore/Rendering/Graph/RenderGraphRasterPassBuilder.cs +++ b/managed/XCEngine.ScriptCore/Rendering/Graph/RenderGraphRasterPassBuilder.cs @@ -18,9 +18,12 @@ namespace XCEngine.Rendering private readonly string m_passName; private readonly List m_readTextures = new List(); + private readonly List m_readDepthTextures = + new List(); private readonly List m_colorAttachments = new List(); private RenderGraphTextureHandle m_sourceColorTexture; + private RenderGraphTextureHandle m_depthAttachment; private Vector4 m_vectorPayload; private string m_shaderPath = string.Empty; private string m_shaderPassName = string.Empty; @@ -79,6 +82,17 @@ namespace XCEngine.Rendering return this; } + public RenderGraphRasterPassBuilder UseDepthTexture( + RenderGraphTextureHandle texture) + { + if (texture.isValid) + { + m_readDepthTextures.Add(texture); + } + + return this; + } + public RenderGraphRasterPassBuilder SetColorAttachment( RenderGraphTextureHandle texture, int index = 0) @@ -99,6 +113,13 @@ namespace XCEngine.Rendering return this; } + public RenderGraphRasterPassBuilder SetDepthAttachment( + RenderGraphTextureHandle texture) + { + m_depthAttachment = texture; + return this; + } + public RenderGraphRasterPassBuilder SetColorScaleFullscreenExecution( Vector4 colorScale) @@ -184,6 +205,25 @@ namespace XCEngine.Rendering } } + for (int i = 0; i < m_readDepthTextures.Count; ++i) + { + RenderGraphTextureHandle readDepthTexture = + m_readDepthTextures[i]; + if (!readDepthTexture.isValid) + { + continue; + } + + if (!InternalCalls + .Rendering_ScriptableRenderContext_AddRasterPassReadDepthTexture( + m_context.nativeHandle, + nativePassHandle, + readDepthTexture.nativeIndex)) + { + return false; + } + } + for (int i = 0; i < m_colorAttachments.Count; ++i) { RenderGraphTextureHandle colorAttachment = @@ -204,6 +244,16 @@ namespace XCEngine.Rendering } } + if (m_depthAttachment.isValid && + !InternalCalls + .Rendering_ScriptableRenderContext_SetRasterPassDepthAttachment( + m_context.nativeHandle, + nativePassHandle, + m_depthAttachment.nativeIndex)) + { + return false; + } + bool configuredExecution; switch (m_executionKind) {