From caa54b7878a930c4990c7b05d1fef9819aa7daf0 Mon Sep 17 00:00:00 2001 From: ssdfasd <2156608475@qq.com> Date: Sun, 26 Apr 2026 19:09:09 +0800 Subject: [PATCH] Condense rendering agent guide --- engine/include/XCEngine/Rendering/AGENTS.md | 179 +++++++------------- 1 file changed, 61 insertions(+), 118 deletions(-) diff --git a/engine/include/XCEngine/Rendering/AGENTS.md b/engine/include/XCEngine/Rendering/AGENTS.md index 3f935eb6..8bfc4d32 100644 --- a/engine/include/XCEngine/Rendering/AGENTS.md +++ b/engine/include/XCEngine/Rendering/AGENTS.md @@ -1,125 +1,68 @@ -# Rendering 模块说明 +# Rendering Agent Guide -## 1. 目的 -- 本文记录当前渲染模块已经落地的真实边界,以及后续改动必须遵守的约束。 -- 本文优先描述代码现状和明确目标,不替代码补脑。 -- 如果实现与本文冲突,以代码为准;修完代码后同步更新本文。 +This file records the long-term rendering direction and the architecture cuts +already made. It is intentionally not a full map of the current implementation. -## 2. 当前主链 -```text -SceneRenderer - -> SceneRenderRequestPlanner - -> RenderPipelineHost - -> CameraFramePlanBuilder - -> CameraRenderer - -> DirectionalShadowRuntime - -> RenderSceneExtractor - -> CameraFrameGraph - -> RenderGraph Record / Compile / Execute -``` +If this file conflicts with the current code, trust the code and update this +file in the same change. -## 3. 当前顶层切换语义 -- 顶层切换目标向 Unity 对齐。 -- `GraphicsSettings.renderPipelineAsset == null`:走内置管线。 -- `GraphicsSettings.renderPipelineAsset != null`:走可编程渲染管线。 -- 当前内置管线默认直连 `BuiltinForwardPipelineAsset -> BuiltinForwardPipeline`。 -- 当前可编程管线默认直连 `ManagedScriptableRenderPipelineAsset -> ScriptableRenderPipelineHost`。 -- 运行时启动不得再偷偷自动选择 `ProjectDefaultRenderPipelineAsset`。 -- “当前项目里存在某个默认 SRP asset” 不是切换条件;唯一切换条件是 `GraphicsSettings.renderPipelineAsset`。 +## Long-Term Goal -## 4. 和 Unity SRP / URP 的对齐方式 -- `RenderPipelineAsset` 对应 Unity 的 `RenderPipelineAsset`。 -- `ScriptableRenderPipelineHost` 对应 native 侧承接托管 SRP 的 `RenderPipeline` 宿主。 -- managed 侧产品骨架仍是: - `ScriptableRenderPipelineAsset -> ScriptableRendererData -> ScriptableRenderer -> ScriptableRendererFeature/Pass` -- builtin 和 SRP 现在都必须是显式可切换的顶层路径,而不是“SRP 隐式优先,builtin 只是兜底”。 -- `ScriptableRenderPipelineHost` 里的 native backend 是 managed SRP 的绘制后端,不是 SRP stage 录制失败时的顶层兜底。 -- managed `ScriptableRenderContext` 的公开场景接口只表达绘制能力:`DrawRenderers(...)`、`DrawSkybox()`、`DrawOpaqueRenderers()`、`DrawTransparentRenderers()`。 -- renderer-backed SRP 的 frame stage 组织权归 `ScriptableRenderer` / `ScriptableRendererFeature`,包括 shadow caster、depth only、post-process、final output 等可选 stage。 +The rendering module is moving toward a Unity SRP / URP style model: -## 5. 当前硬边界 -- `RenderPipelineFactory` 在无显式 asset、无托管配置、创建失败回退时,都必须先回 builtin,而不是回 `ScriptableRenderPipelineHost`。 -- `MonoScriptRuntime::OnRuntimeStart()` 不得隐式写入 render pipeline 选择。 -- builtin 私有 native feature 通道只能留在 native 内部使用。 -- managed SRP runtime 或 stage recorder 存在时,stage 组织权归 managed SRP;native backend 不得在 host 层隐式接管 `RecordStageRenderGraph`、`Render(...)` 或 scene-pass standalone stage。 -- `RendererBackedRenderPipelineAsset` 进入 frame planning 时必须先清掉 native 默认请求出来的可选 stage,再由 renderer / feature 显式请求需要的 stage。 -- 下列能力不得再暴露给 managed / URP 公开层: - `NativeSceneFeaturePassId` - `ScriptableRenderContext.RecordNativeSceneFeaturePass(...)` - `ScriptableRenderContext.RecordScene(...)` - `ScriptableRenderContext.RecordScenePhase(...)` - `ScriptableRenderContext.RecordSceneInjectionPoint(...)` - `ScriptableRenderContext.RecordOpaque/Skybox/TransparentScenePhase(...)` - `ScriptableRenderContext.RecordBefore/After*Injection(...)` - 依赖上述接口的 managed wrapper feature / controller -- `CameraRenderRequestContext.hasDirectionalShadow` 和 `CameraRenderRequestContext.ClearDirectionalShadow()` 不得作为 ScriptCore public surface 暴露;core 层只能保留内部桥接,产品层策略放在 URP renderer asset / renderer data / feature。 -- URP 默认 renderer feature 工厂不得自动注入 builtin 私有 feature wrapper。 +- `GraphicsSettings.renderPipelineAsset == null` selects the built-in pipeline. +- `GraphicsSettings.renderPipelineAsset != null` selects the programmable SRP + path. +- The managed product shape should stay close to: + `ScriptableRenderPipelineAsset -> ScriptableRendererData -> + ScriptableRenderer -> ScriptableRendererFeature/ScriptableRenderPass`. +- `ScriptableRenderPipelineHost` is the native host for managed SRP execution; + it must not become a hidden fallback renderer when managed SRP planning or + recording fails. +- Managed SRP / URP owns renderer selection, stage planning, feature/pass + organization, camera policy, and optional stage requests such as shadow, + depth, post-process, and final output. +- Native rendering owns scene extraction, renderer-list drawing, render graph + execution, fullscreen primitive execution, and built-in private draw kernels. +- Public managed scene drawing should expose drawing capability, not native + built-in injection order. Keep the public surface centered on + `DrawRenderers(...)`, `DrawSkybox()`, `DrawOpaqueRenderers()`, and + `DrawTransparentRenderers()`. +- Do not reintroduce implicit project-default SRP activation, hidden + `ScriptableRenderPipelineHost` fallback, or public managed wrappers for + built-in private scene injection points. +- Future URP alignment should add managed-side renderer/pass/render-graph + capability. It should not reopen native private fallback paths just to make a + feature appear to work. -## 6. native / managed 分层 -- 放在 native 的内容: - scene extraction - renderer list 绘制 - render graph 执行 - fullscreen primitive 执行 - builtin 私有 scene feature 执行内核 -- 放在 managed URP 的内容: - renderer 选择 - stage planning - renderer feature / pass 组织 - renderer feature 的 frame-plan / scene-setup / shadow-execution 配置分发 - camera 级策略 - shadow caster / depth only 等可选 stage 的显式请求 - 产品层行为差异 -- 判断原则: - 如果新增的是“绘制能力”或“后端 contract”,优先放 C++。 - 如果新增的是“渲染组织策略”或“URP 行为”,优先放 managed。 +## Past Execution -## 7. 禁止回退的实现方式 -- 不要再引入“项目默认 SRP asset 自动生效”的隐式逻辑。 -- 不要再把 builtin 私有 native feature 包成 public managed API 方便调用。 -- 不要让 managed `ScriptableRenderContext.RecordScene(...)` 或任何 managed pass 录制 native scene injection point。 -- 不要再让 “null 选择” 默认落到 `ScriptableRenderPipelineHost`。 -- 不要把非通用产品层策略继续直接塞回 `BuiltinForwardPipeline`。 -- 不要让 `ScriptableRenderPipelineHost` 在 managed SRP 未支持或未录制某个 stage 时自动回退到 native backend;需要绘制时应通过 managed `ScriptableRenderContext` 显式调用 native draw 能力。 -- 不要让 renderer-backed SRP 继续继承 native planner 默认请求出来的 shadow/depth stage;需要这些 stage 时必须由 managed renderer / feature 显式请求并录制。 - -## 8. 关键文件 -- `engine/src/Rendering/Internal/RenderPipelineFactory.cpp` -- `engine/src/Rendering/Execution/RenderPipelineHost.cpp` -- `engine/src/Rendering/Execution/CameraRenderer.cpp` -- `engine/src/Rendering/Extraction/RenderSceneExtractor.cpp` -- `engine/src/Rendering/Pipelines/BuiltinForwardPipeline.cpp` -- `engine/src/Rendering/Pipelines/ScriptableRenderPipelineHost.cpp` -- `engine/src/Scripting/Mono/MonoScriptRuntime.cpp` -- `managed/XCEngine.ScriptCore/Rendering/Core/GraphicsSettings.cs` -- `managed/XCEngine.ScriptCore/Rendering/Core/ScriptableRenderPipeline*.cs` -- `managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/*.cs` - -## 9. 当前验证点 -- `tests/scripting/test_project_script_assembly.cpp` - 运行时启动不会自动配置 `ProjectDefaultRenderPipelineAsset`。 -- `tests/Rendering/unit/test_camera_scene_renderer.cpp` - 无 managed 选择时默认走 builtin。 - 设置 managed descriptor 后切到 `ScriptableRenderPipelineHost`。 - 清空 managed descriptor 后退回 builtin。 -- `tests/scripting/test_mono_script_runtime.cpp` - `ScriptableRenderContextPublicApiSurfaceUsesDirectContextModel` 保证 public managed surface 不再暴露 native scene injection / phase wrapper。 - `DefaultSceneRendererUsesManagedUniversalPipelineForPlannedMainSceneAndPostProcessRender` 保证 managed URP 通过显式 renderer/pass 录制主场景和后处理。 - `ManagedRenderContextExposes*ThroughRenderingData` 保证 managed renderer 可通过 `RenderingData` 观察 camera / lighting / shadow / environment / final color / stage color 数据。 - `ManagedStageRecorderRecordsMainSceneThroughScriptableRenderContext` 保证主场景通过 `ScriptableRenderContext` 的显式 draw 能力录制。 - `ScriptCoreUniversalRendererFeatureConfiguresCameraRequestPolicy` 保证 URP renderer feature 能通过产品层相机请求策略真正禁用 native 默认方向光阴影规划。 - -## 10. 后续演进方向 -- 继续补齐 URP 上层组织能力,但不能破坏 builtin / programmable 的显式切换语义。 -- 如果未来继续向 Unity 收口,优先收口“入口语义”和“分层边界”,不要靠隐式 fallback 和私有桥接维持表面形似。 - -## 过去几刀 - -- 收回 managed native scene injection 公开面:渲染模块目标向 Unity SRP / URP 对齐,但 managed / URP 层仍公开 native builtin scene injection point 和 phase wrapper,导致产品层像是在组织 URP,实质上仍在调用 builtin 私有时序。 -- 移除 `ScriptableRenderContext.RecordSceneInjectionPoint(...)`、`RecordBefore/After*Injection(...)`、`RecordOpaque/Skybox/TransparentScenePhase(...)` 等 public managed API;移除对应 Mono internal call;`RecordScene()` / `RecordScenePhase(...)` 收回 internal。 -- 确立 managed 公开层只通过 `DrawRenderers(...)`、`DrawSkybox()`、`DrawOpaqueRenderers()`、`DrawTransparentRenderers()` 表达 native draw 能力;pass / feature / stage 的组织权归 managed SRP / URP。 -- `ScriptableRenderer` 统一驱动 renderer feature 的 frame-plan、scene-setup、directional-shadow execution 配置;`RendererBackedRenderPipelineAsset` 清掉 native 默认 optional stage 后再让 renderer / feature 显式请求。 -- `CameraRenderRequestContext.hasDirectionalShadow` 和 `ClearDirectionalShadow()` 从 ScriptCore public surface 收回 internal,避免 core public API 泄漏 native shadow 规划控制。 -- 收口 managed 相机请求策略顺序:`MonoManagedRenderPipelineAssetRuntime::ConfigureCameraRenderRequest` 先生成 native 默认方向光阴影基线给 managed / URP 观察,再按 managed 最终策略重算或清除,避免 `ClearDirectionalShadow()` 之后又被 native 默认规划补回。 -- 当时验证:`xcengine_managed_assemblies`、`scripting_tests` 构建通过;聚焦 `MonoScriptRuntimeTest` 12 项 SRP / URP / API surface 测试通过。 -- 收口 SRP 创建失败语义:`ManagedScriptableRenderPipelineAsset::CreatePipeline()` 在 managed runtime、backend asset 或 stage recorder 不可用时直接创建失败;`RenderPipelineFactory::CreateRenderPipelineOrDefault()` 不再在已解析 asset 创建失败后重新走 configured SRP 默认解析,而是明确退回 builtin fallback,避免 `ScriptableRenderPipelineHost` 带 native backend 冒充 managed SRP 成功。 +- Established the top-level selection rule: explicit null means built-in, + explicit managed asset means SRP, and runtime startup must not silently assign + `ProjectDefaultRenderPipelineAsset`. +- Removed public managed native scene injection APIs such as + `ScriptableRenderContext.RecordSceneInjectionPoint(...)`, + `RecordBefore/After*Injection(...)`, and + `RecordOpaque/Skybox/TransparentScenePhase(...)`. +- Kept `RecordScene()` / `RecordScenePhase(...)` internal and made the public + managed scene surface express draw operations through `DrawRenderers(...)`, + `DrawSkybox()`, `DrawOpaqueRenderers()`, and + `DrawTransparentRenderers()`. +- Moved renderer-backed SRP stage ownership into `ScriptableRenderer`, + `ScriptableRendererFeature`, and `ScriptableRenderPass`; renderer-backed + assets clear native optional stage defaults before managed renderer/features + explicitly request the stages they need. +- Removed `CameraRenderRequestContext.hasDirectionalShadow` and + `ClearDirectionalShadow()` from the ScriptCore public surface. Core keeps only + internal bridge access, while URP policy belongs in renderer asset, renderer + data, and feature code. +- Reordered managed camera request policy so managed / URP first observes the + native directional-shadow baseline, then the final managed policy recomputes + or clears the request without native planning adding it back afterward. +- Prevented URP default renderer feature factories from auto-injecting built-in + private feature wrappers. +- Tightened SRP creation failure semantics: + `ManagedScriptableRenderPipelineAsset::CreatePipeline()` fails when managed + runtime, backend asset, or stage recorder is unavailable; factory fallback + then returns the built-in pipeline instead of letting + `ScriptableRenderPipelineHost` impersonate a successful managed SRP.