Files
XCEngine/docs/plan/SRP_Mainline_2026-04-16.md

375 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 Mainline 2026-04-16
## 1. 结论
现在可以正式切到 `SRP` 主线。
但这里的“切到 SRP 主线”不是直接开做 `URP` 包层,也不是马上把所有渲染效果搬到 C#。
当前最正确的主线是:
`Native RenderGraph / Planning / Execution`
`-> Managed SRP Runtime`
`-> Managed Forward Pipeline v1`
`-> URP-like 官方包层`
也就是说,下一阶段的真正目标不是“做一个叫 SRP 的壳”,而是先把:
1. `managed pipeline asset` 真正实例化出来
2. `managed pipeline` 真正被 native 持有并回调
3. `C#` 真正能组织主场景 render graph 录制
这三件事做成闭环。
在这之前,`URP-like package` 还不能开工。
## 2. 当前状态判断
### 2.1 已经具备的东西
当前 native 底座已经够你正式进入 SRP 主线:
1. `RenderGraph` 已经不是空壳builder / compiler / executor 都在工作。
2. `ScriptableRenderPipelineHost` 已经能把 “stage recorder + fallback renderer” 组合起来。
3. `BuiltinForwardPipeline` 已经支持按 `MainScene` stage 录制 render graph。
4. 默认 pipeline 工厂已经能从 “managed or default asset” 入口走。
这说明 native 侧已经有了 SRP runtime 可以依附的承接点。
### 2.2 还没具备的东西
当前 managed 侧还远远没有形成真正的 SRP runtime
1. `GraphicsSettings` 现在只是在 native 里记录了一个 pipeline asset 类型描述,不是 asset 实例。
2. `ManagedScriptableRenderPipelineAsset` 现在只是 “fallback host + optional stage recorder bridge”。
3. 真正的 `ManagedRenderPipelineBridge` 实现根本还没接进运行时,当前只有测试里在 mock。
4. `ScriptableRenderPipelineAsset` 只有 `CreatePipeline()` 占位,没有 frame/request planning 能力。
5. `ScriptableRenderPipeline` 只有 `SupportsStageRenderGraph/RecordStageRenderGraph` 两个最小占位方法,而且没有上下文对象。
6. C# 层没有 `ScriptableRenderContext`、没有 `CommandBuffer`、没有 `RendererFeature`、没有 `Renderer` 抽象。
所以当前状态不是 “SRP 已经差不多了”,而是:
`native SRP host seam 已经有了`
`managed SRP runtime 还没开始真正落地`
## 3. 当前最核心的架构根因
### 3.1 现在的 managed 入口只是“选择器”,不是“运行时”
当前 `GraphicsSettings.renderPipelineAssetType` 的语义本质上是:
`把一个 C# 类型名写回 native`
它没有解决下面这些真正关键的问题:
1. asset 谁实例化
2. pipeline 谁实例化
3. 生命周期谁管理
4. native 如何回调到具体 pipeline 对象
5. pipeline 如何持有自己的配置
这意味着现在的 API 形态本身还不是未来可长期保留的最终形态。
### 3.2 当前 bridge 只允许“补一个 stage recorder”这还不是 SRP
现在 `ManagedScriptableRenderPipelineAsset` 的工作方式是:
1. 先创建 native fallback host
2. 再给 host 塞一个可选 `stage recorder`
这条路只能得到:
`C# 向 builtin forward 注入一个 graph 录制钩子`
而不是:
`C# 自己拥有一条 render pipeline`
如果这条边界不改,后面做出来的只会是“脚本包装版 builtin forward”不是 Unity 意义上的 `SRP`
### 3.3 当前 pipeline API 颗粒度太粗,无法支撑未来 SRP/URP
现在 managed pipeline 只有:
1. `SupportsStageRenderGraph(CameraFrameStage)`
2. `RecordStageRenderGraph(CameraFrameStage)`
问题是它没有:
1. frame context
2. camera context
3. render graph builder/context wrapper
4. scene draw / fullscreen / blit / renderer feature 注入接口
5. request/frame planning hook
这意味着即使把 bridge 打通C# 也拿不到足够的组织能力。
### 3.4 当前 `BuiltinForwardPipeline` 仍然太像“完整管线”,还不像“可被 SRP 调度的 renderer”
现在 builtin forward 内部已经有:
1. `SceneRenderFeatureHost`
2. scene phase
3. stage graph builder
但这些能力大部分仍然锁在 `BuiltinForwardPipeline` 这个整管线对象内部。
对未来 SRP 来说,更正确的方向应该是:
1. `BuiltinForward` 退化为 native 默认 renderer 实现
2. 把可复用的 scene rendering contract 抽成稳定 native renderer API
3. 让 managed pipeline 调用这个 renderer API 组织主场景,而不是直接操纵 `BuiltinForwardPipeline` 私有实现
### 3.5 当前 asset API 太弱,无法承担 Unity 风格 pipeline asset 角色
Unity 里的 pipeline asset 至少要承担:
1. 创建 pipeline 实例
2. 保存 renderer 配置
3. 保存阴影/后处理/renderer data 等默认策略
4. 驱动 camera/frame 规划策略
而现在的 managed asset 还没有这些入口。
这会直接阻塞未来:
1. `URP Asset`
2. `RendererData`
3. `RendererFeature`
4. shadow/post-process 默认策略迁移
## 4. 正确目标架构
正确的长期结构应该是:
`RHI`
`-> Native Render Kernel`
`-> Native RenderGraph`
`-> Native Renderer Contract`
`-> Managed SRP Runtime`
`-> Managed Universal Pipeline Package`
`-> 用户自定义 Pipeline / Feature / Pass`
其中边界必须明确:
### 4.1 留在 C++ 的东西
1. `RHI`
2. `RenderGraph`
3. planning / execution 主框架
4. scene extraction / culling / resource lifetime
5. native draw/fullscreen/feature primitive
6. builtin renderer 的底层实现
### 4.2 去到 managed 的东西
1. `ScriptableRenderPipelineAsset`
2. `ScriptableRenderPipeline`
3. `ScriptableRenderContext`
4. `UniversalRenderPipelineAsset`
5. `UniversalRenderer / RendererFeature / RenderPass`
6. 用户自定义管线逻辑
### 4.3 不应该长期停留在 C++ builtin pipeline 里的东西
这些能力最终应该逐步上移到 `URP-like package` 的组织层:
1. 阴影默认策略
2. post-process 组合策略
3. gaussian / volumetric / custom effect 的注入时机
4. renderer feature 的启用/排序/注入逻辑
但注意:
“上移”指的是组织和调度上移,不是把底层 draw code 全部改成 C#。
## 5. 执行顺序
### Step 1: 先做通用 managed object runtime
这是第一刀,必须先做。
目标:
1.`MonoScriptRuntime` 里补通用 managed object 创建/持有/释放能力
2. 不再只支持 `ScriptComponent` 实例和 `GameObject/Component` wrapper
3. 能按类描述创建任意 managed 对象
4. 能持有 GC handle
5. 能反射调用实例方法
6. 能稳定记录异常并向 native 返回失败
这一步是后面所有 SRP runtime 的硬前提。
没有这个asset/pipeline 实例生命周期根本没法成立。
### Step 2: 把 managed pipeline asset 从“类型描述”提升成“真实 runtime 对象”
目标:
1. native 不再只拿到 `assembly/namespace/class` 描述
2. native 能真正创建一个 managed asset 实例
3. managed asset 能产出 managed pipeline 实例
4. runtime 能持有 asset/pipeline 的生命周期
这一阶段里,`GraphicsSettings.renderPipelineAssetType` 可以临时继续作为 bootstrap 入口,
但 native 内部不能再停留在 descriptor-only 语义。
后面如果你要彻底对齐 Unity再把 public API 从 `Type` 收敛到 asset instance。
### Step 3: 实现真正的 managed render pipeline bridge
目标:
1.`MonoScriptRuntime` 提供真实的 `ManagedRenderPipelineBridge`
2. `ManagedScriptableRenderPipelineAsset` 不再只接测试 mock
3. bridge 负责创建绑定到具体 managed pipeline 实例的 recorder/runtime object
4. native `ScriptableRenderPipelineHost` 能稳定回调到对应 managed pipeline
注意:
这一步不能继续维持“只有一个全局空 bridge”的临时状态。
### Step 4: 扩展 managed asset / pipeline API
当前 API 太弱,必须补接口。
至少要补到:
1. asset 侧有 request/frame planning 钩子
2. pipeline 侧有真正的 record context
3. pipeline 侧能拿到 camera/stage/frame 语义
4. pipeline 侧不再只有裸 `CameraFrameStage`
推荐的第一版方向:
1. `ScriptableRenderPipelineAsset`
- `CreatePipeline()`
- `ConfigureCameraRenderRequest(...)`
- `ConfigureCameraFramePlan(...)`
- `GetDefaultFinalColorSettings()` 或等价设置入口
2. `ScriptableRenderPipeline`
- `SupportsStageRenderGraph(...)`
- `RecordStageRenderGraph(...)`
- 参数升级为真正 context而不是只有 stage enum
### Step 5: 建立 `ScriptableRenderContext v1`
这是第二个根问题。
如果没有 `ScriptableRenderContext`C# 根本无法真正组织管线。
第一版不要直接暴露 RHI要暴露“受控的 native renderer contract”
1. record graph pass
2. 调用 builtin scene renderer 绘制 opaque / skybox / transparent
3. 执行 fullscreen / blit
4. 访问必要的 frame blackboard / source/target
5. 注入 renderer feature/pass
原则:
1. 不把 native 内部 planning 细节直接暴露给 C#
2. 不把 `RenderGraphTextureHandle``RenderSurface` 全量裸暴露成最终 API
3. 先做受控 wrapper再决定哪些能力继续上放
### Step 6: 把 builtin forward 拆成可复用的 native renderer contract
这一刀非常关键。
目标:
1. 不让 managed pipeline 直接依赖 `BuiltinForwardPipeline` 私有实现
2. 把主场景绘制能力抽成稳定 native renderer API
3. 让 builtin forward 退化为默认实现,而不是未来所有 SRP 的硬编码中心
正确方向类似:
`BuiltinForwardSceneRenderer`
或等价的
`UniversalRendererNativeBackend`
它至少要能被 managed 调度:
1. 主场景 phase 绘制
2. feature injection point
3. shadow sampling 相关约束
4. scene setup / pass begin/end
### Step 7: 做一条最小可用 managed forward pipeline
到这一步,才算真正开始“跑 SRP 主线”。
验收标准不是有类名,而是:
1. C# managed pipeline 可以被创建
2. managed pipeline 可以稳定回调
3. managed pipeline 可以录 `MainScene` graph
4. 这条 managed pipeline 可以替代当前 builtin forward 跑出主场景
这个阶段不要急着搬阴影/体积/高斯的全部组织权。
先把主链跑通。
### Step 8: 再开 URP-like package
只有当 Step 7 完成,才适合正式开:
`UniversalRenderPipelineAsset`
`UniversalRendererData`
`UniversalRenderer`
`RendererFeature`
`RenderPassEvent`
到这时才开始逐步把:
1. 阴影策略
2. post-process 组合
3. 体积/高斯等特性注入
从当前 native builtin 组织层往 managed package 迁。
## 6. 本阶段明确不做的事
现在不应该做:
1. 直接开 `URP`
2. 直接做 deferred pipeline
3. 直接把所有阴影/体积/高斯逻辑搬上 C#
4. 直接暴露一堆 raw native internal type 给脚本
这些都会把架构做歪。
## 7. 第一阶段收口标准
下面这些条件成立,才算 `SRP runtime v1` 收口:
1. 运行时存在真实的 managed bridge而不是测试 mock
2. native 能创建并持有 managed asset 与 managed pipeline 实例
3. managed pipeline 能稳定参与 camera frame graph 录制
4. managed forward pipeline 能替代 builtin forward 跑通主场景
5. builtin forward 仍保留 native fallback 路径
6. editor / runtime 渲染不会因为切到 managed pipeline 而失稳
## 8. 下一步从哪里下刀
下一步不要先碰 `URP`,也不要先改渲染效果组织。
第一刀就应该是:
`MonoScriptRuntime -> 通用 managed object runtime -> 真实 ManagedRenderPipelineBridge`
原因很简单:
当前最根的缺口不是某个 pass不是某个 renderer feature也不是 shader。
而是:
`managed pipeline 在运行时根本还不存在`
这个根因不先解决后面所有“SRP API”“URP 包”“阴影搬迁”都会变成空中楼阁。