Files
XCEngine/docs/plan/SRP_Runtime_v1_2026-04-17.md

9.8 KiB
Raw Blame History

SRP Runtime v1 实施计划 2026-04-17

1. 结论

现在可以正式进入 SRP 主线了。

但这里的“开始搭 SRP”准确含义不是

  1. 直接开做 URP 包层。
  2. 直接做延迟渲染。
  3. 直接把阴影、高斯、体积、后处理全部搬到 C#。

本阶段正确目标是:

Native RenderGraph / Planning / Execution -> Managed SRP Runtime v1 -> Managed Forward Pipeline v1 -> 之后再开 URP-like Package

也就是说,下一阶段确实是搭 SRP但搭的是 SRP Runtime v1,不是直接搭“最终版 URP”。


2. 为什么现在可以开始做 SRP

当前 native 渲染层已经具备进入 SRP 主线的前提:

  1. RenderGraph 已经可用,不是空壳。
  2. CameraFramePlan 已经把每相机渲染组织稳定下来。
  3. CameraFrameStage 和 stage dispatch 已经把主链拆清楚了。
  4. BuiltinForwardPipeline 已经能把 MainScene 录进 render graph。
  5. ScriptableRenderPipelineHost 已经提供了 stage recorder + fallback renderer 的宿主接缝。
  6. 默认 pipeline 工厂已经能从 managed or default asset 入口创建渲染管线。

所以当前真正缺的已经不是 native 渲染骨架,而是:

  1. managed pipeline 在 runtime 里真实存在。
  2. native 能持有并调用 managed pipeline。
  3. managed 层拿到最小可用的渲染上下文。

换句话说,native 这一段已经够了,下一刀就该切 SRP runtime


3. 本阶段目标

本阶段收口目标只有四个:

  1. native 能创建并持有真实 managed ScriptableRenderPipelineAsset / ScriptableRenderPipeline 实例。
  2. ScriptableRenderPipelineHost 能稳定回调到 managed pipeline 参与 MainScene stage graph 录制。
  3. managed 拿到一个最小可用的 ScriptableRenderContext v1
  4. 跑通一条最小 managed forward pipeline 主链,同时保留 builtin forward fallback。

如果这四件事没有形成闭环,就不算进入 SRP 主线。


4. 本阶段明确不做的事

这一阶段明确不做下面这些内容:

  1. 不开 URP-like package
  2. 不做 deferred pipeline。
  3. 不把阴影、后处理、高斯、体积的组织权全部搬到 C#。
  4. 不直接对外暴露原始 RHI 或原始 native internal type。
  5. 不追求第一版就完全对齐 Unity 的 ScriptableRenderContextCommandBuffer

原因很简单:

当前根问题不是“缺某个 renderer feature”而是“managed pipeline 运行时还没真正成立”。


5. 本阶段的正确边界

留在 C++ 的

  1. RHI
  2. RenderGraph
  3. frame planning / stage dispatch / graph compile / execute
  4. scene extraction / culling / frame data
  5. builtin renderer 的底层执行实现

开始上移到 managed 的

  1. pipeline asset 的实例化和生命周期
  2. pipeline 的主场景录制组织
  3. 受控的 render context 封装
  4. 后续 URP-like 包层需要依赖的 SRP runtime 接缝

本阶段的核心原则是:

C++ 继续负责渲染内核C# 开始接管渲染组织。


6. 分阶段实施顺序

Phase A: 建立通用 managed object runtime

目标:

  1. MonoScriptRuntime 中补齐“任意 managed 对象”的创建、持有、释放能力。
  2. 不再只围绕 ScriptComponentGameObjectComponent wrapper 打转。
  3. 能按类型描述创建 asset 实例和 pipeline 实例。
  4. 能稳定保存 GCHandle 或等价持有关系。
  5. 能稳定回调实例方法并正确处理异常。

这一阶段是整个 SRP runtime 的硬前提。

如果这一步不成立,后面一切 SRP API 都只是空壳。

Phase B: 把 render pipeline asset 从“类型描述”升级成“真实 runtime 对象”

当前 GraphicsSettings.renderPipelineAssetType 的语义还是:

把一个 C# 类型名写给 native

这一阶段需要升级成:

  1. native 能根据类型创建真实 managed asset 实例。
  2. managed asset 能创建真实 managed pipeline 实例。
  3. native 能持有 asset / pipeline 生命周期。
  4. ManagedScriptableRenderPipelineAsset 不再只是 descriptor-only 包装。

第一版允许继续用 Type 作为 bootstrap 入口,但 native 内部不能再停留在 descriptor 模型。

Phase C: 实现真实的 managed render pipeline bridge

目标:

  1. ManagedRenderPipelineBridgeMonoScriptRuntime 提供真实实现。
  2. ManagedScriptableRenderPipelineAsset 创建的 host 能绑定到真实 managed pipeline。
  3. ScriptableRenderPipelineHost 能调用 managed pipeline 的 stage 录制方法。
  4. bridge 不再只是测试用 mock seam。

这一阶段完成后managed pipeline 才算真正“活过来”。

Phase D: 定义 ScriptableRenderContext v1

第一版不要追求大而全。

只需要提供最小可用能力:

  1. 查询当前 camera frame / stage 基本信息。
  2. 参与 MainScene render graph 录制。
  3. 调用 native scene renderer 绘制 Opaque / Skybox / Transparent
  4. 访问最基础的 source / target / blackboard 语义。
  5. 预留 fullscreen / blit 接口,但不强求一步到位。

