From 73821ff73fbfeac02ab8b38b02c40bd00329f73b Mon Sep 17 00:00:00 2001 From: ssdfasd <2156608475@qq.com> Date: Fri, 3 Apr 2026 13:51:27 +0800 Subject: [PATCH] docs: sync builtin forward pipeline docs --- .../BuildInputLayout.md | 53 +++++++++++ .../BuiltinForwardPipeline.md | 94 ++++++++++++------- .../BuiltinForwardPipeline/Constructor.md | 42 +++++++++ .../BuiltinForwardPipeline/Destructor.md | 6 +- .../BuiltinForwardPipeline/Initialize.md | 26 +++-- .../BuiltinForwardPipeline/Render.md | 62 +++++++----- .../BuiltinForwardPipeline/Shutdown.md | 35 +++++-- .../BuiltinForwardPipelineAsset.md | 49 ++++++++++ .../CreatePipeline.md | 47 ++++++++++ .../XCEngine/Rendering/Pipelines/Pipelines.md | 47 ++++++++-- .../RenderPipelineAsset/CreatePipeline.md | 47 ++++++++-- .../RenderPipelineAsset.md | 66 ++++++++++--- docs/api/XCEngine/Rendering/Rendering.md | 25 +++-- 13 files changed, 483 insertions(+), 116 deletions(-) create mode 100644 docs/api/XCEngine/Rendering/Pipelines/BuiltinForwardPipeline/BuildInputLayout.md create mode 100644 docs/api/XCEngine/Rendering/Pipelines/BuiltinForwardPipeline/Constructor.md create mode 100644 docs/api/XCEngine/Rendering/Pipelines/BuiltinForwardPipelineAsset/BuiltinForwardPipelineAsset.md create mode 100644 docs/api/XCEngine/Rendering/Pipelines/BuiltinForwardPipelineAsset/CreatePipeline.md diff --git a/docs/api/XCEngine/Rendering/Pipelines/BuiltinForwardPipeline/BuildInputLayout.md b/docs/api/XCEngine/Rendering/Pipelines/BuiltinForwardPipeline/BuildInputLayout.md new file mode 100644 index 00000000..2634faa0 --- /dev/null +++ b/docs/api/XCEngine/Rendering/Pipelines/BuiltinForwardPipeline/BuildInputLayout.md @@ -0,0 +1,53 @@ +# BuiltinForwardPipeline::BuildInputLayout + +**命名空间**: `XCEngine::Rendering::Pipelines` + +**类型**: `method` + +**头文件**: `XCEngine/Rendering/Pipelines/BuiltinForwardPipeline.h` + +返回这条前向管线当前硬编码使用的静态网格顶点布局。 + +```cpp +static RHI::InputLayoutDesc BuildInputLayout(); +``` + +## 当前实现返回值 + +当前固定返回 3 个顶点元素: + +1. `POSITION` + - 格式: `R32G32B32_Float` + - `semanticIndex = 0` + - `inputSlot = 0` + - `alignedByteOffset = 0` +2. `NORMAL` + - 格式: `R32G32B32_Float` + - offset: `offsetof(Resources::StaticMeshVertex, normal)` +3. `TEXCOORD` + - 格式: `R32G32_Float` + - offset: `offsetof(Resources::StaticMeshVertex, uv0)` + +最需要注意的一点是: + +- 位置当前是 `float3`,不是旧实现或旧文档里写过的 `float4` + +这已经由 `tests/Rendering/unit/test_builtin_forward_pipeline.cpp` 明确校验。 + +## 当前语义 + +这个方法定义的不是“通用顶点布局建议”,而是 `BuiltinForwardPipeline` 当前真正依赖的 mesh 输入契约。 + +换句话说: + +- 只要你还在用这条 builtin forward pipeline,就必须保证顶点数据与 `StaticMeshVertex` 的布局兼容 +- 如果你需要不同的顶点流或额外属性,更合理的做法通常是创建新的 pipeline,而不是继续复用这条 builtin 管线 + +## 返回值 + +- `RHI::InputLayoutDesc` - 可直接写入图形管线描述的输入布局 + +## 相关文档 + +- [BuiltinForwardPipeline](BuiltinForwardPipeline.md) +- [Render](Render.md) diff --git a/docs/api/XCEngine/Rendering/Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md b/docs/api/XCEngine/Rendering/Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md index 4144ddba..2930300d 100644 --- a/docs/api/XCEngine/Rendering/Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md +++ b/docs/api/XCEngine/Rendering/Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md @@ -6,56 +6,82 @@ **头文件**: `XCEngine/Rendering/Pipelines/BuiltinForwardPipeline.h` -**描述**: 当前内建的默认前向渲染管线,实现基础纹理采样、深度测试和 mesh 绘制。 +**描述**: 当前内建的前向主渲染管线实现。它会按 shader pass 的资源声明动态构建 `PassResourceLayout`、descriptor set 与 `RHIPipelineState`,并通过 `RenderPassSequence` 执行默认的 opaque pass。 -## 概述 +## 概览 -`BuiltinForwardPipeline` 是当前引擎真正能跑起来的默认渲染管线。 +`BuiltinForwardPipeline` 已经不再是“固定几套 descriptor set + 单一 pipeline layout”的旧模型。当前实现有三条关键缓存链路: -它的工作路径大致是: +- `m_passResourceLayouts`:以 `(shader*, passName)` 为 key,缓存每个 shader pass 的资源布局、pipeline layout、静态 descriptor set 和语义位置。 +- `m_pipelineStates`:以 `(shader*, passName, material render state)` 为 key,缓存真正的图形 pipeline state。 +- `m_dynamicDescriptorSets`:以 `(passLayout, setIndex, objectId, material)` 为 key,缓存逐物体或逐材质的 descriptor set。 -1. 基于 `RenderContext` 创建 pipeline state、descriptor pool、sampler 和 fallback texture。 -2. 使用 [RenderResourceCache](../../RenderResourceCache/RenderResourceCache.md) 把 `Mesh` / `Texture` 上传成 GPU 资源。 -3. 读取 [VisibleRenderObject](../../VisibleRenderObject/VisibleRenderObject.md) 列表。 -4. 为每个物体写常量缓冲、绑定纹理和采样器,然后发出 draw call。 +构造函数只向 `m_passSequence` 注册一个 `BuiltinForwardOpaquePass`。因此当前仍是一条单 pass 的前向路径,但生命周期已经统一收口到 [RenderPassSequence](../../RenderPass/RenderPass.md)。 -## 当前实现能力 +## 当前资源契约 -- 支持 D3D12 与 OpenGL 两套内嵌 shader 路径。 -- 支持颜色附件和深度附件。 -- 支持 mesh section 绘制。 -- 支持从 `Material` 上按若干常见名字查找基础颜色纹理。 -- 当材质或纹理缺失时,使用 1x1 白纹理作为 fallback。 +`BuiltinForwardPipeline` 会优先读取 shader pass 自己声明的 `resources`。如果该列表为空,则回退到 legacy builtin forward 绑定: -## 当前实现限制 +- `set 1 binding 0` -> `PerObject` / `CBV` +- `set 2 binding 0` -> `Material` / `CBV` +- `set 3 binding 0` -> `BaseColorTexture` / `Texture2D` +- `set 4 binding 0` -> `LinearClampSampler` / `Sampler` -- 当前是非常基础的 forward path,不包含光照、阴影、法线贴图、后处理或多 pass。 -- 只画当前提取结果中的 mesh;没有 skybox、UI、粒子或透明物体排序。 -- 纹理查找采用名字启发式,当前会依次尝试 `baseColorTexture`、`_BaseColorTexture`、`_MainTex` 等键名。 -- 当前 input layout 把位置声明成 `R32G32B32A32_Float`,而 `StaticMeshVertex::position` 是 `Vector3`;现有集成测试能跑通,但这说明顶点布局约定仍需要更严格校准。 -- 当前 pipeline resource 生命周期完全由这条管线对象自己管理,还没有被更高层渲染框架统一接管。 +当前可识别的 forward 语义只有四个: + +- `PerObject`:必需,且必须是唯一的 constant buffer。 +- `Material`:可选,且必须是唯一的 constant buffer。 +- `BaseColorTexture`:可选,且必须是唯一的 `Texture2D` 或 `TextureCube`。 +- `LinearClampSampler`:可选,且必须是唯一的 sampler。 + +布局构建阶段遇到以下情况会直接记录错误并拒绝创建该 pass layout: + +- 未知语义。 +- 非法 set index。 +- 在同一个 set 中混用 sampler 与非 sampler 绑定。 +- 在同一个 set 中出现重复 binding。 +- 缺少 `PerObject`。 + +如果第一个实际绑定的 set 大于 `0`,并且 `set 0` 为空,实现还会补一个兼容用的 `set 0`,避免某些布局路径要求从 `set 0` 开始。 + +## 当前渲染流程 + +1. [Initialize](Initialize.md) 通过 `m_passSequence.Initialize(context)` 进入 pass 生命周期。 +2. [Render](Render.md) 把 `RenderContext`、`RenderSurface` 和 `RenderSceneData` 打包成 `RenderPassContext`,再交给 `m_passSequence.Execute(...)`。 +3. `BuiltinForwardOpaquePass` 内部调用 `ExecuteForwardOpaquePass()`,处理 render target 绑定、viewport/scissor、颜色与深度清理,以及前后自动状态切换。 +4. 渲染阶段遍历 `RenderSceneData::visibleItems`,筛出 `BuiltinMaterialPass::ForwardLit` 物体。 +5. 每个物体都会按当前材质解析 shader/pass,获取或创建 pass layout、pipeline state、动态或静态 descriptor set,然后写入常量并发出 draw call。 + +## 当前实现细节 + +- [BuildInputLayout](BuildInputLayout.md) 现在明确使用 `POSITION=float3`、`NORMAL=float3`、`TEXCOORD=float2`,与 `StaticMeshVertex` 对齐。 +- 材质贴图解析通过 `ResolveBuiltinBaseColorTexture(material)` 进入 builtin base-color 语义,不再依赖旧文档里的“按若干名字猜测纹理”说法。 +- 逐物体常量来自 `PerObjectConstants`;逐材质常量目前只写入 `baseColorFactor`。 +- 采样器和 1x1 白色 fallback 纹理在初始化后长期复用;具体 `Texture` 和 `Mesh` 的 GPU 资源则由 [RenderResourceCache](../../RenderResourceCache/RenderResourceCache.md) 按需上传。 + +## 当前限制 + +- 目前只注册了 `BuiltinForwardOpaquePass`,没有透明排序、阴影、延迟渲染或后处理主路径。 +- 资源语义是白名单模型,超出 `PerObject / Material / BaseColorTexture / LinearClampSampler` 的声明不会被接受。 +- `Render()` 层面不会因为单个物体 `DrawVisibleItem()` 失败而整体返回 `false`;当前调用点仍然以“尽量继续绘制其余物体”为主。 ## 公开方法 | 方法 | 说明 | |------|------| -| [Destructor](Destructor.md) | 析构时关闭管线资源。 | -| [Initialize](Initialize.md) | 初始化这条内建前向管线。 | -| [Shutdown](Shutdown.md) | 释放内部创建的所有 RHI 资源。 | -| [Render](Render.md) | 把 `RenderSceneData` 绘制到目标表面。 | - -## 设计说明 - -即便当前实现很轻量,把默认管线拆成独立类仍然是对的: - -- `SceneRenderer` 不必硬编码具体 draw 逻辑。 -- 未来想加 deferred、shadow pass 或 editor preview pipeline 时,接口上有扩展空间。 - -这和商业引擎里保留 builtin pipeline 作为“默认可用实现”的思路是一致的。 +| [Constructor](Constructor.md) | 创建管线对象,并注册默认的 opaque pass。 | +| [Destructor](Destructor.md) | 析构时调用 `Shutdown()`。 | +| [BuildInputLayout](BuildInputLayout.md) | 返回 builtin forward 使用的静态网格输入布局。 | +| [Initialize](Initialize.md) | 初始化 pass sequence,并在需要时准备共享 GPU 资源。 | +| [Shutdown](Shutdown.md) | 关闭 pass sequence,释放 pass layout、descriptor set、pipeline state 与 fallback 资源。 | +| [Render](Render.md) | 把 `RenderSceneData` 绘制到目标 `RenderSurface`。 | ## 相关文档 - [Pipelines](../Pipelines.md) +- [BuiltinForwardPipelineAsset](../BuiltinForwardPipelineAsset/BuiltinForwardPipelineAsset.md) - [RenderPipeline](../../RenderPipeline/RenderPipeline.md) -- [RenderResourceCache](../../RenderResourceCache/RenderResourceCache.md) +- [RenderPipelineAsset](../../RenderPipelineAsset/RenderPipelineAsset.md) +- [CameraRenderer](../../CameraRenderer/CameraRenderer.md) +- [RenderPass](../../RenderPass/RenderPass.md) - [Scene Extraction And Builtin Forward Pipeline](../../../../_guides/Rendering/Scene-Extraction-And-Builtin-Forward-Pipeline.md) diff --git a/docs/api/XCEngine/Rendering/Pipelines/BuiltinForwardPipeline/Constructor.md b/docs/api/XCEngine/Rendering/Pipelines/BuiltinForwardPipeline/Constructor.md new file mode 100644 index 00000000..2c11cd26 --- /dev/null +++ b/docs/api/XCEngine/Rendering/Pipelines/BuiltinForwardPipeline/Constructor.md @@ -0,0 +1,42 @@ +# BuiltinForwardPipeline::BuiltinForwardPipeline + +**命名空间**: `XCEngine::Rendering::Pipelines` + +**类型**: `method` + +**头文件**: `XCEngine/Rendering/Pipelines/BuiltinForwardPipeline.h` + +创建一条新的内建前向渲染管线对象。 + +```cpp +BuiltinForwardPipeline(); +``` + +## 当前实现行为 + +构造函数当前只做一件事: + +- 向内部 `m_passSequence` 注册一个 `Detail::BuiltinForwardOpaquePass` + +它不会在构造时立刻创建任何设备相关资源。下面这些对象都留到 [Initialize](Initialize.md) 或首次 [Render](Render.md) 时再按需创建: + +- builtin `ForwardLit` shader 句柄 +- 线性 clamp sampler +- fallback 白色纹理和 SRV +- `PassResourceLayout` +- `RHIPipelineState` +- 静态 / 动态 descriptor set + +## 设计说明 + +把“对象构造”和“设备资源初始化”拆开,是渲染系统里很常见也很合理的设计: + +- 构造函数不依赖 `RenderContext` +- 上层可以先把 pipeline 对象组装进 `CameraRenderer` +- 真正拿到设备和命令列表后,再决定是否初始化、重建或销毁资源 + +## 相关文档 + +- [BuiltinForwardPipeline](BuiltinForwardPipeline.md) +- [Initialize](Initialize.md) +- [Render](Render.md) diff --git a/docs/api/XCEngine/Rendering/Pipelines/BuiltinForwardPipeline/Destructor.md b/docs/api/XCEngine/Rendering/Pipelines/BuiltinForwardPipeline/Destructor.md index 0b8f5d93..34f6fee5 100644 --- a/docs/api/XCEngine/Rendering/Pipelines/BuiltinForwardPipeline/Destructor.md +++ b/docs/api/XCEngine/Rendering/Pipelines/BuiltinForwardPipeline/Destructor.md @@ -1,16 +1,14 @@ # BuiltinForwardPipeline::~BuiltinForwardPipeline -销毁内建前向管线对象。 - ```cpp ~BuiltinForwardPipeline() override; ``` ## 行为说明 -当前析构函数会调用 [Shutdown](Shutdown.md)。 +析构函数会直接调用 [Shutdown](Shutdown.md),把内部 pass sequence 和 builtin forward 共享资源完整释放掉。 ## 相关文档 -- [返回类型总览](BuiltinForwardPipeline.md) +- [BuiltinForwardPipeline](BuiltinForwardPipeline.md) - [Shutdown](Shutdown.md) diff --git a/docs/api/XCEngine/Rendering/Pipelines/BuiltinForwardPipeline/Initialize.md b/docs/api/XCEngine/Rendering/Pipelines/BuiltinForwardPipeline/Initialize.md index e5753c9f..7e9061b0 100644 --- a/docs/api/XCEngine/Rendering/Pipelines/BuiltinForwardPipeline/Initialize.md +++ b/docs/api/XCEngine/Rendering/Pipelines/BuiltinForwardPipeline/Initialize.md @@ -1,31 +1,37 @@ # BuiltinForwardPipeline::Initialize -初始化内建前向管线。 - ```cpp bool Initialize(const RenderContext& context) override; ``` ## 行为说明 -当前实现直接转发到内部 `EnsureInitialized(context)`。 +当前实现不再直接调用管线自身的 `EnsureInitialized()`,而是把生命周期交给内部的 `m_passSequence`: + +```cpp +return m_passSequence.Initialize(context); +``` + +由于构造函数只注册了一个 `BuiltinForwardOpaquePass`,这里的真实初始化工作会进入该 pass 的 `Initialize()`,再由它调用 `BuiltinForwardPipeline::EnsureInitialized(context)`。 ## 参数 -- `context` - 当前渲染上下文。 +- `context` - 当前渲染上下文,必须提供有效的 device、command list 与 backend。 ## 返回值 -- 初始化成功返回 `true`。 -- 否则返回 `false`。 +- 成功返回 `true`。 +- `context` 无效,或共享 GPU 资源准备失败时返回 `false`。 -## 当前实现说明 +## 当前初始化内容 -- 若当前设备与 backend 和已初始化状态匹配,内部会复用现有资源。 -- 若上下文变化,会先销毁旧资源,再重新创建。 +- 复用同一个 device/backend 时,`EnsureInitialized()` 会直接返回,不重复构建共享资源。 +- device 或 backend 变化时,会先销毁旧资源,再重新创建 builtin forward shader、线性 clamp sampler、1x1 白色 fallback 纹理和对应 SRV。 +- `PassResourceLayout`、`RHIPipelineState` 与动态 descriptor set 不会在这里一次性全部建立,而是在后续真正渲染某个 shader pass / 材质时按需创建。 ## 相关文档 -- [返回类型总览](BuiltinForwardPipeline.md) +- [BuiltinForwardPipeline](BuiltinForwardPipeline.md) - [Render](Render.md) - [Shutdown](Shutdown.md) +- [RenderPass](../../RenderPass/RenderPass.md) diff --git a/docs/api/XCEngine/Rendering/Pipelines/BuiltinForwardPipeline/Render.md b/docs/api/XCEngine/Rendering/Pipelines/BuiltinForwardPipeline/Render.md index 298b21f0..60492c7c 100644 --- a/docs/api/XCEngine/Rendering/Pipelines/BuiltinForwardPipeline/Render.md +++ b/docs/api/XCEngine/Rendering/Pipelines/BuiltinForwardPipeline/Render.md @@ -1,7 +1,5 @@ # BuiltinForwardPipeline::Render -执行一次内建前向渲染。 - ```cpp bool Render( const RenderContext& context, @@ -11,36 +9,58 @@ bool Render( ## 行为说明 -当前实现会: +当前 `Render()` 本身很薄,只做两件事: -1. 确保管线资源已初始化。 -2. 检查颜色附件是否存在。 -3. 在需要时把颜色附件从 `stateBefore` 转成 `RenderTarget`。 -4. 绑定 render target、viewport 和 scissor。 -5. 清颜色和深度。 -6. 设置 pipeline state 与 primitive topology。 -7. 遍历 `sceneData.visibleObjects`,逐个发出 draw call。 -8. 在需要时把颜色附件从 `RenderTarget` 转回 `stateAfter`。 +1. 调用 `Initialize(context)`,确保 pass sequence 与共享资源已经可用。 +2. 组装 `RenderPassContext { context, surface, sceneData }`,再执行 `m_passSequence.Execute(passContext)`。 + +由于当前 sequence 里只包含 `BuiltinForwardOpaquePass`,真正的绘制逻辑发生在 `ExecuteForwardOpaquePass()` 中。 + +## 当前 opaque pass 流程 + +1. 校验 `surface.GetColorAttachments()` 非空。 +2. 如启用了自动状态切换,把颜色附件从 `surface.GetColorStateBefore()` 转成 `RenderTarget`。 +3. 绑定 render target、depth attachment、viewport 与 scissor。 +4. 按 `RenderSurface` 的 clear-color override 和 `sceneData.cameraData.clearFlags` 决定是否清颜色/深度。 +5. 设置 `TriangleList` 拓扑。 +6. 遍历 `RenderSceneData::visibleItems`,只处理匹配 `BuiltinMaterialPass::ForwardLit` 的可见项。 +7. 对每个物体复用或创建匹配的 pipeline state,并调用内部 `DrawVisibleItem(...)`。 +8. 结束时如启用了自动状态切换,再把颜色附件从 `RenderTarget` 切回 `surface.GetColorStateAfter()`。 + +## `DrawVisibleItem()` 当前行为 + +单个可见项的绘制链路为: + +1. 通过 `RenderResourceCache` 取得 mesh 的 GPU 缓存。 +2. 写入 `PerObjectConstants`,其中包含投影矩阵、视图矩阵、`localToWorld`、逆矩阵和主方向光数据。 +3. 基于材质解析实际要使用的 shader/pass。 +4. 获取或创建该 `(shader*, passName)` 对应的 `PassResourceLayout`。 +5. 解析 base-color 纹理视图与逐材质常量。 +6. 逐 set 绑定 descriptor: + - 含 `PerObject / Material / Texture` 的 set 走动态 descriptor set 缓存。 + - 只含 sampler 的 set 走静态 descriptor set 缓存。 +7. 调用 `SetGraphicsDescriptorSets(...)`,并按 section 或整 mesh 发出 `DrawIndexed` / `Draw`。 ## 参数 - `context` - 当前渲染上下文。 -- `surface` - 当前目标表面。 -- `sceneData` - 提取好的相机和可见对象数据。 +- `surface` - 当前输出目标。 +- `sceneData` - `RenderSceneExtractor` 产出的相机、光照与 `visibleItems` 数据。 ## 返回值 -- 成功返回 `true`。 -- 初始化失败或没有颜色附件时返回 `false`。 +- 整个 pass sequence 成功执行时返回 `true`。 +- 初始化失败、缺少颜色附件、render area 非法,或 pass sequence 中某个 pass 明确失败时返回 `false`。 -## 当前实现限制 +## 当前限制 -- 当前不会因为某个单独物体绘制失败而整体返回 `false`;内部 `DrawVisibleObject()` 的失败结果并没有汇总成整帧失败。 -- 当前没有多 pass 结构。 -- 当前默认总会清颜色;没有“只加载不清除”的 load/store 策略配置。 +- 当前 sequence 只有一个 opaque pass,还没有透明排序、shadow pass 或 deferred path。 +- 调用点目前不会把单个 `DrawVisibleItem()` 的失败汇总成整体失败;它更偏向“跳过当前物体,继续绘制其余物体”。 +- `Render()` 只处理一个 `RenderSurface` 和一份 `RenderSceneData`,不是 render graph。 ## 相关文档 -- [返回类型总览](BuiltinForwardPipeline.md) +- [BuiltinForwardPipeline](BuiltinForwardPipeline.md) - [RenderSurface](../../RenderSurface/RenderSurface.md) -- [VisibleRenderObject](../../VisibleRenderObject/VisibleRenderObject.md) +- [RenderPass](../../RenderPass/RenderPass.md) +- [Scene Extraction And Builtin Forward Pipeline](../../../../_guides/Rendering/Scene-Extraction-And-Builtin-Forward-Pipeline.md) diff --git a/docs/api/XCEngine/Rendering/Pipelines/BuiltinForwardPipeline/Shutdown.md b/docs/api/XCEngine/Rendering/Pipelines/BuiltinForwardPipeline/Shutdown.md index 13280b4d..7402307a 100644 --- a/docs/api/XCEngine/Rendering/Pipelines/BuiltinForwardPipeline/Shutdown.md +++ b/docs/api/XCEngine/Rendering/Pipelines/BuiltinForwardPipeline/Shutdown.md @@ -1,23 +1,38 @@ # BuiltinForwardPipeline::Shutdown -关闭内建前向管线并释放其资源。 - ```cpp void Shutdown() override; ``` ## 行为说明 -当前实现直接调用内部 `DestroyPipelineResources()`,释放: +当前 `Shutdown()` 已经统一走 pass sequence: -- resource cache -- fallback texture / view -- sampler -- pipeline state -- pipeline layout -- descriptor set / descriptor pool +```cpp +m_passSequence.Shutdown(); +``` + +真正的资源释放发生在 `BuiltinForwardOpaquePass::Shutdown()` 中。该 pass 会回调 `BuiltinForwardPipeline::DestroyPipelineResources()`,把 builtin forward 相关的共享缓存全部清掉。 + +## 当前释放内容 + +- `RenderResourceCache` +- `m_pipelineStates` +- `m_dynamicDescriptorSets` +- `m_passResourceLayouts` +- fallback 纹理与 SRV +- 线性 clamp sampler + +这里释放的是“按 pass layout 分组的 pipeline layout / descriptor set / descriptor pool”,而不是旧文档里描述的单一全局 pipeline layout。 + +## 当前语义 + +- 多次调用是安全的;资源被清空后成员会回到空状态。 +- 下次 `Render()` 或 `Initialize()` 再次进入时,会按当前 device/backend 重新建立共享资源。 ## 相关文档 -- [返回类型总览](BuiltinForwardPipeline.md) +- [BuiltinForwardPipeline](BuiltinForwardPipeline.md) +- [Destructor](Destructor.md) - [RenderResourceCache](../../RenderResourceCache/RenderResourceCache.md) +- [RenderPass](../../RenderPass/RenderPass.md) diff --git a/docs/api/XCEngine/Rendering/Pipelines/BuiltinForwardPipelineAsset/BuiltinForwardPipelineAsset.md b/docs/api/XCEngine/Rendering/Pipelines/BuiltinForwardPipelineAsset/BuiltinForwardPipelineAsset.md new file mode 100644 index 00000000..07bbf77d --- /dev/null +++ b/docs/api/XCEngine/Rendering/Pipelines/BuiltinForwardPipelineAsset/BuiltinForwardPipelineAsset.md @@ -0,0 +1,49 @@ +# BuiltinForwardPipelineAsset + +**命名空间**: `XCEngine::Rendering::Pipelines` + +**类型**: `class final` + +**头文件**: `XCEngine/Rendering/Pipelines/BuiltinForwardPipeline.h` + +**描述**: 当前默认的具体 `RenderPipelineAsset`,负责生成新的 [BuiltinForwardPipeline](../BuiltinForwardPipeline/BuiltinForwardPipeline.md) 实例。 + +## 概览 + +`BuiltinForwardPipelineAsset` 是当前渲染模块里唯一公开的 concrete pipeline asset。它的职责很简单: + +- 作为默认主管线工厂存在 +- 在需要时返回一条新的 `BuiltinForwardPipeline` + +按 `engine/src/Rendering/CameraRenderer.cpp` 的当前接线: + +- `CameraRenderer` 的默认构造路径会使用静态共享的 `BuiltinForwardPipelineAsset` +- `SetPipelineAsset()` 也会通过这类 asset 重建当前主管线实例 +- 如果外部传入空 asset,当前仍会回退到默认 `BuiltinForwardPipelineAsset` + +## 生命周期与所有权 + +- asset 自身通常以 `std::shared_ptr` 共享持有 +- 它创建出来的 pipeline 以 `std::unique_ptr` 返回 +- runtime pipeline 的生命周期最终由 `CameraRenderer` 或调用方接管,而不是由 asset 自己保留 + +这就是“共享工厂对象 + 独占运行时实例”的典型渲染系统分层。 + +## 当前实现边界 + +- 当前没有任何可配置字段 +- 不能通过它选择不同 shader、不同 pass 序列或不同渲染路径 +- 它还不是项目资源数据库里的可序列化 renderer asset,只是 C++ 工厂对象 + +## 公开方法 + +| 方法 | 说明 | +|------|------| +| [CreatePipeline](CreatePipeline.md) | 创建一条新的 `BuiltinForwardPipeline` 实例。 | + +## 相关文档 + +- [BuiltinForwardPipeline](../BuiltinForwardPipeline/BuiltinForwardPipeline.md) +- [Pipelines](../Pipelines.md) +- [RenderPipelineAsset](../../RenderPipelineAsset/RenderPipelineAsset.md) +- [CameraRenderer](../../CameraRenderer/CameraRenderer.md) diff --git a/docs/api/XCEngine/Rendering/Pipelines/BuiltinForwardPipelineAsset/CreatePipeline.md b/docs/api/XCEngine/Rendering/Pipelines/BuiltinForwardPipelineAsset/CreatePipeline.md new file mode 100644 index 00000000..0f2b0e9b --- /dev/null +++ b/docs/api/XCEngine/Rendering/Pipelines/BuiltinForwardPipelineAsset/CreatePipeline.md @@ -0,0 +1,47 @@ +# BuiltinForwardPipelineAsset::CreatePipeline + +**命名空间**: `XCEngine::Rendering::Pipelines` + +**类型**: `method` + +**头文件**: `XCEngine/Rendering/Pipelines/BuiltinForwardPipeline.h` + +创建一条新的 builtin forward runtime pipeline。 + +```cpp +std::unique_ptr CreatePipeline() const override; +``` + +## 当前实现行为 + +当前实现直接返回: + +```cpp +std::make_unique() +``` + +这意味着: + +- 每次调用都会生成一条新的 `BuiltinForwardPipeline` +- 当前不会复用已有 runtime pipeline +- 当前也不会返回 `nullptr` + +## 当前调用位置 + +`CameraRenderer` 通过内部 `CreatePipelineFromAsset()` 使用这个方法: + +1. 若当前有 `pipelineAsset`,先执行 `asset->CreatePipeline()` +2. 若拿到有效实例,就接管这条新管线 +3. 若 asset 为空或返回空指针,再回退到直接 `std::make_unique()` + +对 `BuiltinForwardPipelineAsset` 来说,第 3 步当前基本不会触发。 + +## 返回值 + +- `std::unique_ptr` - 指向一条全新的 `BuiltinForwardPipeline` + +## 相关文档 + +- [BuiltinForwardPipelineAsset](BuiltinForwardPipelineAsset.md) +- [BuiltinForwardPipeline](../BuiltinForwardPipeline/BuiltinForwardPipeline.md) +- [RenderPipelineAsset::CreatePipeline](../../RenderPipelineAsset/CreatePipeline.md) diff --git a/docs/api/XCEngine/Rendering/Pipelines/Pipelines.md b/docs/api/XCEngine/Rendering/Pipelines/Pipelines.md index 8f8664e7..afb16132 100644 --- a/docs/api/XCEngine/Rendering/Pipelines/Pipelines.md +++ b/docs/api/XCEngine/Rendering/Pipelines/Pipelines.md @@ -4,27 +4,54 @@ **类型**: `submodule` -**描述**: 承载具体渲染管线实现,当前公开的是内建前向渲染管线。 +**描述**: 提供当前公开的具体渲染管线实现,以及与之配套的 pipeline asset 工厂。 -## 概述 +## 概览 -把具体渲染实现放在 `Rendering::Pipelines` 子命名空间,而不是直接塞进 `SceneRenderer`,是很合理的架构选择: +`Rendering::Pipelines` 子命名空间承载的不是“渲染总流程”,而是“真正把场景数据画到目标表面的 runtime pipeline 实现”。 -- `SceneRenderer` 只负责组织渲染流程。 -- 具体怎么画,由管线对象决定。 +当前这层已经明确分成两类对象: -这和商业引擎里“renderer 负责 orchestration,pipeline 负责 actual rendering”的分层是相通的。 +- runtime pipeline + 负责解析 shader pass、构建 pipeline layout、缓存 descriptor set,并发出 draw call。 +- pipeline asset + 负责决定该创建哪一条 runtime pipeline,并把实例交给 `CameraRenderer`。 -## 当前实现 +这和商业引擎里常见的 `RenderPipelineAsset -> RenderPipeline` 分层是一致的。当前功能还不算多,但架构边界已经建立起来了。 -当前公开的具体管线只有一个: +## 当前公开类型 - [BuiltinForwardPipeline](BuiltinForwardPipeline/BuiltinForwardPipeline.md) + - `BuiltinForwardPipeline.h` + - 当前默认的主场景前向管线实现。 +- [BuiltinForwardPipelineAsset](BuiltinForwardPipelineAsset/BuiltinForwardPipelineAsset.md) + - `BuiltinForwardPipeline.h` + - 当前默认的 concrete `RenderPipelineAsset`,负责创建新的 `BuiltinForwardPipeline`。 -它承担的角色更像“默认可跑通的内建前向管线”,而不是覆盖完整 PBR、光照、阴影和后处理的成熟渲染框架。 +## 默认接线关系 + +当前默认路径是: + +1. `CameraRenderer` 拿到 `BuiltinForwardPipelineAsset` +2. asset 创建 `BuiltinForwardPipeline` +3. runtime pipeline 执行主场景绘制 + +这样做的价值在于: + +- `CameraRenderer` 不需要知道 builtin forward 的内部细节 +- future custom pipeline 的扩展位已经存在 +- pipeline 工厂和 pipeline 实例的生命周期可以分开管理 + +## 当前边界 + +- 目前公开的 concrete runtime pipeline 仍然只有 builtin forward 一条 +- `BuiltinForwardPipelineAsset` 还只是 C++ 工厂对象,不是项目资源数据库里的 renderer asset +- deferred、多主管线配置、render graph 和复杂 frame orchestration 还没有在这一层落地 ## 相关文档 -- [当前模块](../Rendering.md) +- [Rendering](../Rendering.md) - [RenderPipeline](../RenderPipeline/RenderPipeline.md) - [RenderPipelineAsset](../RenderPipelineAsset/RenderPipelineAsset.md) +- [CameraRenderer](../CameraRenderer/CameraRenderer.md) +- [Scene Extraction And Builtin Forward Pipeline](../../../_guides/Rendering/Scene-Extraction-And-Builtin-Forward-Pipeline.md) diff --git a/docs/api/XCEngine/Rendering/RenderPipelineAsset/CreatePipeline.md b/docs/api/XCEngine/Rendering/RenderPipelineAsset/CreatePipeline.md index 20235a5a..6f7994c3 100644 --- a/docs/api/XCEngine/Rendering/RenderPipelineAsset/CreatePipeline.md +++ b/docs/api/XCEngine/Rendering/RenderPipelineAsset/CreatePipeline.md @@ -1,24 +1,59 @@ # RenderPipelineAsset::CreatePipeline -创建一个新的渲染管线实例。 +**命名空间**: `XCEngine::Rendering` + +**类型**: `method` + +**头文件**: `XCEngine/Rendering/RenderPipelineAsset.h` + +由具体 asset 创建一条新的 runtime 渲染管线实例。 ```cpp virtual std::unique_ptr CreatePipeline() const = 0; ``` -## 行为说明 +## 接口契约 -派生类应根据自身配置返回一个具体 `RenderPipeline` 实例。 +从接口形状上,调用方可以依赖这几点: + +- 返回值拥有独占所有权 +- 返回对象是 `RenderPipeline` 派生实例 +- 这是一个 `const` 工厂方法,asset 自己不需要暴露可变运行时状态 + +## 当前调用链 + +当前最主要的消费方是 `CameraRenderer` 内部的 `CreatePipelineFromAsset()`: + +1. 若存在 `pipelineAsset`,先调用 `asset->CreatePipeline()` +2. 若拿到有效实例,就把它作为当前主管线 +3. 若 asset 为空或返回空指针,再回退到 `BuiltinForwardPipeline` + +因此派生类最好遵守一个明确的工程约定: + +- 返回一条新的、可独立 `Shutdown()` / `Render()` 的 runtime pipeline +- 不要把某条活动中的共享 pipeline 实例直接借给调用方 ## 返回值 -- 一个拥有独占所有权的 `RenderPipeline` 对象。 +- `std::unique_ptr` - 新创建的运行时管线;允许派生类返回 `nullptr`,但当前默认调用方会把这视为失败并继续走 fallback + +## 当前公开实现示例 + +- [BuiltinForwardPipelineAsset::CreatePipeline](../Pipelines/BuiltinForwardPipelineAsset/CreatePipeline.md) ## 设计说明 -把返回值设计成 `std::unique_ptr` 是合理的,因为渲染管线往往具有明确的独占生命周期,不适合共享所有权。 +这里使用 `std::unique_ptr` 很关键,因为 runtime pipeline 往往持有: + +- 设备指针 +- pipeline state +- descriptor set +- 缓存和临时 GPU 资源 + +这类对象通常应当具备清晰的唯一生命周期,而不是被多处共享。 ## 相关文档 -- [返回类型总览](RenderPipelineAsset.md) +- [RenderPipelineAsset](RenderPipelineAsset.md) - [RenderPipeline](../RenderPipeline/RenderPipeline.md) +- [BuiltinForwardPipelineAsset](../Pipelines/BuiltinForwardPipelineAsset/BuiltinForwardPipelineAsset.md) diff --git a/docs/api/XCEngine/Rendering/RenderPipelineAsset/RenderPipelineAsset.md b/docs/api/XCEngine/Rendering/RenderPipelineAsset/RenderPipelineAsset.md index 372acbbc..24c7d9fa 100644 --- a/docs/api/XCEngine/Rendering/RenderPipelineAsset/RenderPipelineAsset.md +++ b/docs/api/XCEngine/Rendering/RenderPipelineAsset/RenderPipelineAsset.md @@ -6,34 +6,70 @@ **头文件**: `XCEngine/Rendering/RenderPipelineAsset.h` -**描述**: 定义渲染管线工厂接口,用于创建具体 `RenderPipeline` 实例。 +**描述**: 渲染管线工厂接口,用于按需创建新的 runtime [RenderPipeline](../RenderPipeline/RenderPipeline.md) 实例。 -## 概述 +## 概览 -`RenderPipelineAsset` 体现的是“数据/配置对象负责生成运行时管线实例”的设计方向。 +`RenderPipelineAsset` 的职责不是自己渲染,而是回答一个更高层的问题: -这和商业引擎里常见的 pipeline asset / renderer asset 思路很接近: +- 当前这台 `CameraRenderer` 应该创建哪一种主管线实例? -- asset 负责描述“要创建哪条渲染管线” -- runtime pipeline 负责真正执行渲染 +这和商业引擎里常见的 `RenderPipelineAsset -> RenderPipeline` 分层很接近。好处是: + +- 上层编排器只依赖抽象接口,不直接硬编码具体管线类型 +- runtime pipeline 可以被重建、替换或按不同入口注入 +- 工厂对象和运行时实例可以采用不同所有权模型 + +## 当前真实接线 + +当前最直接的消费方是 [CameraRenderer](../CameraRenderer/CameraRenderer.md): + +- 默认构造时会拿到一份默认 pipeline asset +- [SetPipelineAsset](../CameraRenderer/SetPipelineAsset.md) 会通过 asset 重建主管线 +- `GetPipelineAsset()` 返回的是当前工厂对象,而不是 runtime pipeline + +按当前源码,默认 concrete asset 是 [Pipelines::BuiltinForwardPipelineAsset](../Pipelines/BuiltinForwardPipelineAsset/BuiltinForwardPipelineAsset.md)。 + +## 当前公开实现 + +当前公开的 concrete 实现有: + +- [BuiltinForwardPipelineAsset](../Pipelines/BuiltinForwardPipelineAsset/BuiltinForwardPipelineAsset.md) + +它会创建 [BuiltinForwardPipeline](../Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md)。 + +## 生命周期与所有权 + +- `RenderPipelineAsset` 通常以 `std::shared_ptr` 共享持有 +- [CreatePipeline](CreatePipeline.md) 返回新的 `std::unique_ptr` +- asset 不保留运行时实例;实例生命周期由 `CameraRenderer` 或调用方接管 + +这种“共享工厂 + 独占运行体”的组合很适合渲染系统,因为 runtime pipeline 往往持有设备、pipeline state 和 descriptor set,不适合被多方共享所有权。 ## 当前实现边界 -- 当前它只是抽象接口。 -- 当前公开 API 里没有看到对应的具体 asset 派生类型。 -- `SceneRenderer` 目前也没有直接接入这个抽象,而是默认直接创建 [BuiltinForwardPipeline](../Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md)。 - -这说明接口方向已经铺好,但 asset-driven pipeline 切换还没有完全接上。 +- 当前它仍然只是纯 C++ 工厂接口,不是项目资源数据库里的可序列化资产类型 +- 还没有 renderer asset inspector、热重载或多 profile 配置 +- 当前 fallback 策略很保守,目标是“即使 asset 路径出问题,也尽量总有 builtin pipeline 可跑” ## 公开方法 | 方法 | 说明 | |------|------| -| [Destructor](Destructor.md) | 虚析构函数。 | -| [CreatePipeline](CreatePipeline.md) | 创建一个具体渲染管线实例。 | +| [Destructor](Destructor.md) | 虚析构函数,保证经由基类销毁派生 asset 时行为正确。 | +| [CreatePipeline](CreatePipeline.md) | 创建一条新的 runtime 管线实例。 | + +## 设计说明 + +这一层的重要性,不在于“多包一层接口”,而在于把“选择哪种主管线”和“真正执行绘制”分开: + +- `CameraRenderer` 不需要知道 builtin forward 的内部细节 +- 不同 asset 后续可以创建完全不同的 runtime pipeline 类型 +- 如果未来要把主管线选择接入项目设置或 viewport 模式,不必重写 camera submission 主流程 ## 相关文档 -- [当前模块](../Rendering.md) +- [Rendering](../Rendering.md) - [RenderPipeline](../RenderPipeline/RenderPipeline.md) -- [SceneRenderer](../SceneRenderer/SceneRenderer.md) +- [BuiltinForwardPipelineAsset](../Pipelines/BuiltinForwardPipelineAsset/BuiltinForwardPipelineAsset.md) +- [Scene Extraction And Builtin Forward Pipeline](../../../_guides/Rendering/Scene-Extraction-And-Builtin-Forward-Pipeline.md) diff --git a/docs/api/XCEngine/Rendering/Rendering.md b/docs/api/XCEngine/Rendering/Rendering.md index 4cecee87..782a3551 100644 --- a/docs/api/XCEngine/Rendering/Rendering.md +++ b/docs/api/XCEngine/Rendering/Rendering.md @@ -14,12 +14,15 @@ 2. [CameraRenderRequest](CameraRenderRequest/CameraRenderRequest.md) 把单次提交的主表面、object-id 输出和 builtin 后处理需求打包起来。 3. [CameraRenderer](CameraRenderer/CameraRenderer.md) 执行单个请求。 4. [RenderSceneExtractor](RenderSceneExtractor/RenderSceneExtractor.md) 依据相机和 render area 提取 `RenderSceneData`。 -5. [RenderPipeline](RenderPipeline/RenderPipeline.md) 负责主场景绘制。 -6. `ObjectIdPass` 与 [Passes](Passes/Passes.md) 子模块在主场景之后补上 object-id、grid 和 selection outline 等额外结果。 -7. [RenderMaterialUtility](RenderMaterialUtility/RenderMaterialUtility.md) 把材质元数据与 render state 翻译成这条链路能消费的规则。 +5. [RenderPipelineAsset](RenderPipelineAsset/RenderPipelineAsset.md) 决定创建哪条 runtime 主场景管线;默认实现是 [Pipelines::BuiltinForwardPipelineAsset](Pipelines/BuiltinForwardPipelineAsset/BuiltinForwardPipelineAsset.md)。 +6. [RenderPipeline](RenderPipeline/RenderPipeline.md) 负责主场景绘制;当前默认 runtime 实现是 [Pipelines::BuiltinForwardPipeline](Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md)。 +7. `ObjectIdPass` 与 [Passes](Passes/Passes.md) 子模块在主场景之后补上 object-id、grid 和 selection outline 等额外结果。 +8. [RenderMaterialUtility](RenderMaterialUtility/RenderMaterialUtility.md) 把材质元数据与 render state 翻译成这条链路能消费的规则。 这意味着当前渲染模块已经不只是“scene -> pipeline”两段式结构,而是包含了主场景、辅助缓冲和 builtin post-process 的完整相机提交流程。 +更底层的基础协议则由 [SceneRenderRequestPlanner](SceneRenderRequestPlanner/SceneRenderRequestPlanner.md)、[SceneRenderRequestUtils](SceneRenderRequestUtils/SceneRenderRequestUtils.md)、[RenderSceneUtility](RenderSceneUtility/RenderSceneUtility.md)、[RenderPass](RenderPass/RenderPass.md)、[ObjectIdPass](ObjectIdPass/ObjectIdPass.md) 和 [ObjectIdEncoding](ObjectIdEncoding/ObjectIdEncoding.md) 补齐。它们分别负责请求规划、排序规则、场景提取 helper、通用 pass 生命周期以及 object-id 编解码约定。 + ## 当前主流程 对一台相机,当前主流程大致是: @@ -27,9 +30,10 @@ 1. `SceneRenderer` 生成并排序 `CameraRenderRequest` 2. `CameraRenderer` 校验请求 3. `RenderSceneExtractor` 提取可见物体与相机数据 -4. 主 `RenderPipeline` 绘制主颜色目标 -5. 如有需要,执行 object-id pass,生成辅助 object-id 纹理 -6. 执行调用方注入的 post pass、builtin post-process 和 overlay pass +4. 通过 `RenderPipelineAsset` 创建或替换主管线实例 +5. 主 `RenderPipeline` 绘制主颜色目标 +6. 如有需要,执行 object-id pass,生成辅助 object-id 纹理 +7. 执行调用方注入的 post pass、builtin post-process 和 overlay pass scene viewport 的无限网格和选中轮廓,就是通过这条 object-id + builtin post-process 链路接入的。 @@ -48,9 +52,12 @@ scene viewport 的无限网格和选中轮廓,就是通过这条 object-id + b - 不透明 / 透明排序语义 - 剔除、混合和深度状态如何写进图形管线描述 +在当前默认 builtin forward 路径里,shader pass 的 `resources` 声明还会进一步参与 `PassResourceLayout` 构建,因为 `BuiltinForwardPipeline` 已经开始按资源契约生成 descriptor set layout。 + ## 当前实现边界 - 当前默认路径仍然是内建前向渲染,而不是完整 SRP / render graph。 +- `RenderPipelineAsset` 已经接入默认主链路,但当前还不是项目资源系统里的完整 renderer asset。 - object-id 和 builtin post-process 主要服务于编辑器视口与调试链路。 - builtin selection outline 当前依赖单独的 object-id SRV,而不是从主颜色结果反推。 - 多相机排序由 `SceneRenderer` 处理,`CameraRenderer` 本身只执行单请求。 @@ -59,15 +66,21 @@ scene viewport 的无限网格和选中轮廓,就是通过这条 object-id + b - [CameraRenderRequest](CameraRenderRequest/CameraRenderRequest.md) - `CameraRenderRequest.h` - [CameraRenderer](CameraRenderer/CameraRenderer.md) - `CameraRenderer.h` +- [ObjectIdEncoding](ObjectIdEncoding/ObjectIdEncoding.md) - `ObjectIdEncoding.h` +- [ObjectIdPass](ObjectIdPass/ObjectIdPass.md) - `ObjectIdPass.h` - [Passes](Passes/Passes.md) - `Passes/` - [RenderCameraData](RenderCameraData/RenderCameraData.md) - `RenderCameraData.h` - [RenderContext](RenderContext/RenderContext.md) - `RenderContext.h` - [RenderMaterialUtility](RenderMaterialUtility/RenderMaterialUtility.md) - `RenderMaterialUtility.h` +- [RenderPass](RenderPass/RenderPass.md) - `RenderPass.h` - [RenderPipeline](RenderPipeline/RenderPipeline.md) - `RenderPipeline.h` - [RenderPipelineAsset](RenderPipelineAsset/RenderPipelineAsset.md) - `RenderPipelineAsset.h` - [RenderResourceCache](RenderResourceCache/RenderResourceCache.md) - `RenderResourceCache.h` - [RenderSceneExtractor](RenderSceneExtractor/RenderSceneExtractor.md) - `RenderSceneExtractor.h` +- [RenderSceneUtility](RenderSceneUtility/RenderSceneUtility.md) - `RenderSceneUtility.h` - [RenderSurface](RenderSurface/RenderSurface.md) - `RenderSurface.h` +- [SceneRenderRequestPlanner](SceneRenderRequestPlanner/SceneRenderRequestPlanner.md) - `SceneRenderRequestPlanner.h` +- [SceneRenderRequestUtils](SceneRenderRequestUtils/SceneRenderRequestUtils.md) - `SceneRenderRequestUtils.h` - [SceneRenderer](SceneRenderer/SceneRenderer.md) - `SceneRenderer.h` - [VisibleRenderObject](VisibleRenderObject/VisibleRenderObject.md) - `VisibleRenderObject.h` - [Pipelines](Pipelines/Pipelines.md) - `Pipelines/`