From d1126d70f767f5e6fa0a8543b1ea8ef4270d82c9 Mon Sep 17 00:00:00 2001 From: ssdfasd <2156608475@qq.com> Date: Mon, 27 Apr 2026 01:32:37 +0800 Subject: [PATCH] docs: reorganize rendering agent guide --- engine/include/XCEngine/Rendering/AGENTS.md | 633 +++++++++----------- 1 file changed, 278 insertions(+), 355 deletions(-) diff --git a/engine/include/XCEngine/Rendering/AGENTS.md b/engine/include/XCEngine/Rendering/AGENTS.md index 1e8ebf45..614f43a3 100644 --- a/engine/include/XCEngine/Rendering/AGENTS.md +++ b/engine/include/XCEngine/Rendering/AGENTS.md @@ -1,412 +1,335 @@ -# Rendering Agent Guide +# 渲染模块 Agent 指南 -This file is a working map for agents changing `engine/include/XCEngine/Rendering`, -`engine/src/Rendering`, and the matching managed SRP/URP surface under -`managed/`. It is not a substitute for reading the implementation. If this -guide conflicts with code, trust the code and update this guide in the same -change. +本文是修改 `engine/include/XCEngine/Rendering`、`engine/src/Rendering`,以及 +`managed/` 下配套 managed SRP/URP 表面的工作地图。它不能替代阅读实现代码。 +如果本文和代码冲突,以代码为准,并在同一次改动里更新本文。 -## Direction +## 【未来目标】 -The renderer is intentionally shaped after Unity SRP and URP. Future work should -prefer Unity-compatible public names, object ownership, and extension points -when those concepts fit the engine. +### 方向 -- Keep the managed public surface close to Unity: `GraphicsSettings.renderPipelineAsset`, - `RenderPipelineAsset`, `ScriptableRenderPipelineAsset`, - `ScriptableRenderPipeline`, `ScriptableRenderContext`, - `UniversalRenderPipelineAsset`, `UniversalRendererData`, - `ScriptableRenderer`, `ScriptableRendererFeature`, `ScriptableRenderPass`, - `RenderPassEvent`, `ContextContainer`, and `RenderGraph`. -- Align behavior before inventing new public vocabulary. If a Unity concept is - only partially implemented here, expose the implemented subset honestly and - keep missing behavior behind internal code or tests. -- Preserve Unity-style numeric ordering for `RenderPassEvent`. Adding or moving - events requires updating `ScriptableRenderPass.TryResolveRendererBlock`, - `RendererBlocks`, probes, and tests together. -- Prefer managed URP features and passes for pipeline customization. Native - paths should supply backend execution, scene extraction, fallback passes, and - tooling support. -- Keep renderer code backend-neutral. D3D12, OpenGL, and Vulkan specifics belong - in `engine/include/XCEngine/RHI/**`, `engine/src/RHI/**`, or editor host - rendering, not in SRP/URP policy. +渲染器有意参考 Unity SRP 和 URP 设计。后续工作在概念适配本引擎时,应优先采用 +Unity 兼容的公开命名、对象所有权和扩展点。 -## Key Facts +- 保持 managed 公开表面接近 Unity:`GraphicsSettings.renderPipelineAsset`、 + `RenderPipelineAsset`、`ScriptableRenderPipelineAsset`、 + `ScriptableRenderPipeline`、`ScriptableRenderContext`、 + `UniversalRenderPipelineAsset`、`UniversalRendererData`、 + `ScriptableRenderer`、`ScriptableRendererFeature`、`ScriptableRenderPass`、 + `RenderPassEvent`、`ContextContainer` 和 `RenderGraph`。 +- 在发明新的公开词汇前,优先对齐行为。如果某个 Unity 概念在这里只实现了一部分, + 要诚实暴露已实现的子集,把缺失行为留在内部代码或测试里。 +- 保留 Unity 风格的 `RenderPassEvent` 数值顺序。新增或移动事件时,必须一起更新 + `ScriptableRenderPass.TryResolveRendererBlock`、`RendererBlocks`、probes 和测试。 +- 管线自定义优先使用 managed URP features 和 passes。Native 路径应提供后端执行、 + 场景提取、fallback passes 和工具支持。 +- 渲染器代码保持后端无关。D3D12、OpenGL 和 Vulkan 细节属于 + `engine/include/XCEngine/RHI/**`、`engine/src/RHI/**` 或 editor host rendering, + 不应进入 SRP/URP 策略层。 -These facts are the current architecture baseline. Do not weaken them without a -deliberate architecture cut and tests. +### 近期目标 -- The SRP/URP architecture is phase-closed enough to extend. The public object - model, managed asset selection, URP renderer data/features/passes, native - frame planning, stage recording, and RenderGraph execution now form a single - path. -- This is not full Unity URP compatibility yet. The public shape is intentionally - Unity-like, but the execution feature set is still smaller than Unity URP. -- `UniversalRenderPipelineAsset` can be selected as the active managed SRP - asset, so users can route rendering through the URP package. Treat that as - supported but still transitional. -- The current URP package is not yet a complete replacement for the built-in - renderer in the strong sense. URP owns selection, planning, renderer feature - organization, pass ordering, and stage recording; native code still supplies - scene extraction, renderer-list realization, RenderGraph execution, RHI - resources, and the default scene draw backend. -- Native execution is not the problem by itself. Unity also executes through a - native engine. The risk is native code retaining built-in forward pipeline - policy instead of acting as a backend executor for URP-declared work. -- The desired ownership model is: URP decides what to render, when to render it, - which renderer lists/passes/features are active, and which stages exist; - native executes those declarations without smuggling in built-in pipeline - policy. -- Hidden fallback is dangerous. If a managed URP stage declares support but - cannot record, the failure should be visible. Do not silently draw the same - stage through the default built-in path and call it URP. -- The test suite has useful coverage, but it is not complete enough to call the - SRP/URP stack fully locked. Add high-value contract tests as architecture - boundaries close; do not pause the architecture work for a broad test-system - rewrite yet. +当前优先级是完成 SRP/URP 架构切分,并在每条边界上补目标明确的测试。近期产品目标 +是让 URP 成为渲染决策层,让 native rendering 成为执行层。 -## Near-Term Goals +- 将 `BuiltinForwardPipeline` 从策略中心降级为默认 native scene draw backend。它可以 + 继续作为 backend/fallback 实现存在,但不应决定 URP pass 顺序、feature 参与方式或 + stage 策略。 +- 让 `ScriptableRenderer` 及其 active pass queue 成为 URP main-scene scheduling 的权威。 + Opaque、skybox、transparent、depth、shadow、post 和 final-output 流程应来自 URP + blocks 和 passes。 +- 保持 `DrawObjectsPass` 和 `DrawSkyboxPass` 作为 managed URP pass declarations,并通过 + renderer-list/native scene-recorder backends 执行。 +- 收紧 stage 支持规则。如果 fullscreen 或 main-scene stage 需要 managed graph recording, + 必须要求所选 renderer/pipeline 支持并记录该 stage。 +- 只在 Unity 形态的 API 后面扩展 managed RenderGraph:resource declarations、frame data、 + renderer-list drawing、pass data 和 command recording。避免暴露 native 私有 graph 或 + scene-recorder 细节。 +- 在切分架构时补 contract tests:URP selection、renderer data selection、renderer override、 + pass event ordering、renderer feature invalidation、stage planning、RenderGraph recording, + 以及 no hidden built-in fallback。 +- 等 SRP/URP 所有权边界稳定后,再做大范围测试体系重组。过早重组有可能固化当前的过渡行为。 -Current priority is to finish the SRP/URP architecture cut, with targeted tests -on each boundary. The immediate product goal is to make URP the render decision -layer and make native rendering the execution layer. +### 修改规则 -- Demote `BuiltinForwardPipeline` from policy center toward default native scene - draw backend. It can remain a backend/fallback implementation, but it should - not decide URP pass order, feature participation, or stage policy. -- Make `ScriptableRenderer` and its active pass queue the authority for URP - main-scene scheduling. Opaque, skybox, transparent, depth, shadow, post, and - final-output flow should come from URP blocks and passes. -- Keep `DrawObjectsPass` and `DrawSkyboxPass` as managed URP pass declarations - that execute through renderer-list/native scene-recorder backends. -- Tighten stage support rules. If a fullscreen or main-scene stage requires - managed graph recording, require the selected renderer/pipeline to support and - record that stage. -- Grow managed RenderGraph only behind Unity-shaped APIs: resource declarations, - frame data, renderer-list drawing, pass data, and command recording. Avoid - exposing native private graph or scene-recorder details. -- Add contract tests while cutting architecture: URP selection, renderer data - selection, renderer override, pass event ordering, renderer feature - invalidation, stage planning, RenderGraph recording, and no hidden built-in - fallback. -- Defer broad test-suite reorganization until these SRP/URP ownership boundaries - are stable. Reorganizing too early risks preserving transitional behavior. +- 行为变更要从 pipeline asset/request/plan 路径开始。app/editor 代码中的临时 pass execution + 通常表示层级位置不对。 +- Native headers 保持小而后端无关。可行时 forward declare RHI 类型,只在后端代码里 include + 具体后端头。 +- 新增 camera-stack、renderer-index、shadow、depth、post-process 或 final output 行为时,不要绕过 + `CameraFramePlanBuilder` 或 `SceneRenderRequestPlanner`。 +- 不要在 native 长生命周期对象里保存 raw managed object pointers 或 managed context handles。 + 需要持久化时,通过现有 external managed object handle 系统 retain。 +- Managed URP public APIs 不要依赖 `CameraFrameGraph` 或 `NativeSceneRecorder` 这类 native + 实现名。 +- Dirty/invalidation 路径必须显式。`ScriptableRendererFeature.SetActive`、 + feature `ComputeRuntimeStateHash`、renderer data feature collection hashes 和 asset runtime + resource versions 必须保持一致。 +- 修改 renderer-index 行为时,要一起更新 `CameraRenderRequest.rendererIndex`、stage support contexts、 + `RendererRecordingContext`、managed probes 和 Mono bridge calls。 +- 新增 public managed rendering type 时,将它加入 `managed/CMakeLists.txt`,并在对应 managed probe + 里覆盖 API presence。 -## Pipeline Selection +## 【当下事实】 -- `GraphicsSettings.renderPipelineAsset == null` means the renderer uses the - engine default native pipeline selection. -- `GraphicsSettings.renderPipelineAsset != null` means the renderer uses the - managed SRP asset descriptor path. -- Runtime startup must not silently assign a project default SRP asset. Project - or editor policy may choose one explicitly, but the active rendering mode must - remain observable through `GraphicsSettings.renderPipelineAsset`. -- If a managed asset cannot create a valid pipeline, recorder, or backend - bridge, fail visibly and let the top-level factory choose the fallback path. - Do not let `ScriptableRenderPipelineHost` look like a successful managed SRP - while secretly rendering an unsupported managed stage through a hidden native - path. -- Keep the deleted public bridge types absent: - `RendererBackedRenderPipelineAsset`, `RendererBackedRenderPipeline`, and - `RendererDrivenRenderPipeline`. +### 架构基线 -## Current Shape +这些事实是当前架构基线。除非有明确的架构切分和测试,不要削弱它们。 -The native renderer is now a camera frame planner plus RenderGraph executor, -with managed SRP/URP recording layered above a native scene draw backend. +- SRP/URP 架构已经阶段性收口到可以继续扩展。公开对象模型、managed asset selection、 + URP renderer data/features/passes、native frame planning、stage recording 和 RenderGraph execution + 现在组成了一条路径。 +- 这还不是完整 Unity URP 兼容。公开形态有意接近 Unity,但执行 feature set 仍小于 Unity URP。 +- `UniversalRenderPipelineAsset` 可以被选为 active managed SRP asset,所以用户可以把渲染路由到 + URP package。把它视为受支持能力,但仍处于过渡状态。 +- 当前 URP package 还不是强意义上对 built-in renderer 的完整替代。URP 拥有 selection、planning、 + renderer feature organization、pass ordering 和 stage recording;native code 仍提供 scene extraction、 + renderer-list realization、RenderGraph execution、RHI resources 和默认 scene draw backend。 +- Native execution 本身不是问题。Unity 也通过 native engine 执行。风险在于 native code 继续保留 + built-in forward pipeline policy,而不是作为 URP-declared work 的 backend executor。 +- 目标所有权模型是:URP 决定渲染什么、何时渲染、哪些 renderer lists/passes/features 激活,以及 + 哪些 stages 存在;native 只执行这些声明,不夹带 built-in pipeline policy。 +- Hidden fallback 很危险。如果 managed URP stage 声明支持但无法 record,失败必须可见。不要静默用 + default built-in path 画同一个 stage,然后称之为 URP。 +- 测试体系已经有有价值的覆盖,但还不足以宣称 SRP/URP stack 完全锁定。随着架构边界收口,应补高价值 + contract tests;现阶段不要为了大范围测试体系重写而暂停架构工作。 -- `SceneRenderer` is the scene-level convenience entry point. It collects camera - requests through `SceneRenderRequestPlanner`, builds frame plans through - `RenderPipelineHost`, then renders sorted camera plans. -- `RenderPipelineHost` owns a `CameraFramePlanBuilder` and a `CameraRenderer`. - It is the normal native bridge from `CameraRenderRequest` to `CameraFramePlan`. -- `CameraRenderer` owns the selected `RenderPipeline`, extracts - `RenderSceneData`, resolves directional shadow execution, records all frame - stages into a native `RenderGraph`, compiles the graph, and executes it. -- `RenderPipelineAsset` is the native asset contract. It creates a pipeline, - configures request policy, configures frame plan policy, and supplies default - final color settings. -- `RenderPipeline`, `RenderPipelineBackend`, and - `RenderPipelineStageRecorder` split backend rendering from graph recording. - Managed SRP normally supplies a stage recorder while the native backend - supplies scene drawing. +### 管线选择 -## Frame Stages +- `GraphicsSettings.renderPipelineAsset == null` 表示 renderer 使用 engine default native pipeline selection。 +- `GraphicsSettings.renderPipelineAsset != null` 表示 renderer 使用 managed SRP asset descriptor path。 +- Runtime startup 不应静默指定 project default SRP asset。Project 或 editor policy 可以显式选择一个, + 但 active rendering mode 必须能通过 `GraphicsSettings.renderPipelineAsset` 观察到。 +- 如果 managed asset 无法创建有效 pipeline、recorder 或 backend bridge,应显式失败,并让 top-level factory + 选择 fallback path。不要让 `ScriptableRenderPipelineHost` 看起来像成功的 managed SRP,同时在背后用 + hidden native path 渲染不受支持的 managed stage。 +- 保持已删除的 public bridge types 不再出现: + `RendererBackedRenderPipelineAsset`、`RendererBackedRenderPipeline` 和 + `RendererDrivenRenderPipeline`。 -`CameraFrameStage` is the authoritative frame-stage model. Keep every native and -managed stage enum in sync. +### 当前形态 -- Current ordered stages are `PreScenePasses`, `ShadowCaster`, `DepthOnly`, - `MainScene`, `PostProcess`, `FinalOutput`, `ObjectId`, `PostScenePasses`, and - `OverlayPasses`. -- `ShadowCaster`, `DepthOnly`, and `ObjectId` are standalone-pass stages. - `MainScene` is the main pipeline stage. `PostProcess` and `FinalOutput` are - fullscreen sequence stages that may be graph-recorded by the pipeline when no - legacy `RenderPassSequence` is present. -- Use `CameraFramePlan` APIs such as `RequestFullscreenStage`, - `ClearFullscreenStage`, `RequestShadowCasterStage`, and - `RequestDepthOnlyStage`. Do not mutate plan stage fields directly unless you - are inside the plan implementation. -- Graph-managed color flow is explicit. `CameraFrameColorSource`, - `UsesGraphManagedSceneColor`, and `UsesGraphManagedOutputColor` decide whether - a stage reads from the main scene, post process, or an explicit surface. -- When adding a stage, update `CameraFrameStage.h`, managed - `CameraFrameStage.cs`, `CameraFramePlan`, camera-frame graph state/policy, - stage dispatch/contract tests, managed probes, and any Mono internal-call - conversion code. +Native renderer 现在是 camera frame planner 加 RenderGraph executor,managed SRP/URP recording +叠在 native scene draw backend 之上。 -## RenderGraph +- `SceneRenderer` 是 scene-level convenience entry point。它通过 `SceneRenderRequestPlanner` 收集 + camera requests,通过 `RenderPipelineHost` 构建 frame plans,然后渲染排序后的 camera plans。 +- `RenderPipelineHost` 拥有一个 `CameraFramePlanBuilder` 和一个 `CameraRenderer`。它是从 + `CameraRenderRequest` 到 `CameraFramePlan` 的常规 native bridge。 +- `CameraRenderer` 拥有所选 `RenderPipeline`,提取 `RenderSceneData`,解析 directional shadow execution, + 把全部 frame stages 记录进 native `RenderGraph`,编译 graph 并执行。 +- `RenderPipelineAsset` 是 native asset contract。它创建 pipeline,配置 request policy,配置 frame plan + policy,并提供默认 final color settings。 +- `RenderPipeline`、`RenderPipelineBackend` 和 `RenderPipelineStageRecorder` 将 backend rendering + 与 graph recording 分开。Managed SRP 通常提供 stage recorder,native backend 提供 scene drawing。 -The native RenderGraph is the execution spine for camera frames. +### 帧阶段 -- Record all graph resource usage through `RenderGraphBuilder` and - `RenderGraphPassBuilder`; do not rely on hidden RHI side effects. -- Imported textures need valid descriptions. If `graphOwnsTransitions` is true, - the imported view must expose a texture so the executor can create barriers. -- Transient textures require valid width, height, format, type, and sample - description. Invalid transient reads are compile errors. -- Use `RenderGraphRecordingContext` helpers to clone or adapt pass contexts - between `RenderPass`, `SceneRenderFeaturePass`, and pipeline-stage recorders. -- `RenderGraphBlackboard` carries per-frame shared data such as - `CameraFrameRenderGraphFrameData`; prefer typed blackboard entries over global - or static frame state. -- Current graph execution does dependency sorting, lifetime tracking, - transient allocation, and resource transitions. Do not assume pass culling or - transient aliasing exists unless you add and test it. +`CameraFrameStage` 是权威 frame-stage model。保持所有 native 和 managed stage enum 同步。 -## Native Passes +- 当前有序 stages 是 `PreScenePasses`、`ShadowCaster`、`DepthOnly`、`MainScene`、`PostProcess`、 + `FinalOutput`、`ObjectId`、`PostScenePasses` 和 `OverlayPasses`。 +- `ShadowCaster`、`DepthOnly` 和 `ObjectId` 是 standalone-pass stages。`MainScene` 是主 pipeline stage。 + `PostProcess` 和 `FinalOutput` 是 fullscreen sequence stages;没有 legacy `RenderPassSequence` 时, + 它们可以由 pipeline 进行 graph recording。 +- 使用 `CameraFramePlan` APIs,例如 `RequestFullscreenStage`、`ClearFullscreenStage`、 + `RequestShadowCasterStage` 和 `RequestDepthOnlyStage`。除非在 plan implementation 内部,否则不要直接 + 改 plan stage fields。 +- Graph-managed color flow 是显式的。`CameraFrameColorSource`、`UsesGraphManagedSceneColor` 和 + `UsesGraphManagedOutputColor` 决定 stage 是读取 main scene、post process 还是 explicit surface。 +- 新增 stage 时,更新 `CameraFrameStage.h`、managed `CameraFrameStage.cs`、`CameraFramePlan`、 + camera-frame graph state/policy、stage dispatch/contract tests、managed probes,以及所有 Mono + internal-call conversion code。 -Native passes still matter for backend fallback, tools, and built-in rendering. +### RenderGraph -- New native passes should implement `RecordRenderGraph` when possible. Keep - `Execute` as the fallback path only when legacy execution is still required. -- Use `RenderPassGraphContract` and `RecordRenderGraphSurfaceIO` helpers for - fallback-compatible raster passes. -- `SceneRenderFeaturePass` is for native scene feature injection around scene - phases. Keep injection points in `SceneRenderInjectionPoint` and scene phases - in `ScenePhase` aligned with `SceneRenderSequence`. -- Object-id rendering is tooling/editor support. `CameraRenderer` installs the - top-level `BuiltinObjectIdPass` only when - `XCENGINE_ENABLE_RENDERING_EDITOR_SUPPORT` is enabled. Do not move object-id - ownership into the scene backend. -- Built-in fullscreen passes live under `Passes/` and planning factories live - under `Planning/`. Keep stage planning separate from pass implementation. +Native RenderGraph 是 camera frames 的执行主干。 -## Managed Boundary +- 所有 graph resource usage 都通过 `RenderGraphBuilder` 和 `RenderGraphPassBuilder` 记录;不要依赖隐藏的 + RHI side effects。 +- Imported textures 需要有效 descriptions。如果 `graphOwnsTransitions` 为 true,imported view 必须暴露 + texture,以便 executor 创建 barriers。 +- Transient textures 需要有效 width、height、format、type 和 sample description。无效 transient reads 是 + compile errors。 +- 使用 `RenderGraphRecordingContext` helpers 在 `RenderPass`、`SceneRenderFeaturePass` 和 pipeline-stage + recorders 之间 clone 或 adapt pass contexts。 +- `RenderGraphBlackboard` 携带 per-frame shared data,例如 `CameraFrameRenderGraphFrameData`;优先使用 + typed blackboard entries,不要用 global 或 static frame state。 +- 当前 graph execution 已有 dependency sorting、lifetime tracking、transient allocation 和 resource transitions。 + 除非实现并测试,否则不要假设存在 pass culling 或 transient aliasing。 -Managed SRP assets are selected through `GraphicsSettings.renderPipelineAsset` -and bridged through `ManagedScriptableRenderPipelineAsset`. +### Native Passes -- `ManagedRenderPipelineAssetDescriptor` identifies the managed asset assembly, - namespace, class, and retained managed object handle. Managed descriptors are - stored in `GraphicsSettingsState`. -- `ManagedScriptableRenderPipelineAsset` resolves a - `ManagedRenderPipelineAssetRuntime`, creates a `ScriptableRenderPipelineHost`, - and forwards request/plan/final-color policy calls to managed code. -- `ScriptableRenderPipelineHost` composes a native backend asset and an optional - managed stage recorder. When a managed recorder is authoritative, direct - legacy `Render` fallback is intentionally disabled for those stages. -- Mono creates `MonoManagedRenderPipelineAssetRuntime` and - `MonoManagedRenderPipelineStageRecorder`. Scriptable context, planning - context, camera request context, scene setup context, and shadow execution - context handles are temporary native registry entries. Do not store managed - context objects beyond their invocation. -- Current Mono-backed SRP assets explicitly use `DefaultNativeBackend` for scene - drawing. Managed `ScriptableRenderContext.DrawRenderers` and `DrawSkybox` - delegate to `NativeSceneRecorder` and the native `SceneDrawBackend`. -- Managed resource/version invalidation is part of correctness. If a managed - asset, renderer data, or feature changes runtime state, call `SetDirty` or the - local invalidation helper so native runtime caches are released. +Native passes 仍用于 backend fallback、工具和 built-in rendering。 -## URP Model +- 新 native passes 应尽可能实现 `RecordRenderGraph`。只有 legacy execution 仍需要时,才把 `Execute` 保留为 + fallback path。 +- 对 fallback-compatible raster passes,使用 `RenderPassGraphContract` 和 `RecordRenderGraphSurfaceIO` + helpers。 +- `SceneRenderFeaturePass` 用于在 scene phases 周围注入 native scene feature。保持 + `SceneRenderInjectionPoint` 中的 injection points、`ScenePhase` 中的 scene phases 与 + `SceneRenderSequence` 对齐。 +- Object-id rendering 是 tooling/editor support。只有启用 `XCENGINE_ENABLE_RENDERING_EDITOR_SUPPORT` 时, + `CameraRenderer` 才安装 top-level `BuiltinObjectIdPass`。不要把 object-id ownership 移入 scene backend。 +- Built-in fullscreen passes 位于 `Passes/`,planning factories 位于 `Planning/`。保持 stage planning 与 + pass implementation 分离。 -The URP package is in `managed/XCEngine.RenderPipelines.Universal`. It should be -treated as the primary user-facing render pipeline package. +### Managed Boundary -- `UniversalRenderPipelineAsset` owns `rendererDataList`, - `defaultRendererIndex`, `UniversalShadowSettings`, and - `UniversalFinalColorSettings`. It resolves renderer index from - `UniversalAdditionalCameraData` before delegating to renderer data. -- `ScriptableRendererData` owns the persistent renderer instance and renderer - feature collection. Renderer data dirty state releases the renderer setup - cache and increments runtime state version. -- `ScriptableRenderer` builds `m_activePassQueue` per stage. It calls feature - `SetupRenderPasses`, feature `AddRenderPasses`, then renderer-owned - `AddRenderPasses`; passes are inserted by `RenderPassEvent` order and grouped - into `RendererBlocks`. -- `RendererBlock` maps pass events to camera stages: shadow caster, depth - prepass, main opaque, main skybox, main transparent, post process, and final - output. -- `UniversalRenderer` owns concrete blocks: - `UniversalShadowCasterBlock`, `UniversalDepthPrepassBlock`, - `UniversalMainSceneBlock`, `UniversalPostProcessBlock`, and - `UniversalFinalOutputBlock`. -- Built-in URP passes include `DrawObjectsPass`, `DrawSkyboxPass`, and the - internal `BuiltinFinalColorPass`. Current feature implementations include - `RenderObjectsRendererFeature`, `ColorScalePostProcessRendererFeature`, and - `DisableDirectionalShadowRendererFeature`. -- When adding a URP feature, keep its serializable settings, runtime hash, - `Create`, `ConfigureCameraRenderRequest`, `ConfigureCameraFramePlan`, - `ConfigureRenderSceneSetup`, `AddRenderPasses`, and stage gate behavior - together. If the feature needs a stage, request it during planning before - enqueueing a pass. +Managed SRP assets 通过 `GraphicsSettings.renderPipelineAsset` 选择,并通过 +`ManagedScriptableRenderPipelineAsset` bridge。 -## Managed RenderGraph +- `ManagedRenderPipelineAssetDescriptor` 标识 managed asset assembly、namespace、class 和 retained managed + object handle。Managed descriptors 存在 `GraphicsSettingsState` 中。 +- `ManagedScriptableRenderPipelineAsset` 解析 `ManagedRenderPipelineAssetRuntime`,创建 + `ScriptableRenderPipelineHost`,并把 request/plan/final-color policy calls 转发给 managed code。 +- `ScriptableRenderPipelineHost` 组合 native backend asset 和可选 managed stage recorder。当 managed recorder + 是权威时,这些 stages 的 direct legacy `Render` fallback 会被刻意禁用。 +- Mono 创建 `MonoManagedRenderPipelineAssetRuntime` 和 `MonoManagedRenderPipelineStageRecorder`。 + Scriptable context、planning context、camera request context、scene setup context 和 shadow execution + context handles 都是临时 native registry entries。不要在调用之外保存 managed context objects。 +- 当前 Mono-backed SRP assets 显式使用 `DefaultNativeBackend` 做 scene drawing。Managed + `ScriptableRenderContext.DrawRenderers` 和 `DrawSkybox` 委托给 `NativeSceneRecorder` 以及 native + `SceneDrawBackend`。 +- Managed resource/version invalidation 是正确性的一部分。如果 managed asset、renderer data 或 feature + 修改 runtime state,调用 `SetDirty` 或本地 invalidation helper,确保 native runtime caches 被释放。 -Managed RenderGraph is intentionally small but should keep Unity's modern shape. +### URP Model -- Public managed authoring goes through - `XCEngine.Rendering.RenderGraphModule.RenderGraph.AddRasterPass` and - `RenderGraphRasterPassBuilder`. -- Public passes should declare reads, bindings, color attachments, depth - attachment, and render func, then `Commit`. -- Internal fullscreen helpers such as color scale, shader vector, and final - color are URP implementation details. Do not expose them as public - `ScriptableRenderContext` shortcuts. -- Managed `SetRenderFunc` is not a fully bridged native command buffer yet. It - invokes the managed render func during recording and records declared IO into - native graph execution. Do not add behavior that assumes managed commands run - later on the native command list. -- Public RenderGraph frame data is shared for all passes recorded in the same - renderer stage. Keep `ContextContainer` as stage frame data, not pass-local - scratch data. -- Fullscreen internal passes require valid `sourceColorTexture` and - `primaryColorTarget`. Multi-pass fullscreen chains should update the current - source color after each pass. +URP package 位于 `managed/XCEngine.RenderPipelines.Universal`。它应被视为主要面向用户的 render pipeline +package。 -## Scene Data +- `UniversalRenderPipelineAsset` 拥有 `rendererDataList`、`defaultRendererIndex`、 + `UniversalShadowSettings` 和 `UniversalFinalColorSettings`。它从 `UniversalAdditionalCameraData` 解析 + renderer index,然后委托给 renderer data。 +- `ScriptableRendererData` 拥有持久 renderer instance 和 renderer feature collection。Renderer data dirty + state 会释放 renderer setup cache,并递增 runtime state version。 +- `ScriptableRenderer` 按 stage 构建 `m_activePassQueue`。它依次调用 feature `SetupRenderPasses`、feature + `AddRenderPasses`,再调用 renderer-owned `AddRenderPasses`;passes 按 `RenderPassEvent` 顺序插入,并归组到 + `RendererBlocks`。 +- `RendererBlock` 将 pass events 映射到 camera stages:shadow caster、depth prepass、main opaque、main + skybox、main transparent、post process 和 final output。 +- `UniversalRenderer` 拥有具体 blocks: + `UniversalShadowCasterBlock`、`UniversalDepthPrepassBlock`、`UniversalMainSceneBlock`、 + `UniversalPostProcessBlock` 和 `UniversalFinalOutputBlock`。 +- Built-in URP passes 包括 `DrawObjectsPass`、`DrawSkyboxPass` 和内部 `BuiltinFinalColorPass`。当前 feature + implementations 包括 `RenderObjectsRendererFeature`、`ColorScalePostProcessRendererFeature` 和 + `DisableDirectionalShadowRendererFeature`。 +- 新增 URP feature 时,保持 serializable settings、runtime hash、`Create`、 + `ConfigureCameraRenderRequest`、`ConfigureCameraFramePlan`、`ConfigureRenderSceneSetup`、 + `AddRenderPasses` 和 stage gate behavior 一致。如果 feature 需要 stage,先在 planning 阶段 request, + 再 enqueue pass。 -Scene data is extracted once per camera frame and then adjusted by the pipeline. +### Managed RenderGraph -- `RenderSceneExtractor` builds `RenderSceneData` from the scene and camera. - Keep component traversal and render item extraction there or in - `Extraction/RenderSceneUtility`. -- Pipeline scene setup belongs in `RenderPipeline::ConfigureRenderSceneData` or - managed `ConfigureRenderSceneSetup`, not in individual draw passes. -- Main-light shadow data is planned through `DirectionalShadowPlanningSettings` - and executed through `DirectionalShadowRuntime`. The current implementation is - a single main directional shadow map, not cascaded shadows. -- Final color policy is resolved from pipeline defaults plus camera overrides. - `FinalOutput` is requested only when final color processing is required or a - feature explicitly asks for it. -- Global shader keywords are normalized. Keep keyword changes centralized in - scene setup policy, not scattered through draw passes. +Managed RenderGraph 目前有意保持较小,但应维持 Unity 的现代形态。 -## Materials And Shaders +- Public managed authoring 通过 + `XCEngine.Rendering.RenderGraphModule.RenderGraph.AddRasterPass` 和 + `RenderGraphRasterPassBuilder` 进行。 +- Public passes 应声明 reads、bindings、color attachments、depth attachment 和 render func,然后 `Commit`。 +- Internal fullscreen helpers,例如 color scale、shader vector 和 final color,是 URP implementation details。 + 不要把它们作为 public `ScriptableRenderContext` shortcuts 暴露。 +- Managed `SetRenderFunc` 还不是完全 bridged native command buffer。它在 recording 时调用 managed render + func,并把声明的 IO 记录进 native graph execution。不要添加依赖 managed commands 之后在 native command + list 上运行的行为。 +- Public RenderGraph frame data 由同一个 renderer stage 内记录的所有 passes 共享。保持 `ContextContainer` + 作为 stage frame data,而不是 pass-local scratch data。 +- Fullscreen internal passes 需要有效 `sourceColorTexture` 和 `primaryColorTarget`。Multi-pass fullscreen chains + 应在每个 pass 后更新 current source color。 -- Built-in material pass names and resource semantics live in `Builtin/`. - Update `BuiltinPassTypes`, `BuiltinPassMetadataUtils`, and - `BuiltinPassLayoutUtils` together. -- Material-state resolution belongs under `Materials/`. Avoid duplicating render - state conversion logic inside passes. -- Shader variant helpers are split between public forwarding headers and - `Internal/`; keep public includes stable for engine users. -- URP shader package paths should follow the existing - `Packages/com.xcengine.render-pipelines.universal/...` convention. +### Scene Data -## Modification Rules +Scene data 每个 camera frame 提取一次,然后由 pipeline 调整。 -- Start from the pipeline asset/request/plan path for behavior changes. Ad hoc - pass execution in app/editor code usually indicates the wrong layer. -- Keep native headers small and backend-agnostic. Forward declare RHI types where - practical and include concrete backend headers only in backend code. -- Do not bypass `CameraFramePlanBuilder` or `SceneRenderRequestPlanner` when - adding camera-stack, renderer-index, shadow, depth, post-process, or final - output behavior. -- Do not store raw managed object pointers or managed context handles in native - long-lived objects. Retain through the existing external managed object handle - system when persistence is required. -- Do not make managed URP public APIs depend on native implementation names such - as `CameraFrameGraph` or `NativeSceneRecorder`. -- Keep dirty/invalidation paths explicit. `ScriptableRendererFeature.SetActive`, - feature `ComputeRuntimeStateHash`, renderer data feature collection hashes, - and asset runtime resource versions must remain consistent. -- For renderer-index behavior, update `CameraRenderRequest.rendererIndex`, - stage support contexts, `RendererRecordingContext`, managed probes, and Mono - bridge calls together. -- When adding a new public managed rendering type, add it to - `managed/CMakeLists.txt` and cover API presence in the appropriate managed - probe. +- `RenderSceneExtractor` 从 scene 和 camera 构建 `RenderSceneData`。Component traversal 和 render item + extraction 应留在这里,或放在 `Extraction/RenderSceneUtility`。 +- Pipeline scene setup 属于 `RenderPipeline::ConfigureRenderSceneData` 或 managed + `ConfigureRenderSceneSetup`,不属于单个 draw pass。 +- Main-light shadow data 通过 `DirectionalShadowPlanningSettings` 规划,并通过 + `DirectionalShadowRuntime` 执行。当前实现是单个 main directional shadow map,不是 cascaded shadows。 +- Final color policy 由 pipeline defaults 加 camera overrides 解析。只有需要 final color processing 或 feature + 显式要求时,才 request `FinalOutput`。 +- Global shader keywords 是规范化的。Keyword changes 应集中在 scene setup policy,不要散落在 draw passes 中。 -## Tests +### Materials And Shaders -Use the narrowest test set that covers the changed boundary, then broaden when a -change crosses native/managed or RenderGraph execution. +- Built-in material pass names 和 resource semantics 位于 `Builtin/`。一起更新 `BuiltinPassTypes`、 + `BuiltinPassMetadataUtils` 和 `BuiltinPassLayoutUtils`。 +- Material-state resolution 属于 `Materials/`。避免在 passes 中重复 render state conversion logic。 +- Shader variant helpers 分为 public forwarding headers 和 `Internal/`;保持 public includes 对 engine users 稳定。 +- URP shader package paths 应遵循现有 + `Packages/com.xcengine.render-pipelines.universal/...` 约定。 -- Build engine after native Rendering changes: +### 测试体系 + +使用覆盖变更边界的最窄测试集合;当改动跨 native/managed 或 RenderGraph execution 时,再扩大范围。 + +- Native Rendering 改动后构建 engine: `cmake --build --config Debug --target XCEngine` -- Build managed assemblies after ScriptCore or URP changes: +- ScriptCore 或 URP 改动后构建 managed assemblies: `cmake --build --config Debug --target xcengine_managed_assemblies` -- Build native rendering unit tests: +- 构建 native rendering unit tests: `cmake --build --config Debug --target rendering_unit_tests` -- Run native rendering tests directly: +- 直接运行 native rendering tests: `/tests/Rendering/unit//rendering_unit_tests` -- Or run the native rendering CTest subset: +- 或运行 native rendering CTest 子集: `ctest -C Debug -R "RenderGraph|CameraFrame|SceneRender|RenderPass|BuiltinForward|FullscreenPass" --output-on-failure` -- Build scripting bridge tests: +- 构建 scripting bridge tests: `cmake --build --config Debug --target scripting_tests` -- Run scripting bridge tests directly: +- 直接运行 scripting bridge tests: `/tests/scripting//scripting_tests` -- Or run the SRP/URP scripting CTest subset: +- 或运行 SRP/URP scripting CTest 子集: `ctest -C Debug -R "MonoScriptRuntimeTest|ProjectScriptAssemblyTest" --output-on-failure` -- Run the renderer phase regression suite when SRP/URP phase ordering, renderer - features, or editor viewport rendering changes: +- 当 SRP/URP phase ordering、renderer features 或 editor viewport rendering 改动时,运行 renderer phase + regression suite: `cmake --build --config Debug --target rendering_phase_regression` -- Useful probe files for managed API changes: - `managed/GameScripts/RenderPipelineApiProbe.cs`, - `managed/GameScripts/ScriptableRenderContextApiSurfaceProbe.cs`, and - `project/Assets/Scripts/ProjectRenderPipelineProbe.cs`. -- Important native test files: - `tests/Rendering/unit/test_render_graph.cpp`, - `tests/Rendering/unit/test_camera_frame_graph_stage_policy.cpp`, - `tests/Rendering/unit/test_camera_frame_graph_stage_contract.cpp`, - `tests/Rendering/unit/test_camera_scene_renderer.cpp`, - `tests/Rendering/unit/test_scene_render_request_planner.cpp`, and - `tests/scripting/test_mono_script_runtime.cpp`. +- Managed API 改动常用 probe files: + `managed/GameScripts/RenderPipelineApiProbe.cs`、 + `managed/GameScripts/ScriptableRenderContextApiSurfaceProbe.cs` 和 + `project/Assets/Scripts/ProjectRenderPipelineProbe.cs`。 +- 重要 native test files: + `tests/Rendering/unit/test_render_graph.cpp`、 + `tests/Rendering/unit/test_camera_frame_graph_stage_policy.cpp`、 + `tests/Rendering/unit/test_camera_frame_graph_stage_contract.cpp`、 + `tests/Rendering/unit/test_camera_scene_renderer.cpp`、 + `tests/Rendering/unit/test_scene_render_request_planner.cpp` 和 + `tests/scripting/test_mono_script_runtime.cpp`。 -## Current Debt +### 当前债务 -- Managed SRP is still an SRP v1 surface. Main scene drawing is recorded through - managed calls but executed by native scene draw backends. -- Managed `CommandBuffer` and public `SetRenderFunc` do not execute deferred - native command lists yet. -- Managed RenderGraph currently exposes raster authoring. Native graph has - compute pass support, but managed compute authoring is not public. -- `UniversalPostProcessBlock` mostly owns planning and promotion. Actual - post-process work currently comes from features/passes. -- `UniversalRendererData` and features are code-created objects, not a full - Unity-style serialized asset pipeline. -- Current shadow support is a single main directional shadow path with no - cascades. -- The graph compiler/executor does not currently implement pass culling or - transient aliasing. +- Managed SRP 仍是 SRP v1 surface。Main scene drawing 通过 managed calls 记录,但由 native scene draw + backends 执行。 +- Managed `CommandBuffer` 和 public `SetRenderFunc` 还不会执行 deferred native command lists。 +- Managed RenderGraph 当前暴露 raster authoring。Native graph 有 compute pass support,但 managed compute + authoring 还未公开。 +- `UniversalPostProcessBlock` 主要负责 planning 和 promotion。实际 post-process work 当前来自 features/passes。 +- `UniversalRendererData` 和 features 是 code-created objects,还不是完整 Unity 风格 serialized asset pipeline。 +- 当前 shadow support 是单个 main directional shadow path,没有 cascades。 +- Graph compiler/executor 当前没有实现 pass culling 或 transient aliasing。 -## Past Execution +## 【过去进展】 -This section records architecture cuts that have already been made. Keep it as a -running ledger when future changes close or move ownership boundaries. +### 已完成的架构切分 -- `GraphicsSettings.renderPipelineAsset` selects managed SRP assets through - `ManagedScriptableRenderPipelineAsset` and `GraphicsSettingsState`. -- Managed SRP execution is hosted by `ScriptableRenderPipelineHost`, which - combines a native backend with an optional managed stage recorder. -- Mono-backed SRP assets use `DefaultNativeBackend` for scene drawing and record - managed stages into the native RenderGraph. -- URP now has renderer data, renderer features, renderer pass queueing, renderer - blocks, renderer-index resolution, and per-stage recording. -- Public managed RenderGraph raster authoring exists; internal fullscreen - kernels remain URP implementation details. -- Public `ScriptableRenderPass.RecordRenderGraph(RenderGraph, ContextContainer)` - receives real URP frame data through `RenderingData`, `CameraData`, - `LightingData`, `ShadowData`, `EnvironmentData`, `FinalColorData`, and - `StageColorData`. -- Public managed `SceneRenderInjectionPoint` has been removed. Managed SRP/URP - authors should use `RenderPassEvent`, renderer blocks, renderer-list drawing, - and RenderGraph declarations instead of native private injection points. -- Main scene, post process, final output, object id, depth-only, and - shadow-caster stages are centralized under `CameraFrameStage` and - `CameraFramePlan`. -- Final color processing is represented as a policy and a final output stage, - not as implicit swapchain behavior. -- Object-id rendering is a top-level tooling pass guarded by - `XCENGINE_ENABLE_RENDERING_EDITOR_SUPPORT`. +本节记录已经完成的架构切分。未来改动关闭或移动所有权边界时,继续把它作为流水账维护。 + +- `GraphicsSettings.renderPipelineAsset` 已通过 `ManagedScriptableRenderPipelineAsset` 和 + `GraphicsSettingsState` 选择 managed SRP assets。 +- Managed SRP execution 由 `ScriptableRenderPipelineHost` 承载,它组合 native backend 和可选 managed + stage recorder。 +- Mono-backed SRP assets 使用 `DefaultNativeBackend` 做 scene drawing,并把 managed stages 记录到 native + RenderGraph。 +- URP 现在已有 renderer data、renderer features、renderer pass queueing、renderer blocks、renderer-index + resolution 和 per-stage recording。 +- Public managed RenderGraph raster authoring 已存在;internal fullscreen kernels 仍是 URP implementation + details。 +- Public `ScriptableRenderPass.RecordRenderGraph(RenderGraph, ContextContainer)` 通过 `RenderingData`、 + `CameraData`、`LightingData`、`ShadowData`、`EnvironmentData`、`FinalColorData` 和 `StageColorData` + 接收真实 URP frame data。 +- Public managed `SceneRenderInjectionPoint` 已移除。Managed SRP/URP authors 应使用 `RenderPassEvent`、 + renderer blocks、renderer-list drawing 和 RenderGraph declarations,而不是 native private injection points。 +- Main scene、post process、final output、object id、depth-only 和 shadow-caster stages 已集中到 + `CameraFrameStage` 和 `CameraFramePlan`。 +- Final color processing 表示为 policy 和 final output stage,而不是 implicit swapchain behavior。 +- Object-id rendering 是 top-level tooling pass,并由 `XCENGINE_ENABLE_RENDERING_EDITOR_SUPPORT` guard。