这一版不直接暴露 raw RenderGraphTextureHandle 和 raw RenderSurface 给用户脚本。

Phase E: 跑通最小 managed forward pipeline v1

目标:

  1. 用 C# 创建一个 managed pipeline。
  2. managed pipeline 能声明支持 MainScene stage graph。
  3. managed pipeline 能在 MainScene 调 native forward scene renderer。
  4. editor / runtime 在切到 managed pipeline 后仍能正常渲染。
  5. builtin forward 仍可作为 fallback 路径保留。

这一阶段完成后,才算正式进入 “SRP 已经开始工作” 的状态。


7. 第一批要改的文件

Native 侧核心落点

  1. engine/src/Scripting/Mono/MonoScriptRuntime.cpp
  2. engine/include/XCEngine/Rendering/Pipelines/ManagedScriptableRenderPipelineAsset.h
  3. engine/src/Rendering/Pipelines/ManagedScriptableRenderPipelineAsset.cpp
  4. engine/include/XCEngine/Rendering/Pipelines/ScriptableRenderPipelineHost.h
  5. engine/src/Rendering/Pipelines/ScriptableRenderPipelineHost.cpp
  6. engine/src/Rendering/Internal/RenderPipelineFactory.cpp

Managed 侧核心落点

  1. managed/XCEngine.ScriptCore/InternalCalls.cs
  2. managed/XCEngine.ScriptCore/GraphicsSettings.cs
  3. managed/XCEngine.ScriptCore/ScriptableRenderPipelineAsset.cs
  4. managed/XCEngine.ScriptCore/ScriptableRenderPipeline.cs
  5. 新增 managed/XCEngine.ScriptCore/ScriptableRenderContext.cs
  6. 可能新增最小 managed/XCEngine.ScriptCore/Rendering/* 辅助类型

测试与验证

  1. managed/GameScripts/RenderPipelineApiProbe.cs
  2. 新增 native / managed bridge smoke tests
  3. editor 冒烟场景验证

8. 代码层面的实施拆分

建议按下面的提交粒度推进,而不是一口气乱改:

Commit 1: managed object runtime 基础设施

完成后应该能:

  1. 按类型创建普通 managed 对象。
  2. 持有并释放对象句柄。
  3. 回调实例方法。

Commit 2: managed pipeline asset / pipeline 生命周期

完成后应该能:

  1. GraphicsSettings.renderPipelineAssetType 生成真实 asset 实例。
  2. 从 asset 生成真实 pipeline 实例。
  3. 由 native 负责持有这两个对象。

Commit 3: host 与 managed bridge 接通

完成后应该能:

  1. ScriptableRenderPipelineHost 绑定真实 managed stage recorder。
  2. MainScene 录制可回调到 managed pipeline。

Commit 4: ScriptableRenderContext v1

完成后应该能:

  1. managed 侧拿到最小上下文。
  2. managed 能调用 native scene renderer 画主场景阶段。

Commit 5: managed forward pipeline v1 smoke path

完成后应该能:

  1. 用 managed pipeline 跑通主场景。
  2. 与 builtin forward fallback 共存。

9. 关键风险

风险 1: Mono 生命周期和 GC handle 泄漏

这是第一风险。

如果 object runtime 持有策略不稳后面渲染管线切换、domain reload、editor 热切换都会出问题。

风险 2: 把 host 做成“全局单例桥”

如果 bridge 继续停留在粗糙全局状态,后面多实例、多场景、重建 pipeline 都会很难收口。

风险 3: 过早暴露原始 native 类型

如果第一版就把 raw graph/resource handle 暴露给 managedAPI 很快会固化,后面很难收拾。

风险 4: builtin forward 与 managed forward 边界不清

如果 managed 直接依赖 BuiltinForwardPipeline 私有实现细节,后面就不是 SRP而是“脚本包一层 builtin forward”。


10. 阶段验收标准

本阶段收口时,必须同时满足下面这些条件:

  1. native 里存在真实的 managed pipeline bridge不再只是 mock seam。
  2. GraphicsSettings 能驱动创建真实 managed asset / pipeline 实例。
  3. ScriptableRenderPipelineHost 能稳定回调 managed pipeline 的 MainScene 录制。
  4. managed 侧存在最小 ScriptableRenderContext v1
  5. 一条最小 managed forward pipeline 能真实跑出主场景。
  6. builtin forward fallback 路径仍然可用。
  7. editor 编译通过,基础冒烟渲染不崩。

只要这 7 条有一条不成立,这一阶段就不能算收口。


11. 本阶段完成后,下一阶段才做什么

SRP Runtime v1 收口之后,下一阶段才适合开始:

  1. URP-like asset
  2. RendererData
  3. RendererFeature
  4. RenderPassEvent
  5. 阴影 / 后处理 / 高斯 / 体积 等组织权逐步上移

也就是说:

现在可以开始搭 SRP。

但准确说法应该是:

现在开始搭的是 SRP Runtime v1,不是直接搭最终版 URP。


12. 下一刀从哪里下

下一步第一刀就应该下在:

MonoScriptRuntime -> 通用 managed object runtime -> 真实 ManagedRenderPipelineBridge

这是整个 SRP 主线最根上的卡点。

如果这里不先解决,后面无论做多少 ScriptableRenderPipelineAssetScriptableRenderContextRendererFeature,都只是外壳。