Files
XCEngine/engine/include/XCEngine/Rendering/AGENTS.md

34 KiB
Raw Blame History

渲染模块 Agent 指南

本文是修改 engine/include/XCEngine/Renderingengine/src/Rendering,以及 managed/ 下配套 managed SRP/URP 表面的工作地图。它不能替代阅读实现代码。 如果本文和代码冲突,以代码为准,并在同一次改动里更新本文。

【未来目标】

方向

渲染器有意参考 Unity SRP 和 URP 设计。后续工作在概念适配本引擎时,应优先采用 Unity 兼容的公开命名、对象所有权和扩展点。

  • 保持 managed 公开表面接近 UnityGraphicsSettings.renderPipelineAssetRenderPipelineAssetScriptableRenderPipelineAssetScriptableRenderPipelineScriptableRenderContextUniversalRenderPipelineAssetUniversalRendererDataScriptableRendererScriptableRendererFeatureScriptableRenderPassRenderPassEventContextContainerRenderGraph
  • 在发明新的公开词汇前,优先对齐行为。如果某个 Unity 概念在这里只实现了一部分, 要诚实暴露已实现的子集,把缺失行为留在内部代码或测试里。
  • 保留 Unity 风格的 RenderPassEvent 数值顺序。新增或移动事件时,必须一起更新 ScriptableRenderPass.TryResolveRendererBlockRendererBlocks、probes 和测试。
  • 管线自定义优先使用 managed URP features 和 passes。Native 路径应提供后端执行、 场景提取、fallback passes 和工具支持。
  • 渲染器代码保持后端无关。D3D12、OpenGL 和 Vulkan 细节属于 engine/include/XCEngine/RHI/**engine/src/RHI/** 或 editor host rendering 不应进入 SRP/URP 策略层。

近期目标

当前优先级是完成 SRP/URP 架构切分,并在每条边界上补目标明确的测试。近期产品目标 是让 URP 成为渲染决策层,让 native rendering 成为执行层。

  • BuiltinForwardPipeline 从策略中心降级为默认 native scene draw backend。它可以 继续作为 backend/fallback 实现存在,但不应决定 URP pass 顺序、feature 参与方式或 stage 策略。
  • ScriptableRenderer 及其 active pass queue 成为 URP stage planning 和 recording 的权威。 Opaque、skybox、transparent、depth、shadow、post 和 final-output 流程应来自 URP blocks 和 passes。
  • 保持 DrawObjectsPassDrawSkyboxPass 作为 managed URP pass declarations并通过 RenderGraph renderer-list declarations 和 native scene draw backend 执行。
  • 收紧 stage 支持规则。如果 fullscreen 或 main-scene stage 需要 managed graph recording 必须要求所选 renderer/pipeline 支持并记录该 stage。
  • 只在 Unity 形态的 API 后面扩展 managed RenderGraphresource declarations、frame data、 renderer-list drawing、pass data 和 command recording。避免暴露 native 私有 graph 或 scene-recorder 细节。
  • 在切分架构时补 contract testsURP selection、renderer data selection、renderer override、 pass event ordering、renderer feature invalidation、stage planning、RenderGraph recording 以及 no hidden built-in fallback。
  • 等 SRP/URP 所有权边界稳定后,再做大范围测试体系重组。过早重组有可能固化当前的过渡行为。

修改规则

  • 行为变更要从 pipeline asset/request/plan 路径开始。app/editor 代码中的临时 pass execution 通常表示层级位置不对。
  • 顶层 native renderer 的公开选择和配置入口只能是 RenderPipelineAsset。不要新增或恢复 CameraRendererRenderPipelineHostSceneRenderer 上接受裸 RenderPipeline 的 public constructor/setter需要定制 pipeline 实例时,通过 RenderPipelineAsset::CreatePipelineRenderPipelineAsset::ConfigurePipeline 完成。
  • Native headers 保持小而后端无关。可行时 forward declare RHI 类型,只在后端代码里 include 具体后端头。
  • 新增 camera-stack、renderer-index、shadow、depth、post-process 或 final output 行为时,不要绕过 CameraFramePlanBuilderSceneRenderRequestPlanner
  • 修改 camera stack 行为时,要保持 CameraRenderRequest.cameraStackIdCameraStackFramePlanRenderPipelineHost::BuildStackFramePlansSceneRenderer::BuildStackFramePlans 同步。 CameraFramePlan 是每个 camera 的叶子计划;CameraStackFramePlan 是顶层渲染生命周期根。
  • 不要在 native 长生命周期对象里保存 raw managed object pointers 或 managed context handles。 需要持久化时,通过现有 external managed object handle 系统 retain。
  • Managed URP public APIs 不要依赖 CameraFrameGraphNativeSceneRecorder 这类 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。
  • 修改 URP stage planning、stage support 或 recording 行为时,要保持 CameraFramePlan.framePlanIdRenderPipelineStageSupportContext.framePlanIdRenderPipelineStageRenderGraphContext.framePlanIdScriptableRenderPipelinePlanningContext.framePlanIdScriptableRenderContext.framePlanId 同步。 framePlanId 是 per-camera-frame plan 的托管快照键,不是 renderer 或 camera 的长期身份。
  • 新增 public managed rendering type 时,将它加入 managed/CMakeLists.txt,并在对应 managed probe 里覆盖 API presence。

【当下事实】

架构基线

这些事实是当前架构基线。除非有明确的架构切分和测试,不要削弱它们。

  • 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 recordingnative 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。
  • CameraFramePlanBuilder 现在负责从 request 构造 per-camera CameraFramePlan,再按 CameraRenderRequest.cameraStackId 收口为 CameraStackFramePlan。它委托所选 RenderPipelineAsset::ConfigureCameraFramePlan 配置叶子计划,不再在 asset hook 之后追加通用 legacy fullscreen stage heuristic默认 native fullscreen/final-output 行为应留在 native asset policy 内部。
  • Hidden fallback 很危险。如果 managed URP stage 声明支持但无法 record失败必须可见。不要静默用 default built-in path 画同一个 stage然后称之为 URP。
  • Camera-frame graph dispatch 必须询问所选 pipeline 是否允许 legacy stage fallback。Managed ScriptableRenderPipelineHost 在 stage recorder 或 managed runtime 权威时不允许 fallback此时缺少 recorder、sequence 或 standalone pass 要在 graph recording 阶段失败,而不是排入 built-in fallback。
  • 测试体系已经有有价值的覆盖,但还不足以宣称 SRP/URP stack 完全锁定。随着架构边界收口,应补高价值 contract tests现阶段不要为了大范围测试体系重写而暂停架构工作。

管线选择

  • GraphicsSettings.renderPipelineAsset == null 表示 renderer 使用 engine default native pipeline selection。
  • GraphicsSettings.renderPipelineAsset != null 表示 renderer 使用 render-pipeline asset reference selection path。 AssetRef 是长期选择身份managed descriptor 中的 serialized ScriptableObject graph 和 handle 只是运行时 materialization cache 和过渡 fallback。
  • Runtime startup 不应静默指定 project default SRP asset。Project 或 editor policy 可以显式选择一个, 但 active rendering mode 必须能通过 GraphicsSettings.renderPipelineAsset 观察到。
  • GraphicsSettingsState 同时保存 configured render-pipeline asset AssetRefManagedRenderPipelineAssetDescriptor runtime cache。只要 AssetRef 存在,它就是选择根;后续 managed materialization 只能更新 descriptor cache不得清掉或替换该 asset reference。
  • 如果 managed asset 无法创建有效 pipeline、recorder 或 backend bridge应显式失败并让 top-level factory 选择 fallback path。不要让 ScriptableRenderPipelineHost 看起来像成功的 managed SRP同时在背后用 hidden native path 渲染不受支持的 managed stage。
  • 保持已删除的 public bridge types 不再出现: RendererBackedRenderPipelineAssetRendererBackedRenderPipelineRendererDrivenRenderPipeline

当前形态

Native renderer 现在是 camera frame planner 加 RenderGraph executormanaged SRP/URP recording 叠在 native scene draw backend 之上。

  • SceneRenderer 是 scene-level convenience entry point。它的公开管线选择根是 RenderPipelineAsset 它通过 SceneRenderRequestPlanner 收集 camera requests通过 RenderPipelineHost 构建 CameraStackFramePlan,然后以 camera stack 为根渲染。旧的 BuildFramePlans/flat-plan Render API 只是兼容包装。
  • RenderPipelineHost 拥有一个 CameraFramePlanBuilder 和一个 CameraRenderer。它是从 CameraRenderRequestCameraStackFramePlan 的常规 native bridge并沿用同一个 asset selection root。 Stack 渲染完成后由所选 RenderPipeline 接收 FinishCameraStackRendering,用于 URP stack 生命周期收尾。
  • CameraRenderer 拥有 asset 创建出的所选 RenderPipeline,提取 RenderSceneData,解析 directional shadow execution把全部 frame stages 记录进 native RenderGraph,编译 graph 并执行。
  • RenderPipelineAsset 是 native asset contract。它创建 pipeline配置 pipeline 实例,配置 request policy配置 frame plan policy并提供默认 final color settings。
  • RenderPipelineRenderPipelineBackendRenderPipelineStageRecorder 将 backend rendering 与 graph recording 分开。Managed SRP 通常提供 stage recordernative backend 提供 scene drawing。
  • Native/managed bridge 词汇已经收口为 PipelineBackendSceneDrawBackend。不要重新引入 PipelineRendererNativeSceneRenderer 或以 renderer 命名的 backend asset APISceneRenderer 只保留为 scene-level convenience entry point。

帧阶段

CameraFrameStage 是权威 frame-stage model。保持所有 native 和 managed stage enum 同步。

  • 当前有序 stages 是 PreScenePassesShadowCasterDepthOnlyMainScenePostProcessFinalOutputObjectIdPostScenePassesOverlayPasses
  • ShadowCasterDepthOnlyObjectId 是 standalone-pass stages。MainScene 是主 pipeline stage。 PostProcessFinalOutput 是 fullscreen sequence stages没有 legacy RenderPassSequence 时, 它们可以由 pipeline 进行 graph recording。
  • 使用 CameraFramePlan APIs例如 RequestFullscreenStageClearFullscreenStageRequestShadowCasterStageRequestDepthOnlyStage。除非在 plan implementation 内部,否则不要直接 改 plan stage fields。
  • Graph-managed color flow 是显式的。CameraFrameColorSourceUsesGraphManagedSceneColorUsesGraphManagedOutputColor 决定 stage 是读取 main scene、post process 还是 explicit surface。
  • 新增 stage 时,更新 CameraFrameStage.h、managed CameraFrameStage.csCameraFramePlan、 camera-frame graph state/policy、stage dispatch/contract tests、managed probes以及所有 Mono internal-call conversion code。

RenderGraph

Native RenderGraph 是 camera frames 的执行主干。

  • 所有 graph resource usage 都通过 RenderGraphBuilderRenderGraphPassBuilder 记录;不要依赖隐藏的 RHI side effects。
  • Imported textures 需要有效 descriptions。如果 graphOwnsTransitions 为 trueimported view 必须暴露 texture以便 executor 创建 barriers。
  • Transient textures 需要有效 width、height、format、type 和 sample description。无效 transient reads 是 compile errors。
  • 使用 RenderGraphRecordingContext helpers 在 RenderPassSceneRenderFeaturePass 和 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。

Native Passes

Native passes 仍用于 backend fallback、工具和 built-in rendering。

  • 新 native passes 应尽可能实现 RecordRenderGraph。只有 legacy execution 仍需要时,才把 Execute 保留为 fallback path。
  • 对 fallback-compatible raster passes使用 RenderPassGraphContractRecordRenderGraphSurfaceIO 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 分离。

Managed Boundary

Managed SRP assets 通过 GraphicsSettings.renderPipelineAsset 选择,并通过 ManagedScriptableRenderPipelineAsset bridge。

  • ManagedRenderPipelineAssetDescriptor 标识 managed asset assembly、namespace、class、可选 AssetRef、 serialized ScriptableObject asset graph 和 retained managed object handle。它不再是 configured pipeline 的唯一身份;GraphicsSettingsState 中的 configured AssetRef 才是 Unity 风格 asset selection root。
  • Descriptor-only selection 仍保留给测试、legacy runtime fallback 和尚未接入 asset import 的路径;但 GraphicsSettings.renderPipelineAsset getter 和任何带 AssetRef 的 managed runtime path 在没有 serializedAssetGraph 时都必须显式失败,不能按 class 默认构造 materialize。只有明确的 descriptor-only legacy/test path 才允许 class-default fallback一旦 snapshot 存在,缺失或失效的 managed object handle 必须从 snapshot 重建,不能退回 code-created default asset。
  • GraphicsSettings.renderPipelineAsset = asset 必须把当前 managed SRP asset graph snapshot 收进 descriptor。 该 snapshot 覆盖 UniversalRenderPipelineAsset -> ScriptableRendererData -> ScriptableRendererFeature 以及 public/[SerializeField] serializable settings。Runtime cache 更新可以替换 handle但不得丢失 snapshot 或 configured AssetRef
  • 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 创建 MonoManagedRenderPipelineAssetRuntimeMonoManagedRenderPipelineStageRecorder。 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。URP 内置对象和 skybox drawing 通过 managed RenderGraph 声明 renderer list、attachments 和 render func再由 native SceneDrawBackend 执行。ScriptableRenderContext.DrawRenderersDrawSkybox 仍作为 SRP v1 兼容入口保留, 并委托给 NativeSceneRecorder
  • Managed resource/version invalidation 是正确性的一部分。如果 managed asset、renderer data 或 feature 修改 runtime state调用 SetDirty 或本地 invalidation helper确保 native runtime caches 被释放。 当前 runtime version 也会兜底 hash UniversalRenderPipelineAsset 的 shadow/final-color settings以及 UniversalRendererData 自身的 main-scene、shadow-caster 和 depth-prepass block settings新增可序列化 renderer data/asset settings 时,必须把影响 request、planning、stage manifest 或 pass queue 的字段纳入 对应 runtime hash。

URP Model

URP package 位于 managed/XCEngine.RenderPipelines.Universal。它应被视为主要面向用户的 render pipeline package。

  • UniversalRenderPipelineAsset 拥有 rendererDataListdefaultRendererIndexUniversalShadowSettingsUniversalFinalColorSettings。它从 UniversalAdditionalCameraData 解析 renderer index然后委托给 renderer data。
  • ScriptableRendererData 拥有持久 renderer instance 和 renderer feature collection。Renderer data dirty state 会释放 renderer setup cache并递增 runtime state version。
  • ScriptableRendererData 的 runtime state version 不只来自 feature collection。UniversalRendererData 已把 mainSceneshadowCasterdepthPrepass block settings 纳入 hash这些 settings 改变时必须 触发 renderer cache 释放和 pass queue/stage manifest 重建。
  • ScriptableRenderer 按 per-camera pass queue 构建 m_activePassQueue。它依次调用 feature SetupRenderPasses、feature AddRenderPasses,再调用 renderer-owned AddRenderPasses;这些声明入口接收 RendererPassQueueData,不暴露 RenderingData.stagepasses 按 RenderPassEvent 顺序插入,并归组到 RendererBlocks
  • URP stage planning 以 ScriptableRenderer 的 active pass queue 为最终事实源。ConfigureCameraFramePlan 仍是兼容和高级策略 hook但它不能单独声明 shadow、depth、post 或 final-output stage没有被 pass queue 覆盖到的 side/fullscreen stage 必须在最终 plan 中清掉。
  • Native CameraFramePlanBuilder 不得在 renderer/pass-queue-derived manifest 应用之后再补 fullscreen stage 请求URP path 中 post/final stage 的存在性必须完全来自 ScriptableRenderer active pass queue。
  • ConfigurePassQueueCameraFramePlanInstance 必须在 planning 阶段为当前 renderer 和 framePlanId 生成一次 per-camera RendererFramePlan,冻结 active pass queue 中每个 pass 的当帧状态,并用同一份 plan 派生 stage manifest。SupportsStageRenderGraphRecordStageRenderGraphframePlanId != 0 时必须消费这个 plan不得重新运行 feature SetupRenderPasses、feature AddRenderPasses 或 renderer-owned AddRenderPasses 来重建队列。 找不到匹配 framePlanId 和 renderer index 的 plan 时必须返回不支持或 record 失败,让上层暴露错误; 不要退回 legacy queue rebuild 或 built-in fallback。
  • RendererFramePlan 不得只是 pass 对象引用列表。ScriptableRenderPass.CreateFramePlanSnapshot 是冻结 pass 状态的边界;新增 mutable pass state 时必须确认它能被 frame-plan snapshot 捕获,避免后续 camera planning 改写前一个 camera 的 recording。
  • OnFinishCameraStackRendering 是 camera-stack 生命周期回调,不是 per-stage 或 per-camera-frame 回调。 ScriptableRenderer 可以在 RecordRendererFromFramePlan 时登记待收尾的 RendererFramePlan,但只能由 native CameraStackFramePlan 渲染完成后的 FinishCameraStackRendering 触发实际回调。
  • URP features 的 AddRenderPasses 是 per-camera 声明点,不是 per-stage 回调。不要通过 stage 数据分阶段重复 enqueueAddRenderPasses/SetupRenderPasses 必须使用 RendererPassQueueData 而不是 recording 阶段的 RenderingData。pass 所属 stage 应由 RenderPassEvent -> RendererBlock 映射决定renderer recording 再按 block range 消费同一份 queue。
  • RendererBlock 将 pass events 映射到 camera stagesshadow caster、depth prepass、main opaque、main skybox、main transparent、post process 和 final output。
  • UniversalRenderer 拥有具体 blocks UniversalShadowCasterBlockUniversalDepthPrepassBlockUniversalMainSceneBlockUniversalPostProcessBlockUniversalFinalOutputBlock
  • Built-in URP passes 包括 DrawObjectsPassDrawSkyboxPass 和内部 BuiltinFinalColorPass。当前 feature implementations 包括 RenderObjectsRendererFeatureColorScalePostProcessRendererFeatureDisableDirectionalShadowRendererFeature
  • 新增 URP feature 时,保持 serializable settings、runtime hash、CreateConfigureCameraRenderRequestConfigureRenderSceneSetupAddRenderPasses 和 stage gate behavior 一致。 如果 feature 需要 stage必须 enqueue 一个 RenderPassEvent 匹配该 stage 的 pass不要只依赖 ConfigureCameraFramePlan 请求 stage。

Managed RenderGraph

Managed RenderGraph 目前有意保持较小,但应维持 Unity 的现代形态。

  • Public managed authoring 通过 XCEngine.Rendering.RenderGraphModule.RenderGraph.AddRasterPassRenderGraphRasterPassBuilder 进行。
  • Public passes 应声明 reads、bindings、color attachments、depth attachment 和 render func然后 Commit
  • Renderer-list drawing 是 RenderGraph authoring 的一等声明:先用 RenderGraph.CreateRendererList(RendererListDesc, DrawingSettings) 创建 RendererListHandle,再通过 RenderGraphRasterPassBuilder.UseRendererList 声明 pass 依赖,最后在 render func 中调用 CommandBuffer.DrawRendererList。URP 内置 DrawObjectsPass 必须走这条路径。
  • Skybox drawing 也应从 managed raster pass 的 render func 进入 CommandBuffer.DrawSkybox。URP 内置 DrawSkyboxPass 不应再直接在 recording 阶段调用 ScriptableRenderContext.DrawSkybox
  • Internal fullscreen helpers例如 color scale、shader vector 和 final color是 URP implementation details。 不要把它们作为 public ScriptableRenderContext shortcuts 暴露。
  • Managed SetRenderFunc 是 deferred RenderGraph execution callback。Mono bridge 必须 retain delegate 在 native graph pass 执行时创建 pass-scoped CommandBuffer,并把已支持的 managed command stream flush 到 当前 RHICommandList。当前公开命令子集是 CommandBuffer.ClearRenderTarget(Color)CommandBuffer.DrawRendererList(RendererListHandle)CommandBuffer.DrawSkybox();没有 native command stream 和 executor 测试的命令不要暴露成 public API。
  • Public RenderGraph frame data 由同一个 renderer stage 内记录的所有 passes 共享。保持 ContextContainer 作为 stage frame data而不是 pass-local scratch data。
  • Fullscreen internal passes 需要有效 sourceColorTextureprimaryColorTarget。Multi-pass fullscreen chains 应在每个 pass 后更新 current source color。

Scene Data

Scene data 每个 camera frame 提取一次,然后由 pipeline 调整。

  • 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 中。

Materials And Shaders

  • Built-in material pass names 和 resource semantics 位于 Builtin/。一起更新 BuiltinPassTypesBuiltinPassMetadataUtilsBuiltinPassLayoutUtils
  • 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/... 约定。

测试体系

使用覆盖变更边界的最窄测试集合;当改动跨 native/managed 或 RenderGraph execution 时,再扩大范围。

  • Native Rendering 改动后构建 engine cmake --build <build-dir> --config Debug --target XCEngine
  • ScriptCore 或 URP 改动后构建 managed assemblies cmake --build <build-dir> --config Debug --target xcengine_managed_assemblies
  • 构建 native rendering unit tests cmake --build <build-dir> --config Debug --target rendering_unit_tests
  • 直接运行 native rendering tests <build-dir>/tests/Rendering/unit/<config>/rendering_unit_tests
  • 或运行 native rendering CTest 子集: ctest -C Debug -R "RenderGraph|CameraFrame|SceneRender|RenderPass|BuiltinForward|FullscreenPass" --output-on-failure
  • 构建 scripting bridge tests cmake --build <build-dir> --config Debug --target scripting_tests
  • 直接运行 scripting bridge tests <build-dir>/tests/scripting/<config>/scripting_tests
  • 或运行 SRP/URP scripting CTest 子集: ctest -C Debug -R "MonoScriptRuntimeTest|ProjectScriptAssemblyTest" --output-on-failure
  • 当 SRP/URP phase ordering、renderer features 或 editor viewport rendering 改动时,运行 renderer phase regression suite cmake --build <build-dir> --config Debug --target rendering_phase_regression
  • Managed API 改动常用 probe files managed/GameScripts/RenderPipelineApiProbe.csmanaged/GameScripts/ScriptableRenderContextApiSurfaceProbe.csproject/Assets/Scripts/ProjectRenderPipelineProbe.cs
  • 重要 native test files tests/Rendering/unit/test_render_graph.cpptests/Rendering/unit/test_camera_frame_graph_stage_policy.cpptests/Rendering/unit/test_camera_frame_graph_stage_contract.cpptests/Rendering/unit/test_camera_scene_renderer.cpptests/Rendering/unit/test_scene_render_request_planner.cpptests/scripting/test_mono_script_runtime.cpp

当前债务

  • Managed SRP 仍是 SRP v1 surface。Main scene drawing 现在可通过 managed RenderGraph renderer-list declarations 记录,但实际绘制仍由 native scene draw backends 执行。
  • Managed CommandBuffer 已能随 public SetRenderFunc 延迟到 RenderGraph 执行期运行,但它不是完整 Unity CommandBuffer;新增命令必须一起补 native command stream、RHI flush 和 scripting bridge tests。
  • Managed RenderGraph 当前暴露 raster authoring。Native graph 有 compute pass support但 managed compute authoring 还未公开。
  • UniversalPostProcessBlock 仍保留 post-process source promotion helper实际 post-process stage 由 active pass queue 中的 features/passes 声明。
  • 当前 camera stack 归属仍来自 SceneRenderRequestPlanner 对 base/overlay 请求流的 cameraStackId 分组;引擎相机数据模型还没有 Unity cameraStack 那种显式 per-base overlay 列表。
  • Render-pipeline selection 已切到 AssetRef 作为根身份,并且 managed SRP descriptor 已保存 ScriptableObject graph snapshot完整 editor/importer .asset 持久化和 sub-asset authoring 仍未完成。
  • 当前 shadow support 是单个 main directional shadow path没有 cascades。
  • Graph compiler/executor 当前没有实现 pass culling 或 transient aliasing。

【过去进展】

已完成的架构切分

本节记录已经完成的架构切分。未来改动关闭或移动所有权边界时,继续把它作为流水账维护。

  • GraphicsSettings.renderPipelineAsset 已通过 ManagedScriptableRenderPipelineAssetGraphicsSettingsState 选择 managed SRP assets。
  • Render-pipeline asset selection 已从 descriptor/managed handle 切到 AssetRef 根身份descriptor 保留为 assembly/type/handle runtime cachemanaged materialization 更新 cache 时保留 configured asset reference。
  • Managed SRP descriptor 已接入 serialized ScriptableObject graph snapshot。GraphicsSettings setter 保存 当前 asset/data/features 图getter 和 MonoManagedRenderPipelineAssetRuntime 在 handle 缺失或失效时按 snapshot 重建;GraphicsSettings getter 与任何带 AssetRef 的 runtime path 不再接受无 snapshot 的 class 默认构造,只有 descriptor-only legacy/test path 保留该 fallback。
  • Managed SRP execution 由 ScriptableRenderPipelineHost 承载,它组合 native backend 和可选 managed stage recorder。
  • Mono-backed SRP assets 使用 DefaultNativeBackend 做 scene drawing并把 managed stages 记录到 native RenderGraph。
  • DefaultNativeBackend 解析到 default scene draw backend asset而不是带 standalone fallback passes 的 top-level pipeline asset。Managed host 组合任意 backend asset 时不自动安装 object-id、depth-only 或 shadow-caster fallback passes。
  • Native SRP/URP bridge contract tests 已对齐当前命名和所有权backend asset 创建 SceneDrawBackendstage recorder 失败不会静默落回 native backendgraph-owned imported surface 的 test views 必须提供 texture-backed view。
  • URP 现在已有 renderer data、renderer features、renderer pass queueing、renderer blocks、renderer-index resolution 和 per-stage recording。
  • URP stage planning 已收口到 renderer active pass queue 派生的 per-framePlanId RendererFramePlan 和 stage manifest。Stage support 和 stage recording 现在消费 planning 阶段保存的同一份冻结 plan 关闭了 feature planning hook、support probe、recording 和各 stage 分别重建 pass queue 的重复事实源。
  • 顶层 native orchestration 已从 flat camera frame list 收口为 CameraStackFramePlanSceneRendererRenderPipelineHost 的真实渲染入口以 camera stack 为根flat CameraFramePlan APIs 保留为兼容包装。
  • URP OnFinishCameraStackRendering 已改为 stack-end 语义recording 阶段只登记待收尾 passnative CameraStackFramePlan 渲染完成后再通过 pipeline/stage-recorder bridge 触发。
  • CameraFramePlanBuilder 已移除对 fullscreen stages 的通用尾部自动补齐selected RenderPipelineAsset 现在是 native plan policy 的唯一入口managed URP path 不再保留第二个 fullscreen stage planner。
  • ScriptableRenderPass.CreateFramePlanSnapshot 已接入 RendererFramePlan 生成路径。多 camera planning 会冻结 每个 camera 当时的 pass 状态,后续 camera 对复用 pass 实例的 Configure 不应污染已生成的 frame plan。
  • AddRenderPasses/SetupRenderPasses 已从 recording RenderingData 分离到 RendererPassQueueDataRendererPassQueueData 是 per-camera queue 声明数据,故意不携带 stagestage 信息只应在 pass recording 阶段通过 RenderingData/ScriptableRenderContext 消费。
  • URP runtime-state invalidation 已覆盖 asset-level shadow/final-color settings 和 renderer-data-level main-scene/shadow-caster/depth-prepass block settings。配置变更会通过 runtime resource version 释放 renderer caches并让后续 planning 重新生成 RendererFramePlan 和 stage manifest。
  • Public managed RenderGraph raster authoring 已存在internal fullscreen kernels 仍是 URP implementation details。
  • Public managed SetRenderFunc 已从 recording-time 调用改为 RenderGraph execution-time 调用; native 通过 retained managed delegate 和 pass-scoped CommandBuffer bridge 执行已支持的 command stream 当前支持 CommandBuffer.ClearRenderTarget(Color)CommandBuffer.DrawRendererList(RendererListHandle)CommandBuffer.DrawSkybox()
  • Renderer-list drawing 已成为 managed RenderGraph 声明:RenderGraph.CreateRendererList 创建 RendererListHandleRenderGraphRasterPassBuilder.UseRendererList 把 renderer list 纳入 pass declaration CommandBuffer.DrawRendererList 在 RenderGraph 执行期触发 native SceneDrawBackend。URP 内置 DrawObjectsPassDrawSkyboxPass 已迁离 recording-time ScriptableRenderContext.DrawRenderers/DrawSkybox 主路径。
  • Public ScriptableRenderPass.RecordRenderGraph(RenderGraph, ContextContainer) 通过 RenderingDataCameraDataLightingDataShadowDataEnvironmentDataFinalColorDataStageColorData 接收真实 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 已集中到 CameraFrameStageCameraFramePlan
  • Final color processing 表示为 policy 和 final output stage而不是 implicit swapchain behavior。
  • Object-id rendering 是 top-level tooling pass并由 XCENGINE_ENABLE_RENDERING_EDITOR_SUPPORT guard。
  • Camera-frame graph dispatch 已收紧 legacy fallback gate只有所选 pipeline 明确允许时,未被 render-graph recorder、pass sequence 或 standalone pass 处理的 stage 才能进入 fallback raster pass。 Managed SRP/URP host 不允许 hidden built-in fallback。