From a6f7530855d04069b22305038676fb9cadb3dbcf Mon Sep 17 00:00:00 2001 From: ssdfasd <2156608475@qq.com> Date: Tue, 21 Apr 2026 00:34:46 +0800 Subject: [PATCH] refactor(srp): infer fullscreen stages from renderer pass queues --- ...en旧桥清理与Builder统一计划_阶段归档_2026-04-20.md} | 0 ...agedSceneDrawAPI计划_完成归档_2026-04-21.md} | 0 ...RenderStateBlock计划_完成归档_2026-04-21.md} | 0 ...screenStage归位计划_完成归档_2026-04-21.md | 99 +++++++++++++++++++ ...lRendererData配置层计划_完成归档_2026-04-21.md} | 0 ...al默认ScenePass数据化计划_完成归档_2026-04-21.md} | 0 .../ColorScalePostProcessRendererFeature.cs | 3 +- .../Universal/RenderObjectsRendererFeature.cs | 3 +- .../Rendering/Universal/ScriptableRenderer.cs | 67 +++++++++++++ .../Universal/ScriptableRendererData.cs | 8 ++ .../Rendering/Universal/UniversalRenderer.cs | 3 +- 11 files changed, 177 insertions(+), 6 deletions(-) rename docs/{plan/SRP_ManagedFullscreen旧桥清理与Builder统一计划_2026-04-20.md => used/SRP_ManagedFullscreen旧桥清理与Builder统一计划_阶段归档_2026-04-20.md} (100%) rename docs/{plan/SRP_ManagedSceneDrawAPI计划_2026-04-20.md => used/SRP_ManagedSceneDrawAPI计划_完成归档_2026-04-21.md} (100%) rename docs/{plan/SRP_RenderStateBlock计划_2026-04-20.md => used/SRP_RenderStateBlock计划_完成归档_2026-04-21.md} (100%) create mode 100644 docs/used/SRP_UniversalFullscreenStage归位计划_完成归档_2026-04-21.md rename docs/{plan/SRP_UniversalRendererData配置层计划_2026-04-20.md => used/SRP_UniversalRendererData配置层计划_完成归档_2026-04-21.md} (100%) rename docs/{plan/SRP_Universal默认ScenePass数据化计划_2026-04-20.md => used/SRP_Universal默认ScenePass数据化计划_完成归档_2026-04-21.md} (100%) diff --git a/docs/plan/SRP_ManagedFullscreen旧桥清理与Builder统一计划_2026-04-20.md b/docs/used/SRP_ManagedFullscreen旧桥清理与Builder统一计划_阶段归档_2026-04-20.md similarity index 100% rename from docs/plan/SRP_ManagedFullscreen旧桥清理与Builder统一计划_2026-04-20.md rename to docs/used/SRP_ManagedFullscreen旧桥清理与Builder统一计划_阶段归档_2026-04-20.md diff --git a/docs/plan/SRP_ManagedSceneDrawAPI计划_2026-04-20.md b/docs/used/SRP_ManagedSceneDrawAPI计划_完成归档_2026-04-21.md similarity index 100% rename from docs/plan/SRP_ManagedSceneDrawAPI计划_2026-04-20.md rename to docs/used/SRP_ManagedSceneDrawAPI计划_完成归档_2026-04-21.md diff --git a/docs/plan/SRP_RenderStateBlock计划_2026-04-20.md b/docs/used/SRP_RenderStateBlock计划_完成归档_2026-04-21.md similarity index 100% rename from docs/plan/SRP_RenderStateBlock计划_2026-04-20.md rename to docs/used/SRP_RenderStateBlock计划_完成归档_2026-04-21.md diff --git a/docs/used/SRP_UniversalFullscreenStage归位计划_完成归档_2026-04-21.md b/docs/used/SRP_UniversalFullscreenStage归位计划_完成归档_2026-04-21.md new file mode 100644 index 00000000..ae43f06c --- /dev/null +++ b/docs/used/SRP_UniversalFullscreenStage归位计划_完成归档_2026-04-21.md @@ -0,0 +1,99 @@ +# SRP Universal Fullscreen Stage 归位计划 2026-04-21 + +## 1. 阶段目标 + +把 `PostProcess` / `FinalOutput` 这两个 fullscreen stage 的默认规划逻辑,从零散的 feature 手工 `ConfigureCameraFramePlan()` 请求,收回到 renderer/pass 队列本身。 + +这一阶段完成后,要达到: + +1. renderer pass event 本身就能表达 pass 属于 `MainScene` / `PostProcess` / `FinalOutput` +2. `ScriptableRenderer` 可以基于已构建的 pass 队列自动请求 fullscreen stage +3. Universal 内建 renderer 和首方 feature 不再依赖手工点亮默认 stage +4. feature 继续负责扩展 pass,而不是承担默认 stage orchestration + +## 2. 当前问题 + +目前的主问题不是 `mainScene`,而是 fullscreen stage 规划还不够像 Unity: + +1. `ColorScalePostProcessRendererFeature` 这类 feature 还要自己实现 `ConfigureCameraFramePlan()` +2. `AddRenderPasses()` 里仍然存在按当前 stage 判断是否 enqueue 的逻辑 +3. stage 是否存在,并不是由 renderer 的 pass 拓扑自然推导出来 + +这会导致: + +1. stage planning 逻辑散落在 feature 层 +2. renderer 不能单独说明“我这一帧会组织哪些 stage” +3. 越往后做 fullscreen/post-process,越容易继续堆临时逻辑 + +## 3. 设计原则 + +这一步按 Unity URP 的职责划分来做: + +1. `ScriptableRenderPass.renderPassEvent` 决定 pass 所属 stage +2. `ScriptableRenderer` 负责组织 pass 队列并从中推导 stage 需求 +3. `ScriptableRendererFeature` 负责提供 pass +4. `ConfigureCameraFramePlan()` 只保留给特殊场景的显式覆盖,不再承担默认主链职责 + +## 4. 本阶段范围 + +包括: + +1. 给 `ScriptableRenderer` 增加基于 pass 队列的 fullscreen stage 自动规划 +2. 去掉 Universal 首方 renderer/feature 中按当前 stage 才 enqueue pass 的硬判断 +3. 让 `ColorScalePostProcessRendererFeature` 回到“只提供 post-process pass”的职责 +4. 保持现有 main-scene / post-process 行为不回退 +5. 重编译 `XCEditor` +6. 运行旧版 `editor/bin/Debug/XCEngine.exe` 冒烟至少 10 秒 + +不包括: + +1. 多 renderer 选择 +2. deferred renderer +3. renderer inspector UI +4. final color policy 从 pipeline asset 挪到 renderer data + +## 5. 实施步骤 + +### Step 1:让 renderer 能基于 pass 队列规划 fullscreen stage + +新增 renderer planning 入口: + +1. 构建当前 renderer pass 队列 +2. 扫描是否存在 `PostProcess` pass +3. 扫描是否存在 `FinalOutput` pass +4. 自动请求对应 fullscreen stage + +### Step 2:清理 Universal 首方 stage-gated enqueue + +把这些逻辑从“当前 stage 才 enqueue”改成“统一 enqueue,由 pass event 决定在哪个 stage 生效”: + +1. `UniversalRenderer` +2. `RenderObjectsRendererFeature` +3. `ColorScalePostProcessRendererFeature` + +### Step 3:验证旧 feature 扩展仍然可用 + +确保: + +1. main-scene pass 仍只在 main-scene record +2. post-process pass 仍只在 post-process record +3. stage 规划由 renderer 主链自动完成 + +### Step 4:编译与冒烟 + +固定流程: + +1. `cmake --build . --config Debug --target XCEditor` +2. 启动 `editor/bin/Debug/XCEngine.exe` +3. 冒烟至少 10 秒 +4. 检查 `editor/bin/Debug/editor.log` + +## 6. 验收标准 + +本阶段收口后必须满足: + +1. Universal 首方 post-process feature 不再依赖手工 `ConfigureCameraFramePlan()` 请求默认 stage +2. renderer 可以从 pass queue 自动推导 `PostProcess` / `FinalOutput` +3. `AddRenderPasses()` 不再大量依赖当前 stage 判定才 enqueue +4. `XCEditor` 编译通过 +5. 旧 editor 冒烟通过 diff --git a/docs/plan/SRP_UniversalRendererData配置层计划_2026-04-20.md b/docs/used/SRP_UniversalRendererData配置层计划_完成归档_2026-04-21.md similarity index 100% rename from docs/plan/SRP_UniversalRendererData配置层计划_2026-04-20.md rename to docs/used/SRP_UniversalRendererData配置层计划_完成归档_2026-04-21.md diff --git a/docs/plan/SRP_Universal默认ScenePass数据化计划_2026-04-20.md b/docs/used/SRP_Universal默认ScenePass数据化计划_完成归档_2026-04-21.md similarity index 100% rename from docs/plan/SRP_Universal默认ScenePass数据化计划_2026-04-20.md rename to docs/used/SRP_Universal默认ScenePass数据化计划_完成归档_2026-04-21.md diff --git a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ColorScalePostProcessRendererFeature.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ColorScalePostProcessRendererFeature.cs index 85043c3c..594a952d 100644 --- a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ColorScalePostProcessRendererFeature.cs +++ b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ColorScalePostProcessRendererFeature.cs @@ -61,8 +61,7 @@ namespace XCEngine.Rendering.Universal RenderingData renderingData) { if (renderer == null || - renderingData == null || - !renderingData.isPostProcessStage) + renderingData == null) { return; } diff --git a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RenderObjectsRendererFeature.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RenderObjectsRendererFeature.cs index 2cb7ca62..ee5633ab 100644 --- a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RenderObjectsRendererFeature.cs +++ b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RenderObjectsRendererFeature.cs @@ -57,8 +57,7 @@ namespace XCEngine.Rendering.Universal RenderingData renderingData) { if (renderer == null || - renderingData == null || - !renderingData.isMainSceneStage) + renderingData == null) { return; } diff --git a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRenderer.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRenderer.cs index bfc1f0f6..9e6cccdb 100644 --- a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRenderer.cs +++ b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRenderer.cs @@ -89,6 +89,12 @@ namespace XCEngine.Rendering.Universal return SupportsRendererRecording(context); } + internal void ConfigureCameraFramePlanInstance( + ScriptableRenderPipelinePlanningContext context) + { + ConfigureCameraFramePlan(context); + } + internal bool RecordRendererInstance( RendererRecordingContext context) { @@ -170,6 +176,67 @@ namespace XCEngine.Rendering.Universal new RendererRecordingContext(context)); } + protected virtual void ConfigureCameraFramePlan( + ScriptableRenderPipelinePlanningContext context) + { + if (context == null) + { + return; + } + + BuildPassQueue(new RenderingData(CameraFrameStage.MainScene)); + + bool hasPostProcessPass = false; + bool hasFinalOutputPass = false; + for (int i = 0; i < m_activePassQueue.Count; ++i) + { + ScriptableRenderPass renderPass = m_activePassQueue[i]; + if (renderPass == null) + { + continue; + } + + CameraFrameStage passStage; + if (!ScriptableRenderPass.TryResolveStage( + renderPass.renderPassEvent, + out passStage)) + { + continue; + } + + if (passStage == CameraFrameStage.PostProcess) + { + hasPostProcessPass = true; + } + else if (passStage == + CameraFrameStage.FinalOutput) + { + hasFinalOutputPass = true; + } + } + + if (hasPostProcessPass && + !context.IsStageRequested( + CameraFrameStage.PostProcess)) + { + context.RequestFullscreenStage( + CameraFrameStage.PostProcess, + CameraFrameColorSource.MainSceneColor, + hasFinalOutputPass); + } + + if (hasFinalOutputPass && + !context.IsStageRequested( + CameraFrameStage.FinalOutput)) + { + context.RequestFullscreenStage( + CameraFrameStage.FinalOutput, + hasPostProcessPass + ? CameraFrameColorSource.PostProcessColor + : CameraFrameColorSource.MainSceneColor); + } + } + private void BuildPassQueue( RenderingData renderingData) { diff --git a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRendererData.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRendererData.cs index 0da54449..63ab4c7e 100644 --- a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRendererData.cs +++ b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRendererData.cs @@ -100,6 +100,14 @@ namespace XCEngine.Rendering.Universal { ConfigureCameraFramePlan(context); + ScriptableRenderer renderer = + GetRendererInstance(); + if (renderer != null) + { + renderer.ConfigureCameraFramePlanInstance( + context); + } + ScriptableRendererFeature[] rendererFeatures = GetRendererFeatures(); for (int i = 0; i < rendererFeatures.Length; ++i) diff --git a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRenderer.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRenderer.cs index c1ba61d9..d9cacd97 100644 --- a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRenderer.cs +++ b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRenderer.cs @@ -79,8 +79,7 @@ namespace XCEngine.Rendering.Universal protected override void AddRenderPasses( RenderingData renderingData) { - if (renderingData == null || - !renderingData.isMainSceneStage) + if (renderingData == null) { return; }