Files
XCEngine/docs/plan/SRP_Runtime_v2_2026-04-18.md

349 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# SRP Runtime v2 计划 2026-04-18
## 1. 结论
当前阶段的下一步,不是继续做 editor 对接,也不是直接开做 deferred更不是马上把阴影、体积、高斯这些效果全部搬到 C#。
下一阶段的正确主线是:
`Native RenderGraph / Native Scene Renderer`
`-> Managed SRP Runtime v2`
`-> Managed Renderer / Feature / Pass 组织层`
`-> 之后再开正式的 URP-like package`
换句话说,`SRP runtime v1` 已经把“managed pipeline 能创建、能被 native 持有、能参与 stage record”这条链路打通了
`SRP runtime v2` 要解决的是另一件更关键的事:
**让 managed 侧不再只是“在 ScriptableRenderPipeline 里手写 stage”而是正式进入 Unity/URP 风格的 `Renderer / Feature / Pass` 组织模型。**
---
## 2. 当前状态判断
从现有代码看,下面这些能力已经成立:
1. `RenderGraph``CameraFramePlan`、stage dispatch、compile、execute 已经是工作状态。
2. `ScriptableRenderPipelineHost` 已经能作为 native 宿主,组合 `stage recorder + fallback renderer`
3. `ManagedScriptableRenderPipelineAsset` 已经不只是 descriptor 空壳,能够通过 bridge 创建 managed asset runtime。
4. `MonoScriptRuntime` 已经提供真实的 `ManagedRenderPipelineBridge`,不再只是测试 seam。
5. `ScriptableRenderContext` 已经有最小可用能力,能:
- `RecordScene()`
- `RecordScenePhase(...)`
- `RecordSceneInjectionPoint(...)`
- `RecordFullscreenPass(...)`
6. managed pipeline 已经能通过 `ScriptableRenderContext` 驱动 native `NativeSceneRecorder` 和 fullscreen pass sequence。
7. `ScriptableRenderPipelineAsset` 已经可以参与:
- `ConfigureCameraRenderRequest(...)`
- `ConfigureCameraFramePlan(...)`
- `GetDefaultFinalColorSettings()`
也就是说,**SRP runtime 的“宿主打通”问题已经不是主矛盾了。**
当前真正的主矛盾变成了:
1. managed 侧还没有 `ScriptableRenderer`
2. managed 侧还没有 `ScriptableRendererFeature`
3. managed 侧还没有 `ScriptableRenderPass`
4. managed 侧还没有 `RenderPassEvent`
5. pipeline 仍然直接在自己内部录制 stage缺少可组合的 renderer 层
这意味着你现在虽然已经能“用 C# 自定义渲染”,但它还不是 Unity/URP 那种成熟形态。
现在的形态更接近:
`Pipeline 直接写 RenderGraph 录制逻辑`
而不是:
`Pipeline -> Renderer -> Feature -> Pass`
---
## 3. 为什么下一步必须先做这个
如果这一层不先补起来,后面会出现三个结构性问题:
### 3.1 自定义能力会卡死在 `ScriptableRenderPipeline`
当前用户要改渲染逻辑,主要方式还是:
1. 继承 `ScriptableRenderPipeline`
2. 覆盖 `SupportsStageRenderGraph(...)`
3. 覆盖 `RecordStageRenderGraph(...)`
4. 直接手写 `RecordScenePhase / RecordSceneInjectionPoint / RecordFullscreenPass`
这条路能做 demo但不能支撑成熟工程。
因为它缺少:
1. renderer 内部 pass 队列
2. feature 注入点
3. renderer data / pipeline data
4. 面向 camera/frame 的稳定数据载体
继续沿这条路堆功能,最后只会变成“能工作的脚本版 builtin forward”而不是 Unity 意义上的 SRP/URP。
### 3.2 未来的阴影、后处理、体积、高斯没地方上移
你之前关心的那些东西,长期来看确实应该逐步从 C++ builtin 组织层往更高层移动,但它们要上移的不是裸 `Pipeline`,而是:
1. `Renderer`
2. `RendererFeature`
3. `RenderPass`
4. `RendererData`
如果这层不存在,那后面谈“把 shadow 组织权搬到 URP 层”“把 volumetric/gassian 搬到包层”,都会没有落点。
### 3.3 未来正式做 URP-like package 会缺承接面
真正的 URP-like package 不是只多几个 C# 类名,而是至少要有:
1. `PipelineAsset`
2. `RendererData`
3. `Renderer`
4. `RendererFeature`
5. `RenderPassEvent`
6. `RenderPass`
这几个层次如果不先在 SRP runtime 里长出来,后面直接开做 URP-like package 只会是壳子工程。
---
## 4. 本阶段目标
本阶段只做一件事:
**把当前“managed pipeline 直接录 stage”的模型升级成“managed pipeline 驱动 managed rendererrenderer 再组织 feature/pass”的模型。**
收口后应该形成这样的关系:
`ScriptableRenderPipelineAsset`
`-> ScriptableRenderPipeline`
`-> ScriptableRenderer`
`-> ScriptableRendererFeature`
`-> ScriptableRenderPass`
`-> ScriptableRenderContext`
`-> Native RenderGraph / NativeSceneRenderer`
这一步完成后,你这个引擎才算真正进入“能继续往 Unity SRP/URP 方向长”的状态。
---
## 5. 本阶段明确不做的内容
这一阶段不做下面这些事:
1. 不做 deferred pipeline。
2. 不做 lightmap / baking。
3. 不做 editor 侧 inspector、资源面板、renderer asset 可视化编辑。
4. 不把阴影、体积、高斯、后处理全部迁到 C#。
5. 不直接暴露 raw RHI、raw RenderGraph handle 给脚本层。
6. 不为了兼容临时方案而长期保留双轨 API。
注意:
这不是说这些东西以后不做,而是说**现在最值钱的一刀不是它们**。
现在最值钱的是先把 renderer 组织层做对。
---
## 6. 目标架构
### 6.1 继续留在 C++ 的部分
1. `RHI`
2. `RenderGraph`
3. frame planning / stage dispatch / graph compile / execute
4. scene extraction / culling / frame data
5. native scene renderer 执行内核
6. shadow / fullscreen / scene phase 的底层执行 primitive
### 6.2 开始在 managed 侧稳定下来的部分
1. `ScriptableRenderPipelineAsset`
2. `ScriptableRenderPipeline`
3. `ScriptableRenderer`
4. `ScriptableRendererFeature`
5. `ScriptableRenderPass`
6. `RenderPassEvent`
7. `RenderingData / CameraData` 这类组织层数据
### 6.3 这一阶段的核心原则
1. C++ 负责执行内核,不负责未来用户级管线组织。
2. managed 负责 renderer 组织,不直接持有底层 RHI 细节。
3. `BuiltinForwardPipeline` 继续做默认 native backend但不再是未来自定义渲染的最终承载层。
4. shadow / volumetric / gaussian 这类东西后续上移时,上移的是“组织权”,不是把所有 draw code 都改成 C#。
---
## 7. 分阶段实施
### Phase A: 建立 managed renderer 基础抽象
先把 managed 侧最基础的几块搭出来:
1. `ScriptableRenderer`
2. `ScriptableRendererFeature`
3. `ScriptableRenderPass`
4. `RenderPassEvent`
5. `RenderingData v1`
6. `CameraData v1`
第一版不要追求大而全,只解决最小闭环:
1. pass 能声明执行时机
2. renderer 能收集 pass
3. feature 能往 renderer 注入 pass
4. pipeline 能把 camera/frame 数据传给 renderer
### Phase B: 建立 renderer 的执行骨架
这一阶段要解决的是:
1. `ScriptableRenderer.EnqueuePass(...)`
2. pass 按 `RenderPassEvent` 排序
3. renderer 根据 event 把 pass 映射到当前已有的 native 能力:
- `RecordScenePhase(...)`
- `RecordSceneInjectionPoint(...)`
- `RecordFullscreenPass(...)`
4. renderer 能组织默认的主场景录制顺序
这里的关键不是“把所有 pass 都写复杂”,而是先把**组织模型**做出来。
### Phase C: 做一个最小前向 renderer
在 managed 侧做第一条真正能跑的 renderer 主链:
1. 默认 opaque pass
2. 默认 skybox pass
3. 默认 transparent pass
4. 默认 post-process/fullscreen pass
5. 允许 feature 在标准 injection point 前后插入 pass
注意这里的“前向 renderer”还不是最终版 URP只是
**一个 SRP runtime v2 上的 first-party renderer 验证样板。**
### Phase D: 把 pipeline asset 和 renderer data 关系收清楚
这一阶段要让 `ScriptableRenderPipelineAsset` 不再只是“创建 pipeline”还要能稳定持有 renderer 配置关系。
第一版建议先做到:
1. asset 持有一个默认 renderer data
2. pipeline 从 asset 创建 renderer
3. renderer feature 由 renderer data 决定启用顺序
4. camera/frame 规划仍然通过现有 planning context 接入
也就是说,要先有:
`PipelineAsset -> RendererData -> Renderer`
这条关系。
### Phase E: 替换 probe 级实现,形成正式 smoke path
这一阶段不再满足于 probe/demo而是要形成正式可回归的主链
1. 用 renderer/pass 模型重做当前 managed forward probe
2. 验证主场景 + fullscreen 仍然能工作
3. 验证 pipeline 切换时生命周期正确
4. 验证 native fallback 路径仍然可用
这一步收口后,才算本阶段真正完成。
---
## 8. 第一批要改的文件
### Managed 侧
优先会落在这些位置:
1. `managed/XCEngine.ScriptCore/ScriptableRenderPipelineAsset.cs`
2. `managed/XCEngine.ScriptCore/ScriptableRenderPipeline.cs`
3. `managed/XCEngine.ScriptCore/ScriptableRenderContext.cs`
4. 新增 `managed/XCEngine.ScriptCore/Rendering/*` 或等价目录
5. `managed/GameScripts/RenderPipelineApiProbe.cs`
第一批大概率会新增这些类型:
1. `ScriptableRenderer`
2. `ScriptableRendererFeature`
3. `ScriptableRenderPass`
4. `RenderPassEvent`
5. `RenderingData`
6. `CameraData`
### Native 侧
native 这一阶段不是主战场,但仍可能需要补桥接:
1. `engine/src/Scripting/Mono/MonoScriptRuntime.cpp`
2. `engine/include/XCEngine/Rendering/Pipelines/ManagedScriptableRenderPipelineAsset.h`
3. `engine/src/Rendering/Pipelines/ManagedScriptableRenderPipelineAsset.cpp`
只有当 managed renderer 需要额外上下文时,才增加新的 internal call / bridge 数据。
原则是:
**能用现有 `ScriptableRenderContext` 表达的,就不继续扩 raw native API。**
---
## 9. 验收标准
这一阶段收口时,至少要同时满足下面这些条件:
1. managed 侧存在正式的 `Renderer / Feature / Pass` 基础抽象。
2. `ScriptableRenderPipeline` 不再是唯一的直接录制组织层。
3. 一个 managed forward renderer 能通过 pass 队列稳定跑通主场景和 fullscreen。
4. feature 可以在标准 injection point 上插入 pass。
5. pipeline asset 能稳定持有 renderer 配置关系。
6. native `RenderGraph``NativeSceneRenderer`、fallback renderer 路径不被破坏。
7. editor 编译通过,并完成基础 smoke test。
只要上面任意一条不成立,这一阶段都不能算收口。
---
## 10. 完成本阶段之后,下一步才是什么
等这一阶段收口之后,下一步才适合正式进入更像 URP 的层级:
1. `UniversalRenderPipelineAsset`
2. `UniversalRendererData`
3. `UniversalRenderer`
4. 官方 first-party `RendererFeature`
5. 更成熟的 `RenderPassEvent`
6. 逐步把 shadow / volumetric / gaussian / post-process 的组织权上移
也就是说:
**不是现在不能往 Unity 的 SRP/URP 方向走而是现在要先把“SRP runtime 的 renderer 层”补齐。**
这一步做对了,后面你再做:
1. URP-like package
2. deferred
3. lightmap
4. renderer asset 资源化
5. editor 可视化配置
都会顺很多。
---
## 11. 下一刀从哪里下
下一步建议直接从 managed 侧开刀,顺序如下:
1. 先加 `ScriptableRenderer / ScriptableRenderPass / RenderPassEvent` 基础类型。
2. 再把当前 probe 级 `ManagedForwardRenderPipelineProbe` 改造成 renderer 驱动。
3. 确认 renderer/pass 模型能复用现有 `ScriptableRenderContext`
4. 只有在 managed 侧明确缺上下文时,再补 native internal call。
简单说,下一刀不是继续修 C++ 渲染内核,而是:
**开始正式搭 managed renderer 组织层。**