docs: sync rendering request, surface, and binding docs

This commit is contained in:
2026-04-04 17:35:23 +08:00
parent a833a95216
commit 6e58016009
93 changed files with 2185 additions and 342 deletions

View File

@@ -6,13 +6,14 @@
**头文件**: `XCEngine/Rendering/CameraRenderRequest.h`
**描述**: 把一次单相机提交所需的场景、目标表面、object-id 输出、清屏覆盖和可选 pass 序列打包成显式请求对象。
**描述**: 把一次单相机提交所需的场景、目标表面、shadow-caster / depth-only / object-id 子请求、清屏覆盖和可选 pass 序列打包成显式请求对象。
## 概览
`CameraRenderRequest` 是 [SceneRenderer](../SceneRenderer/SceneRenderer.md) 和 [CameraRenderer](../CameraRenderer/CameraRenderer.md) 之间的主要数据契约。它本身不执行渲染,只负责描述“这一台相机这次要怎么提交”:
- 主场景渲染所需的 `scene``camera``context``surface`
- 可选的 depth-only / shadow-caster scene pass 子请求
- 可选的 object-id 辅助输出 `objectId`
- 多相机排序和清屏覆盖字段
- 主场景前后与最终叠加阶段要执行的可选 pass 序列
@@ -27,6 +28,8 @@ Editor Scene View 的网格和选中轮廓,当前由 editor 侧先组装进 `p
| `camera` | 本次渲染使用的相机组件。 |
| `context` | 当前帧的 RHI 上下文。 |
| `surface` | 主颜色输出目标及其 render area。 |
| `depthOnly` | 可选的 depth-only scene pass 子请求。 |
| `shadowCaster` | 可选的 shadow-caster scene pass 子请求。 |
| `objectId` | 可选的 object-id 辅助输出。 |
| `cameraDepth` | 多相机排序辅助值。 |
| `cameraStackOrder` | `Base` / `Overlay` camera stack 的附加排序键。 |
@@ -36,6 +39,14 @@ Editor Scene View 的网格和选中轮廓,当前由 editor 侧先组装进 `p
| `postScenePasses` | 主场景和 object-id 之后、overlay 之前执行的可选 `RenderPassSequence*`。 |
| `overlayPasses` | 最后叠加到主颜色目标上的可选 `RenderPassSequence*`。 |
## `depthOnly` / `shadowCaster`
`depthOnly``shadowCaster` 当前都是 [ScenePassRenderRequest](ScenePassRenderRequest/ScenePassRenderRequest.md) 的类型别名,用来描述“是否要在主 `RenderPipeline` 之前额外执行一次 scene pass 重绘”。
- [IsRequested](ScenePassRenderRequest/IsRequested.md) 只检查 `surface` 是否真的挂了颜色附件。
- [IsValid](ScenePassRenderRequest/IsValid.md) 进一步要求第一张颜色附件非空、深度附件非空且 render area 宽高都大于 `0`
-`engine/src/Rendering/CameraRenderer.cpp` 的当前实现,`CameraRenderer::Render()` 会先执行 `shadowCaster`,再执行 `depthOnly`,之后才进入主 `RenderPipeline`
## `objectId`
`objectId` 是一个 [ObjectIdRenderRequest](ObjectIdRenderRequest/ObjectIdRenderRequest.md),用于描述“是否要额外输出一张 object-id 辅助表面”。
@@ -67,9 +78,11 @@ Editor Scene View 当前会先通过 [SceneViewportRenderPlan](../../Editor/View
## 当前数据契约
- [IsValid](IsValid.md) 只检查 `scene``camera``context`,不会验证 `surface``objectId` 是否完整。
- [IsValid](IsValid.md) 只检查 `scene``camera``context`,不会验证 `surface``shadowCaster``depthOnly``objectId` 是否完整。
- `CameraRenderer::Render()` 会额外拒绝:
- `surface` 的 render area 宽高为 `0`
- `shadowCaster.IsRequested()``shadowCaster.IsValid()` 为假
- `depthOnly.IsRequested()``depthOnly.IsValid()` 为假
- `objectId.IsRequested()``objectId.IsValid()` 为假
- `SceneRenderer::Render(const std::vector<CameraRenderRequest>&)` 会先检查每条 request 的 `IsValid()`,再按 `cameraStackOrder``cameraDepth` 排序后逐条提交。
@@ -77,11 +90,12 @@ Editor Scene View 当前会先通过 [SceneViewportRenderPlan](../../Editor/View
- `SceneRenderer` 负责构建和排序多个 `CameraRenderRequest`
- Editor Scene View 当前通过 [SceneViewportRenderPlan](../../Editor/Viewport/SceneViewportRenderPlan/SceneViewportRenderPlan.md) 组装 `postScenePasses``overlayPasses` 与 clear override并通过 [ViewportHostRenderFlowUtils](../../Editor/Viewport/ViewportHostRenderFlowUtils/ViewportHostRenderFlowUtils.md) 挂入 object-id surface。
- `tests/Rendering/unit/test_camera_scene_renderer.cpp` 明确验证了 `preScenePasses -> pipeline -> objectId -> postScenePasses` 的真实执行顺序,以及 request clear override / 排序规则。
- `tests/Rendering/unit/test_camera_scene_renderer.cpp` 明确验证了 `preScenePasses -> shadowCaster -> depthOnly -> pipeline -> objectId -> postScenePasses -> overlayPasses` 的真实执行顺序,以及 request clear override / 排序规则。
## 相关文档
- [IsValid](IsValid.md)
- [ScenePassRenderRequest](ScenePassRenderRequest/ScenePassRenderRequest.md)
- [ObjectIdRenderRequest](ObjectIdRenderRequest/ObjectIdRenderRequest.md)
- [CameraRenderer](../CameraRenderer/CameraRenderer.md)
- [SceneRenderer](../SceneRenderer/SceneRenderer.md)

View File

@@ -0,0 +1,31 @@
# ScenePassRenderRequest::IsRequested
检查当前是否请求了一条独立 scene pass 路径。
```cpp
bool IsRequested() const;
```
## 行为说明
当前头文件内联实现只有一条判断:
```cpp
return !surface.GetColorAttachments().empty();
```
## 返回值
- 只要 `surface` 上至少挂了一个颜色附件,就返回 `true`
- 否则返回 `false`
## 注意事项
- 这不是完整性校验;颜色附件数组非空并不代表第一个附件非空,也不代表深度附件和 render area 合法。
- 真正更严格的检查在 [IsValid](IsValid.md)。
## 相关文档
- [返回类型总览](ScenePassRenderRequest.md)
- [IsValid](IsValid.md)
- [CameraRenderRequest](../CameraRenderRequest.md)

View File

@@ -0,0 +1,36 @@
# ScenePassRenderRequest::IsValid
检查当前 scene pass 输出目标是否满足执行 pass 的最小条件。
```cpp
bool IsValid() const;
```
## 行为说明
当前头文件内联实现要求同时满足:
```cpp
const std::vector<RHI::RHIResourceView*>& colorAttachments = surface.GetColorAttachments();
return !colorAttachments.empty() &&
colorAttachments[0] != nullptr &&
surface.GetDepthAttachment() != nullptr &&
surface.GetRenderAreaWidth() > 0 &&
surface.GetRenderAreaHeight() > 0;
```
## 返回值
- 第一个颜色附件非空、深度附件非空且 render area 宽高都大于 `0` 时返回 `true`
- 否则返回 `false`
## 与 `CameraRenderer::Render()` 的关系
- `CameraRenderer::Render()` 会先看 [IsRequested](IsRequested.md)。
- 如果请求了 `shadowCaster``depthOnly`,但这里返回 `false`,整次相机渲染会直接失败。
## 相关文档
- [返回类型总览](ScenePassRenderRequest.md)
- [IsRequested](IsRequested.md)
- [CameraRenderer::Render](../../CameraRenderer/Render.md)

View File

@@ -0,0 +1,40 @@
# ScenePassRenderRequest
**命名空间**: `XCEngine::Rendering`
**类型**: `struct`
**头文件**: `XCEngine/Rendering/CameraRenderRequest.h`
**描述**: 描述一份独立 scene pass 请求是否需要执行,以及这份 depth-only / shadow-caster 目标与覆盖参数是否完整可用。
## 概述
`ScenePassRenderRequest` 是 [CameraRenderRequest](../CameraRenderRequest.md) 里的辅助子请求,用来描述“在主 `RenderPipeline` 之前,是否还要额外执行一次 scene pass 重绘”。
当前 `DepthOnlyRenderRequest``ShadowCasterRenderRequest` 都只是它的类型别名,因此两条路径共用同一套数据契约:
| 字段 | 说明 |
|------|------|
| `surface` | scene pass 要写入的目标表面;当前实现要求至少有第一张颜色附件和一个深度附件。 |
| `clearFlags` | 回写到临时 `sceneData.cameraData.clearFlags` 的覆盖值。 |
| `hasClearColorOverride` / `clearColorOverride` | 是否覆盖这次 scene pass 使用的清屏色。 |
| `hasCameraDataOverride` / `cameraDataOverride` | 预留的相机数据覆盖槽位;当前 `CameraRenderer` 还没有消费它。 |
## 关键语义
- [IsRequested](IsRequested.md) 只回答“调用方有没有挂一个颜色附件过来”。
- [IsValid](IsValid.md) 才回答“这份 scene pass 输出目标是否足够完整,可以真正执行”。
-`engine/src/Rendering/CameraRenderer.cpp` 的当前实现,`CameraRenderer::Render()` 会先消费 `shadowCaster`,再消费 `depthOnly`,之后才进入主 `RenderPipeline`
## 真实使用位置
- `CameraRenderRequest::shadowCaster``CameraRenderRequest::depthOnly` 都是这个结构的别名实例。
- `CameraRenderer` 默认分别用 [BuiltinShadowCasterPass](../../Passes/BuiltinShadowCasterPass/BuiltinShadowCasterPass.md) 与 [BuiltinDepthOnlyPass](../../Passes/BuiltinDepthOnlyPass/BuiltinDepthOnlyPass.md) 来消费它。
## 相关文档
- [CameraRenderRequest](../CameraRenderRequest.md)
- [IsRequested](IsRequested.md)
- [IsValid](IsValid.md)
- [CameraRenderer](../../CameraRenderer/CameraRenderer.md)

View File

@@ -6,81 +6,92 @@
**头文件**: `XCEngine/Rendering/CameraRenderer.h`
**描述**: 单个 `CameraRenderRequest` 的执行器。它负责在一次相机提交里完成场景提取、主管线渲染、object-id 输出,以及调用方注入 post / overlay pass 串接
**描述**: 单个 `CameraRenderRequest` 的执行器负责在一次提交里串起 scene extraction、shadow/depth 预 pass、主主管线、object-id,以及注入 pre/post/overlay pass。
## 概
## 概
`CameraRenderer` 是当前渲染模块里的“单请求执行层”。和 [SceneRenderer](../SceneRenderer/SceneRenderer.md) 的分工是:
`CameraRenderer` 是当前 Rendering 模块里的“单 request 执行层”。它不负责决定应该渲染哪些相机,也不负责 request 排序;这些职责在 [SceneRenderer](../SceneRenderer/SceneRenderer.md) 与 [SceneRenderRequestPlanner](../SceneRenderRequestPlanner/SceneRenderRequestPlanner.md)。
- `SceneRenderer` 负责规划和排序 `CameraRenderRequest`
- `CameraRenderer` 负责把一份 request 真正跑完
因此这里关心的不是“该渲染哪些相机”,而是“这一份相机请求如何被执行”。
它关心的是另一件事:一份已经组装好的 `CameraRenderRequest`,到底按什么顺序跑完。
## 当前持有的运行时对象
- `m_sceneExtractor`
使用 `request.surface` 的 render area 尺寸调用 `ExtractForCamera(...)`,生成这次提交要用`RenderSceneData`
使用 request surface 的 render-area 尺寸提取当前相机对应`RenderSceneData`
- `m_pipelineAsset`
当前主管线的来源工厂;可能为空。
当前主管线的创建来源工厂;可能为空。
- `m_pipeline`
当前实际执行主场景绘制的 runtime [RenderPipeline](../RenderPipeline/RenderPipeline.md)。
- `m_objectIdPass`
主场景之后的 object-id pass默认是 [Passes::BuiltinObjectIdPass](../Passes/BuiltinObjectIdPass/BuiltinObjectIdPass.md)。
按需消费 `request.objectId` 的 object-id pass默认是 [Passes::BuiltinObjectIdPass](../Passes/BuiltinObjectIdPass/BuiltinObjectIdPass.md)。
- `m_depthOnlyPass`
按需消费 `request.depthOnly` 的独立 scene pass默认是 [Passes::BuiltinDepthOnlyPass](../Passes/BuiltinDepthOnlyPass/BuiltinDepthOnlyPass.md)。
- `m_shadowCasterPass`
按需消费 `request.shadowCaster` 的独立 scene pass默认是 [Passes::BuiltinShadowCasterPass](../Passes/BuiltinShadowCasterPass/BuiltinShadowCasterPass.md)。
这意味着 `CameraRenderer` 本身不负责替调用方生成 Scene View 专用效果;它只按 request 已给出的 `postScenePasses` / `overlayPasses` 顺序执行
这意味着 `CameraRenderer` 替调用方生成 Scene View 的特殊效果,但会直接消费 request 上已经明确给出的 depth-only / shadow-caster / object-id / post / overlay 槽位
## 当前执行顺序
对一份有效 request当前 `Render()` 的主顺序是:
1. 校验 request、自身主管线、render-area object-id 请求前置条件。
1. 校验 request、自身主管线、render-area,以及 `shadowCaster / depthOnly / objectId` 请求前置条件。
2.`m_sceneExtractor.ExtractForCamera(...)` 生成 `RenderSceneData`
3. 用 request 覆盖 `sceneData.cameraData.clearFlags`,必要时再覆盖 `clearColor`
4. 执行 `preScenePasses`
5. 执行 `m_pipeline->Render(...)`
6. 如请求了 object-id执行 `m_objectIdPass->Render(...)`
7. 执行 `postScenePasses`
8. 执行 `overlayPasses`
9. 按已初始化的 sequence 逆向 `Shutdown()`
5. 如请求了 shadow-caster执行 `m_shadowCasterPass`
6. 如请求了 depth-only执行 `m_depthOnlyPass`
7. 执行 `m_pipeline->Render(...)`
8. 如请求了 object-id执行 `m_objectIdPass->Render(...)`
9. 执行 `postScenePasses`
10. 执行 `overlayPasses`
11. 按已初始化的 sequence 逆向 `Shutdown()`
这条顺序被 `tests/Rendering/unit/test_camera_scene_renderer.cpp` 明确覆盖
`tests/Rendering/unit/test_camera_scene_renderer.cpp` 已覆盖这条顺序,包括 shadow-caster / depth-only 位于主主管线之前这一点
## 生命周期与回退策略
- 默认构造会使用静态共享的 [BuiltinForwardPipelineAsset](../Pipelines/BuiltinForwardPipelineAsset/BuiltinForwardPipelineAsset.md)。
- 默认构造会使用静态共享的 [BuiltinForwardPipelineAsset](../Pipelines/BuiltinForwardPipelineAsset/BuiltinForwardPipelineAsset.md),并同时创建 builtin object-id / depth-only / shadow-caster pass
- `SetPipeline()` 走“手动注入 runtime pipeline”路径并清空当前 `m_pipelineAsset`
- `SetPipelineAsset()` 走“由 asset 创建 runtime pipeline”路径传空时会回退到默认 asset。
- `ResetPipeline()` 会先 `Shutdown()` 旧主管线,再接管新实例;若新实例为空,则再次回退到默认 asset 并创建 builtin forward。
- `SetObjectIdPass()` 同样会先关闭旧 pass传空时回退到 builtin object-id pass。
- [SetObjectIdPass](SetObjectIdPass.md) 会先关闭旧 pass传空时回退到 builtin object-id pass。
- [SetDepthOnlyPass](SetDepthOnlyPass.md) 会先关闭旧 pass传空时回退到 builtin depth-only pass。
- [SetShadowCasterPass](SetShadowCasterPass.md) 会先关闭旧 pass传空时回退到 builtin shadow-caster pass。
## 当前验证规则
`Render()` 前会显式拒绝:
`Render()` 前会显式拒绝:
- `request.IsValid()` 为假
- 当前 `m_pipeline == nullptr`
- `request.surface` 的 render-area 宽或高为 `0`
- 请求了 shadow-caster`request.shadowCaster.IsValid()` 为假
- 请求了 depth-only`request.depthOnly.IsValid()` 为假
- 请求了 object-id`request.objectId.IsValid()` 为假
## 当前实现边界
- 只执行单个 request多相机排序、stack 顺序和 clear 规则在 `SceneRenderer` / `SceneRenderRequestPlanner` 层完成。
- 不直接决定“默认主管线是什么”,而是通过 pipeline asset seam 解决
- post / overlay 阶段只是顺序执行的 `RenderPassSequence`,不是 render graph。
- 这里只执行单个 request多相机排序、stack 顺序和 clear 规则在 `SceneRenderer` / `SceneRenderRequestPlanner` 层完成。
- 这里只消费 request 上已经存在的 scene-pass 与 pass-sequence 槽位,不主动构建 editor 专用 overlay
- post / overlay 阶段仍然只是顺序执行的 `RenderPassSequence`,不是 render graph。
## 公开方法
| 方法 | 说明 |
|------|------|
| [Constructor](Constructor.md) | 构造 `CameraRenderer`,并建立默认或注入的主管线 / object-id pass。 |
| [Destructor](Destructor.md) | 关闭当前主管线object-id pass。 |
| [Constructor](Constructor.md) | 构造 `CameraRenderer`,并决定主主管线与 builtin 独立 pass 的初始来源。 |
| [Destructor](Destructor.md) | 关闭当前主管线object-id pass、depth-only pass 与 shadow-caster pass。 |
| [SetPipeline](SetPipeline.md) | 手动替换当前 runtime pipeline。 |
| [SetPipelineAsset](SetPipelineAsset.md) | 通过 `RenderPipelineAsset` 重建当前 runtime pipeline。 |
| [SetObjectIdPass](SetObjectIdPass.md) | 替换当前 object-id pass。 |
| [SetDepthOnlyPass](SetDepthOnlyPass.md) | 替换当前 depth-only scene pass。 |
| [SetShadowCasterPass](SetShadowCasterPass.md) | 替换当前 shadow-caster scene pass。 |
| [GetPipeline](GetPipeline.md) | 读取当前主管线的非拥有指针。 |
| [GetPipelineAsset](GetPipelineAsset.md) | 读取当前 pipeline asset 的非拥有指针。 |
| [GetObjectIdPass](GetObjectIdPass.md) | 读取当前 object-id pass 的非拥有指针。 |
| [GetDepthOnlyPass](GetDepthOnlyPass.md) | 读取当前 depth-only pass 的非拥有指针。 |
| [GetShadowCasterPass](GetShadowCasterPass.md) | 读取当前 shadow-caster pass 的非拥有指针。 |
| [Render](Render.md) | 执行一次完整的单相机提交。 |
## 相关文档
@@ -91,4 +102,7 @@
- [RenderSceneExtractor](../RenderSceneExtractor/RenderSceneExtractor.md)
- [RenderPipeline](../RenderPipeline/RenderPipeline.md)
- [ObjectIdPass](../ObjectIdPass/ObjectIdPass.md)
- [BuiltinDepthOnlyPass](../Passes/BuiltinDepthOnlyPass/BuiltinDepthOnlyPass.md)
- [BuiltinShadowCasterPass](../Passes/BuiltinShadowCasterPass/BuiltinShadowCasterPass.md)
- [Camera Request Planning And Clear Rules](../../../_guides/Rendering/Camera-Request-Planning-And-Clear-Rules.md)
- [Scene Extraction And Builtin Forward Pipeline](../../../_guides/Rendering/Scene-Extraction-And-Builtin-Forward-Pipeline.md)

View File

@@ -1,49 +1,65 @@
# CameraRenderer::Constructor
**命名空间**: `XCEngine::Rendering`
**类型**: `constructor-overload group`
**头文件**: `XCEngine/Rendering/CameraRenderer.h`
## 签名
```cpp
CameraRenderer();
explicit CameraRenderer(std::unique_ptr<RenderPipeline> pipeline);
explicit CameraRenderer(std::shared_ptr<const RenderPipelineAsset> pipelineAsset);
CameraRenderer(
std::unique_ptr<RenderPipeline> pipeline,
std::unique_ptr<ObjectIdPass> objectIdPass);
std::unique_ptr<ObjectIdPass> objectIdPass,
std::unique_ptr<RenderPass> depthOnlyPass = nullptr,
std::unique_ptr<RenderPass> shadowCasterPass = nullptr);
```
## 行为说明
构造函数的核心职责是决定件事:
构造函数的核心职责是决定件事:
- 当前主管线实例从哪里来
- 当前 object-id pass 是否使用默认 builtin 实现
- 当前主管线实例从哪里来
- 当前 object-id pass 是否使用默认 builtin 实现
- 当前 depth-only / shadow-caster pass 是否使用默认 builtin 实现
## 当前构造路径
### 默认构造
- 调用内部静态 `CreateDefaultPipelineAsset()`
- 默认 asset 是共享的 [BuiltinForwardPipelineAsset](../Pipelines/BuiltinForwardPipelineAsset/BuiltinForwardPipelineAsset.md)。
- 随后走 asset 构造路径生成主管线
- 通过内部静态 `CreateDefaultPipelineAsset()` 取得共享的默认 asset
- 默认 asset 是 [BuiltinForwardPipelineAsset](../Pipelines/BuiltinForwardPipelineAsset/BuiltinForwardPipelineAsset.md)。
- 随后走 asset 构造路径生成 runtime pipeline
### `std::unique_ptr<RenderPipeline>` 重载
- 交由 `(pipeline, objectIdPass)` 这个双参重载处理。
- 如果未显式提供 object-id pass默认补一个 [Passes::BuiltinObjectIdPass](../Passes/BuiltinObjectIdPass/BuiltinObjectIdPass.md)。
- 交由参重载处理。
- 如果未显式提供 object-id / depth-only / shadow-caster pass会分别补
- [Passes::BuiltinObjectIdPass](../Passes/BuiltinObjectIdPass/BuiltinObjectIdPass.md)
- [Passes::BuiltinDepthOnlyPass](../Passes/BuiltinDepthOnlyPass/BuiltinDepthOnlyPass.md)
- [Passes::BuiltinShadowCasterPass](../Passes/BuiltinShadowCasterPass/BuiltinShadowCasterPass.md)
### `std::shared_ptr<const RenderPipelineAsset>` 重载
- 先保存 asset。
- 再调用 [SetPipelineAsset](SetPipelineAsset.md),立即由 asset 创建 runtime pipeline。
- 默认同时创建 builtin object-id pass。
- 默认同时创建 builtin object-id / depth-only / shadow-caster pass。
### `(pipeline, objectIdPass)` 重载
### 四参重载
-`objectIdPass` 为空,自动回退到 builtin object-id pass。
-`depthOnlyPass` 为空,自动回退到 builtin depth-only pass。
-`shadowCasterPass` 为空,自动回退到 builtin shadow-caster pass。
- 调用内部 `ResetPipeline(std::move(pipeline))`
- 如果传入 `pipeline` 为空,`ResetPipeline()` 会继续回退到默认 pipeline asset并创建 builtin forward 主管线。
## 所有权
- `RenderPipeline``ObjectIdPass` `CameraRenderer``std::unique_ptr` 独占持有。
- `RenderPipeline``ObjectIdPass``depthOnlyPass``shadowCasterPass``CameraRenderer``std::unique_ptr` 独占持有。
- `RenderPipelineAsset``std::shared_ptr<const ...>` 共享持有,只作为 runtime pipeline 的创建来源。
## 相关文档
@@ -52,3 +68,5 @@ CameraRenderer(
- [SetPipeline](SetPipeline.md)
- [SetPipelineAsset](SetPipelineAsset.md)
- [SetObjectIdPass](SetObjectIdPass.md)
- [SetDepthOnlyPass](SetDepthOnlyPass.md)
- [SetShadowCasterPass](SetShadowCasterPass.md)

View File

@@ -14,7 +14,7 @@
## 作用
在对象销毁前关闭当前持有的主管线object-id pass。
在对象销毁前关闭当前持有的主管线object-id pass、depth-only pass 和 shadow-caster pass。
## 当前实现行为
@@ -22,21 +22,25 @@
1. 如果 `m_pipeline` 非空,调用 `m_pipeline->Shutdown()`
2. 如果 `m_objectIdPass` 非空,调用 `m_objectIdPass->Shutdown()`
3. 如果 `m_depthOnlyPass` 非空,调用 `m_depthOnlyPass->Shutdown()`
4. 如果 `m_shadowCasterPass` 非空,调用 `m_shadowCasterPass->Shutdown()`
随后由 `unique_ptr` 和成员对象自身析构负责释放内存。
## 设计含义
- 主管线object-id pass 的 GPU 资源回收路径是显式 `Shutdown()`,而不是只依赖 C++ 析构。
- 主管线object-id pass、depth-only pass 和 shadow-caster pass 的 GPU 资源回收路径是显式 `Shutdown()`,而不是只依赖 C++ 析构。
- 调用方注入到 `CameraRenderRequest` 里的 `RenderPassSequence` 并不由这里持有,因此也不在这里做统一回收。
## 注意事项
- 当前没有内部同步;不应在其它线程仍可能访问管线或命令对象时销毁 `CameraRenderer`
- 如果你只是想切换主管线或 object-id pass不要等到析构应该优先使用 [SetPipeline](SetPipeline.md)、[SetPipelineAsset](SetPipelineAsset.md)[SetObjectIdPass](SetObjectIdPass.md)。
- 当前没有内部同步;不应在其它线程仍可能访问这些对象时销毁 `CameraRenderer`
- 如果你只是想切换主管线或这些独立 pass不要等到析构应该优先使用 [SetPipeline](SetPipeline.md)、[SetPipelineAsset](SetPipelineAsset.md)[SetObjectIdPass](SetObjectIdPass.md)、[SetDepthOnlyPass](SetDepthOnlyPass.md) 或 [SetShadowCasterPass](SetShadowCasterPass.md)
## 相关文档
- [CameraRenderer](CameraRenderer.md)
- [SetPipeline](SetPipeline.md)
- [SetObjectIdPass](SetObjectIdPass.md)
- [SetDepthOnlyPass](SetDepthOnlyPass.md)
- [SetShadowCasterPass](SetShadowCasterPass.md)

View File

@@ -0,0 +1,32 @@
# CameraRenderer::GetDepthOnlyPass
**命名空间**: `XCEngine::Rendering`
**类型**: `method`
**头文件**: `XCEngine/Rendering/CameraRenderer.h`
## 签名
```cpp
RenderPass* GetDepthOnlyPass() const;
```
## 作用
返回当前 depth-only scene pass 的裸指针。
## 当前实现行为
- 这是头文件内联访问器,直接返回 `m_depthOnlyPass.get()`
- 不转移所有权。
## 注意事项
- 调用 [SetDepthOnlyPass](SetDepthOnlyPass.md) 之后,之前读取到的裸指针可能立刻失效。
- 当前默认返回的通常是 builtin depth-only pass但调用方不应把这个 API 当成“只会返回某个具体类型”的承诺。
## 相关文档
- [SetDepthOnlyPass](SetDepthOnlyPass.md)
- [Render](Render.md)

View File

@@ -0,0 +1,32 @@
# CameraRenderer::GetShadowCasterPass
**命名空间**: `XCEngine::Rendering`
**类型**: `method`
**头文件**: `XCEngine/Rendering/CameraRenderer.h`
## 签名
```cpp
RenderPass* GetShadowCasterPass() const;
```
## 作用
返回当前 shadow-caster scene pass 的裸指针。
## 当前实现行为
- 这是头文件内联访问器,直接返回 `m_shadowCasterPass.get()`
- 不转移所有权。
## 注意事项
- 调用 [SetShadowCasterPass](SetShadowCasterPass.md) 之后,之前读取到的裸指针可能立刻失效。
- 当前默认返回的通常是 builtin shadow-caster pass但调用方不应假定返回值一定来自某个具体实现类。
## 相关文档
- [SetShadowCasterPass](SetShadowCasterPass.md)
- [Render](Render.md)

View File

@@ -1,44 +1,57 @@
# CameraRenderer::Render
**命名空间**: `XCEngine::Rendering`
**类型**: `method`
**头文件**: `XCEngine/Rendering/CameraRenderer.h`
## 签名
```cpp
bool Render(const CameraRenderRequest& request);
```
## 行为说明
执行一次完整的单相机提交。当前实现会把主场景、object-id调用方注入的 post passes 和 overlay passes 串成一条固定顺序的执行链。
执行一次完整的单相机提交。当前实现会把 shadow-caster、depth-only、主场景、object-id,以及调用方注入的 pre / post / overlay pass 串成一条固定顺序的执行链。
## 当前流程
1. 校验 `request.IsValid()`,并确认 `m_pipeline` 非空。
2. 拒绝 render-area 宽或高为 `0``surface`
3. 如果请求了 object-id,要 `request.objectId.IsValid()` 为真。
4. `request.surface.GetRenderAreaWidth()` / `GetRenderAreaHeight()` 调用 `m_sceneExtractor.ExtractForCamera(...)`
5. `sceneData.HasCamera()` 为假,则返回 `false`
6. 用 request 覆盖 `sceneData.cameraData.clearFlags`;如果 request 提供了 clear-color override则继续覆盖 `sceneData.cameraData.clearColor`
7. 依次初始化并执行:
3. 如果请求了 shadow-caster,要 `request.shadowCaster.IsValid()` 为真。
4. 如果请求了 depth-only要让 `request.depthOnly.IsValid()` 为真
5. 如果请求了 object-id要让 `request.objectId.IsValid()` 为真
6.`request.surface.GetRenderAreaWidth()` / `GetRenderAreaHeight()` 调用 `m_sceneExtractor.ExtractForCamera(...)`
7. `sceneData.HasCamera()` 为假,则返回 `false`
8. 用 request 覆盖 `sceneData.cameraData.clearFlags`;如果 request 提供了 clear-color override则继续覆盖 `sceneData.cameraData.clearColor`
9. 依次初始化并执行:
- `preScenePasses`
- `m_shadowCasterPass->Execute(...)`
- `m_depthOnlyPass->Execute(...)`
- `m_pipeline->Render(...)`
- `m_objectIdPass->Render(...)`
- `postScenePasses`
- `overlayPasses`
8. 按已经成功初始化的 sequence 做逆向 `Shutdown()`
10. 按已经成功初始化的 sequence 做逆向 `Shutdown()`
## `postScenePasses` / `overlayPasses` 接入点
`CameraRenderer` 只消费调用方传入的 pass 序列,不额外构建内部后处理层。
`CameraRenderer` 只消费调用方传入的 pass 序列,不额外构建内部后处理层。
- `postScenePasses` 直接来自调用方提供的 `RenderPassSequence`
- `overlayPasses` 也是同样的注入点
- 编辑器 Scene View 当前会先通过 [SceneViewportRenderPlan](../../Editor/Viewport/SceneViewportRenderPlan/SceneViewportRenderPlan.md) 组装这些序列,再调用 `ApplySceneViewportRenderPlan(...)` 挂到 request
这意味着 Scene View 的无限网格、选中轮廓和编辑器 overlay已经被上移到 request 组装层,不再由 `CameraRenderer` 内部再做一次翻译。
这意味着 Scene View 的无限网格、选中轮廓和编辑器 overlay已经被上移到 request 组装层,不再由 `CameraRenderer` 内部再做一次翻译。与之相对,`shadowCaster``depthOnly` 当前仍属于 `CameraRenderRequest` 上的专用 scene-pass 槽位,由 `CameraRenderer` 直接在主主管线之前消费。
## 失败与清理语义
- 任一验证失败会直接返回 `false`
- `shadowCaster``depthOnly` 请求校验失败时,不会进入主主管线。
- 任一 sequence 初始化失败会立刻执行对应 `Shutdown()` 回滚。
- 主管线、object-id pass、post 或 overlay 任一阶段失败,都会按已经初始化过的 sequence 做清理再返回 `false`
- `shadowCaster``depthOnly`主管线、object-id pass、post 或 overlay 任一阶段失败,都会按已经初始化过的 sequence 做清理再返回 `false`
## 参数
@@ -46,17 +59,17 @@ bool Render(const CameraRenderRequest& request);
## 返回值
- 整条提交成功执行时返回 `true`
- 整条提交成功执行时返回 `true`
- request 校验失败、场景提取失败、主管线失败,或任一附加阶段失败时返回 `false`
## 测试覆盖
`tests/Rendering/unit/test_camera_scene_renderer.cpp` 当前验证了:
- render-area 会影响提取到的相机 viewport 尺寸
- clear-flags 和 clear-color override 会写回 `sceneData.cameraData`
- `pre / pipeline / object-id / post / overlay` 的执行顺序
- object-id 失败和 post-pass 初始化失败时的回滚路径
- render-area 会影响提取到的相机 viewport 尺寸
- clear-flags 和 clear-color override 会写回 `sceneData.cameraData`
- `shadowCaster / depthOnly / pipeline / object-id / post / overlay` 的执行顺序
- shadow-caster 请求无效、object-id 失败和 post-pass 初始化失败时的回滚路径
## 相关文档
@@ -64,4 +77,6 @@ bool Render(const CameraRenderRequest& request);
- [CameraRenderRequest](../CameraRenderRequest/CameraRenderRequest.md)
- [RenderSceneExtractor](../RenderSceneExtractor/RenderSceneExtractor.md)
- [RenderPipeline::Render](../RenderPipeline/Render.md)
- [SetDepthOnlyPass](SetDepthOnlyPass.md)
- [SetShadowCasterPass](SetShadowCasterPass.md)
- [Passes](../Passes/Passes.md)

View File

@@ -0,0 +1,35 @@
# CameraRenderer::SetDepthOnlyPass
**命名空间**: `XCEngine::Rendering`
**类型**: `method`
**头文件**: `XCEngine/Rendering/CameraRenderer.h`
## 签名
```cpp
void SetDepthOnlyPass(std::unique_ptr<RenderPass> depthOnlyPass);
```
## 作用
替换当前用于消费 `request.depthOnly` 的独立 scene pass。
## 当前实现行为
1. 如果旧 `m_depthOnlyPass` 非空,先调用它的 `Shutdown()`
2. 接管新的 `depthOnlyPass`
3. 如果新指针为空,则自动回退到 [Passes::BuiltinDepthOnlyPass](../Passes/BuiltinDepthOnlyPass/BuiltinDepthOnlyPass.md)。
## 关键语义
- 这里替换的是一个普通 `RenderPass`,并不要求具体类型必须来自 builtin pass 层。
- `CameraRenderer::Render()` 只在 `request.depthOnly.IsRequested()` 时才会真正执行这里持有的 pass。
- `tests/Rendering/unit/test_camera_scene_renderer.cpp` 通过 mock pass 验证了这条注入链会在主主管线之前执行,并正确消费 `ScenePassRenderRequest` 的 surface / clear-color override。
## 相关文档
- [GetDepthOnlyPass](GetDepthOnlyPass.md)
- [Render](Render.md)
- [BuiltinDepthOnlyPass](../Passes/BuiltinDepthOnlyPass/BuiltinDepthOnlyPass.md)

View File

@@ -0,0 +1,35 @@
# CameraRenderer::SetShadowCasterPass
**命名空间**: `XCEngine::Rendering`
**类型**: `method`
**头文件**: `XCEngine/Rendering/CameraRenderer.h`
## 签名
```cpp
void SetShadowCasterPass(std::unique_ptr<RenderPass> shadowCasterPass);
```
## 作用
替换当前用于消费 `request.shadowCaster` 的独立 scene pass。
## 当前实现行为
1. 如果旧 `m_shadowCasterPass` 非空,先调用它的 `Shutdown()`
2. 接管新的 `shadowCasterPass`
3. 如果新指针为空,则自动回退到 [Passes::BuiltinShadowCasterPass](../Passes/BuiltinShadowCasterPass/BuiltinShadowCasterPass.md)。
## 关键语义
- 这里替换的是一个普通 `RenderPass`,并不要求必须是 builtin shadow-caster 实现。
- `CameraRenderer::Render()` 只在 `request.shadowCaster.IsRequested()` 时才会执行这里持有的 pass。
- 当前执行顺序里shadow-caster pass 位于 depth-only 与主主管线之前。
## 相关文档
- [GetShadowCasterPass](GetShadowCasterPass.md)
- [Render](Render.md)
- [BuiltinShadowCasterPass](../Passes/BuiltinShadowCasterPass/BuiltinShadowCasterPass.md)

View File

@@ -46,10 +46,11 @@
在 [CameraRenderer](../CameraRenderer/CameraRenderer.md) 里object-id pass 的执行顺序是:
1. 执行 pre-scene pass
2. 绘制主 `RenderPipeline`
3. 如果 `request.objectId.IsRequested()`,执行 `ObjectIdPass`
4. 再执行 `postScenePasses`
5. 最后执行 `overlayPasses`
2. 如请求了 `shadowCaster` / `depthOnly`,先执行对应 scene pass
3. 绘制主 `RenderPipeline`
4. 如果 `request.objectId.IsRequested()`,执行 `ObjectIdPass`
5. 执行 `postScenePasses`
6. 最后执行 `overlayPasses`
## 当前实现边界

View File

@@ -14,6 +14,7 @@
- 在构造时把基类 pass 类型固定为 `BuiltinMaterialPass::DepthOnly`,并注入 builtin depth-only shader 路径。
- 通过 [GetName](GetName.md) 和 [BuildInputLayout](BuildInputLayout.md) 暴露当前 pass 的公开身份与顶点布局。
- `CameraRenderer` 默认把它挂在 `depthOnly` request 槽位上;如果请求被触发,执行时仍沿用基类对 `colorAttachments[0]``depthAttachment` 的双附件要求。
真正的初始化、执行和资源释放逻辑仍由 [BuiltinDepthStylePassBase](../BuiltinDepthStylePassBase/BuiltinDepthStylePassBase.md) 提供。

View File

@@ -16,6 +16,7 @@
- 复用 [RenderResourceCache](../../RenderResourceCache/RenderResourceCache.md) 上传 mesh GPU 副本。
- 只接受“单个 `PerObject` 常量缓冲”这一类资源绑定计划。
- 在 [Execute](Execute.md) 中统一处理 `RenderSurface` 检查、viewport/scissor、清屏、绘制循环和颜色附件状态切换。
- 虽然是“深度风格” pass当前执行框架仍要求 `RenderSurface` 同时提供 `colorAttachments[0]``depthAttachment`,并沿用颜色 clear / transition 路径。
派生类当前只负责决定:

View File

@@ -20,6 +20,7 @@ bool Execute(const RenderPassContext& context) override;
## 当前语义
- 当前实现只处理第一个颜色附件和一个深度附件。
- 虽然 pipeline state 把 `colorWriteMask` 设为 `0`,当前实现仍要求 `colorAttachments[0]` 有效,因为 render pass 建立、清颜色和状态迁移都走同一套 surface 逻辑。
- 清颜色使用的是 `sceneData.cameraData.clearColor`,不会读取 `RenderSurface` 自己的 clear-color override。
- 物体真正能否绘制,还取决于 mesh 是否有效、shader pass 是否可解析、descriptor set 是否能成功创建等后续条件。

View File

@@ -22,8 +22,8 @@
- editor 调用方
通过 [SetShaderPath](SetShaderPath.md) 或构造函数参数注入具体 shader 路径。
- `SceneViewportGridPass`
负责把 [SceneViewportShaderPaths](../../../Editor/Viewport/SceneViewportShaderPaths/SceneViewportShaderPaths.md)
生成的 editor 资源路径传进来。
负责把 [SceneViewportResourcePaths](../../../Editor/Viewport/SceneViewportResourcePaths/SceneViewportResourcePaths.md)
生成的 editor 资源路径传进来`SceneViewportShaderPaths` 现在只是兼容 include 层
## 关键输入
@@ -79,4 +79,4 @@
- [InfiniteGridParameters](InfiniteGridParameters.md)
- [BuildInfiniteGridParameters](BuildInfiniteGridParameters.md)
- [SceneViewportRenderPlan](../../../Editor/Viewport/SceneViewportRenderPlan/SceneViewportRenderPlan.md)
- [SceneViewportShaderPaths](../../../Editor/Viewport/SceneViewportShaderPaths/SceneViewportShaderPaths.md)
- [SceneViewportResourcePaths](../../../Editor/Viewport/SceneViewportResourcePaths/SceneViewportResourcePaths.md)

View File

@@ -25,8 +25,8 @@
- editor 调用方
通过 [SetShaderPath](SetShaderPath.md) 或构造函数参数注入具体 shader 路径。
- `SceneViewportSelectionOutlinePass`
当前用 [SceneViewportShaderPaths](../../../Editor/Viewport/SceneViewportShaderPaths/SceneViewportShaderPaths.md)
生成 editor-owned object-id outline shader 路径,再交给这里执行。
当前用 [SceneViewportResourcePaths](../../../Editor/Viewport/SceneViewportResourcePaths/SceneViewportResourcePaths.md)
生成 editor-owned object-id outline shader 路径,再交给这里执行`SceneViewportShaderPaths` 只是兼容 include 层
## 输入与输出契约
@@ -93,4 +93,4 @@
- [ObjectIdOutlineStyle](../ObjectIdOutlineStyle/ObjectIdOutlineStyle.md)
- [CameraRenderer](../../CameraRenderer/CameraRenderer.md)
- [RenderSurface](../../RenderSurface/RenderSurface.md)
- [SceneViewportShaderPaths](../../../Editor/Viewport/SceneViewportShaderPaths/SceneViewportShaderPaths.md)
- [SceneViewportResourcePaths](../../../Editor/Viewport/SceneViewportResourcePaths/SceneViewportResourcePaths.md)

View File

@@ -14,6 +14,7 @@
- 构造时注入的是 `BuiltinMaterialPass::ShadowCaster` 与 builtin shadow-caster shader 路径。
- 通过 [ShouldRenderVisibleItem](ShouldRenderVisibleItem.md) 过滤掉 `MeshRendererComponent::GetCastShadows() == false` 的物体。
- `CameraRenderer` 默认把它挂在 `shadowCaster` request 槽位上;如果请求被触发,它会在主 `RenderPipeline` 之前执行,并同样沿用基类对双附件 surface 的要求。
## 公开方法

View File

@@ -4,20 +4,27 @@
**类型**: `submodule`
**描述**: 承载 builtin object-id、selection outline、infinite grid 等补充型渲染 pass以及这些 pass 复用的轻量样式/参数类型。
**描述**: 承载 builtin object-id、selection outline、infinite grid,以及 depth-only / shadow-caster 一类可复用渲染 pass 与配套样式/参数类型。
## 概述
`Rendering::Passes` 不是用来替代 [RenderPipeline](../RenderPipeline/RenderPipeline.md) 的第二套主渲染框架,而是承载“主场景已经画完之后,还需要补一层额外结果”的 builtin pass
`Rendering::Passes` 不是用来替代 [RenderPipeline](../RenderPipeline/RenderPipeline.md) 的第二套主渲染框架,而是承载几类被 `CameraRenderer`、editor 视口流程和 builtin pipeline 复用的 builtin pass
- [BuiltinObjectIdPass](BuiltinObjectIdPass/BuiltinObjectIdPass.md) 把可见物体编码成 object-id 颜色,写到辅助渲染目标,供拾取和选中反馈使用。
- [BuiltinObjectIdOutlinePass](BuiltinObjectIdOutlinePass/BuiltinObjectIdOutlinePass.md) 读取 object-id 纹理和选中对象列表,把轮廓或调试 mask 叠加回场景颜色。
- [BuiltinInfiniteGridPass](BuiltinInfiniteGridPass/BuiltinInfiniteGridPass.md) 给 Scene View 一类编辑器视口叠加无限网格。
- [BuiltinDepthStylePassBase](BuiltinDepthStylePassBase/BuiltinDepthStylePassBase.md) 为深度风格场景重绘 pass 提供共享执行骨架。
- [BuiltinDepthOnlyPass](BuiltinDepthOnlyPass/BuiltinDepthOnlyPass.md) 是 `CameraRenderer` 默认 `depthOnly` request 的 builtin 实现。
- [BuiltinShadowCasterPass](BuiltinShadowCasterPass/BuiltinShadowCasterPass.md) 是 `CameraRenderer` 默认 `shadowCaster` request 的 builtin 实现。
当前这些 builtin pass 更多是“底层执行单元”。真正决定 Scene View 要不要画网格、要不要叠选中轮廓、这些效果要挂到 `postScenePasses` 还是 `overlayPasses` 上的逻辑,已经迁移到 editor 侧的 [SceneViewportRenderPlan](../../Editor/Viewport/SceneViewportRenderPlan/SceneViewportRenderPlan.md)
其中 object-id / outline / infinite-grid 更接近“主场景之外的附加结果”depth-only / shadow-caster 则属于 `ScenePassRenderRequest` 路径,会在 `CameraRenderer` 中作为场景重绘 pass 直接执行,而不是 editor overlay 逻辑的一部分
当前这些 builtin pass 更多是“底层执行单元”。真正决定 Scene View 要不要画网格、要不要叠选中轮廓、这些效果要挂到 `postScenePasses` 还是 `overlayPasses` 上的逻辑,已经迁移到 editor 侧的 [SceneViewportRenderPlan](../../Editor/Viewport/SceneViewportRenderPlan/SceneViewportRenderPlan.md);真正决定 depth-only / shadow-caster surface 与 clear 策略的,则是 [CameraRenderRequest](../CameraRenderRequest/CameraRenderRequest.md)。
## 典型链路
### Scene View / editor 补充 pass
当前 Scene View 相关链路大致是:
1. [CameraRenderer](../CameraRenderer/CameraRenderer.md) 先执行主 `RenderPipeline`
@@ -25,6 +32,14 @@
3. editor 侧的 [SceneViewportRenderPlan](../../Editor/Viewport/SceneViewportRenderPlan/SceneViewportRenderPlan.md) 会根据 overlay、选中对象和 render targets 同时构建 `postScenePasses``overlayPasses`
4. 其中 `postScenePasses` 里的 `SceneViewportGridPass` / `SceneViewportSelectionOutlinePass` 包装器,最终分别调用 [BuiltinInfiniteGridPass](BuiltinInfiniteGridPass/BuiltinInfiniteGridPass.md) 与 [BuiltinObjectIdOutlinePass](BuiltinObjectIdOutlinePass/BuiltinObjectIdOutlinePass.md)`overlayPasses` 则保留给 editor overlay 的最终叠加层。
### Depth-only / shadow-caster request
`CameraRenderer` 自身持有的 scene pass当前链路大致是
1. 调用方在 [CameraRenderRequest](../CameraRenderRequest/CameraRenderRequest.md) 的 `shadowCaster` / `depthOnly` 槽位里提供 `ScenePassRenderRequest`
2. `CameraRenderer` 在执行主 `RenderPipeline` 前,先按顺序驱动 [BuiltinShadowCasterPass](BuiltinShadowCasterPass/BuiltinShadowCasterPass.md) 与 [BuiltinDepthOnlyPass](BuiltinDepthOnlyPass/BuiltinDepthOnlyPass.md) 的默认实例。
3. 这两类 pass 共用 [BuiltinDepthStylePassBase::Execute](BuiltinDepthStylePassBase/Execute.md) 的执行框架,因此当前都要求 `surface` 同时提供 `colorAttachments[0]``depthAttachment`,并复用 `renderArea`、clear flags 与状态迁移逻辑。
## 当前公开概念
| 类型 / 头文件 | 角色 |
@@ -36,10 +51,15 @@
| [InfiniteGridPassData](BuiltinInfiniteGridPass/InfiniteGridPassData.md) | 网格 pass 使用的相机姿态与裁剪参数。 |
| [InfiniteGridParameters](BuiltinInfiniteGridPass/InfiniteGridParameters.md) | 由相机状态推导出的网格尺度、过渡和淡出参数。 |
| [BuildInfiniteGridParameters](BuiltinInfiniteGridPass/BuildInfiniteGridParameters.md) | 把 Scene View 相机数据折算成稳定的十进制网格参数。 |
| [BuiltinDepthStylePassBase](BuiltinDepthStylePassBase/BuiltinDepthStylePassBase.md) | depth-only / shadow-caster 场景重绘共享的执行骨架。 |
| [BuiltinDepthOnlyPass](BuiltinDepthOnlyPass/BuiltinDepthOnlyPass.md) | `CameraRenderer` 默认的 depth-only scene pass。 |
| [BuiltinShadowCasterPass](BuiltinShadowCasterPass/BuiltinShadowCasterPass.md) | `CameraRenderer` 默认的 shadow-caster scene pass。 |
## 测试与真实调用点
- `tests/Rendering/unit/test_camera_scene_renderer.cpp` 验证了 `CameraRenderer` 中 object-id pass 与可选 pass sequence 的接入时机。
- `engine/src/Rendering/CameraRenderer.cpp` 当前把 [BuiltinShadowCasterPass](BuiltinShadowCasterPass/BuiltinShadowCasterPass.md) 与 [BuiltinDepthOnlyPass](BuiltinDepthOnlyPass/BuiltinDepthOnlyPass.md) 作为默认 scene pass 挂进 `shadowCaster` / `depthOnly` request。
- `tests/Rendering/unit/test_builtin_forward_pipeline.cpp` 固定了 depth-only / shadow-caster 输入布局和 legacy builtin binding plan 的兼容语义。
- `tests/Editor/test_scene_viewport_overlay_renderer.cpp` 固定了 `BuildInfiniteGridParameters(...)` 的十进制尺度、过渡和淡出语义。
- `tests/Editor/test_viewport_render_flow_utils.cpp` 验证了 Scene View render plan 如何组装 grid / selection outline / overlay pass以及 object-id SRV 缺失时的警告路径。
@@ -47,6 +67,7 @@
- 这一层目前是 builtin、轻量、偏 editor/工具链导向的 pass 集合,还不是通用 render graph。
- object-id 相关流程依赖单独的辅助 render target / shader resource view而不是直接从主颜色结果反推。
- depth-style 家族当前仍要求 `RenderSurface` 提供首个颜色附件和深度附件;它不是“只给一个 depth target 就能跑”的极简路径。
- 具体 pass 的资源状态切换大多由调用方保证,单个 pass 本身往往只做最小提交逻辑。
## 相关文档
@@ -55,6 +76,9 @@
- [BuiltinInfiniteGridPass](BuiltinInfiniteGridPass/BuiltinInfiniteGridPass.md)
- [BuiltinObjectIdOutlinePass](BuiltinObjectIdOutlinePass/BuiltinObjectIdOutlinePass.md)
- [ObjectIdOutlineStyle](ObjectIdOutlineStyle/ObjectIdOutlineStyle.md)
- [BuiltinDepthStylePassBase](BuiltinDepthStylePassBase/BuiltinDepthStylePassBase.md)
- [BuiltinDepthOnlyPass](BuiltinDepthOnlyPass/BuiltinDepthOnlyPass.md)
- [BuiltinShadowCasterPass](BuiltinShadowCasterPass/BuiltinShadowCasterPass.md)
- [SceneViewportRenderPlan](../../Editor/Viewport/SceneViewportRenderPlan/SceneViewportRenderPlan.md)
- [CameraRenderRequest](../CameraRenderRequest/CameraRenderRequest.md)
- [CameraRenderer](../CameraRenderer/CameraRenderer.md)

View File

@@ -20,13 +20,17 @@
## 当前资源契约
`BuiltinForwardPipeline` 会优先读取 shader pass 自己声明的 `resources`。如果该列表为空,则回退到 legacy builtin forward 绑定:
`BuiltinForwardPipeline` 会优先读取 shader pass 自己声明的 `resources`。如果该列表为空,则回退到 [BuildLegacyBuiltinForwardPassResourceBindings](../../RenderMaterialUtility/BuildLegacyBuiltinForwardPassResourceBindings.md) 返回的 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`
随后会通过 [TryBuildBuiltinPassResourceBindingPlan](../../RenderMaterialUtility/TryBuildBuiltinPassResourceBindingPlan.md)
把显式资源声明或 legacy fallback 统一收口成
[BuiltinPassResourceBindingPlan](../../RenderMaterialUtility/BuiltinPassResourceBindingPlan.md)。
当前可识别的 forward 语义只有四个:
- `PerObject`:必需,且必须是唯一的 constant buffer。
@@ -39,7 +43,7 @@
`Material::GetConstantBufferData()` 的字节视图;只有拿不到有效 payload 时,
才会回退到内部 `FallbackPerMaterialConstants { baseColorFactor }`
布局构建阶段遇到以下情况会直接记录错误并拒绝创建该 pass layout
binding-plan 解析之后,布局构建阶段还会继续拒绝以下情况
- 未知语义。
- 非法 set index。

View File

@@ -1,14 +1,24 @@
# BuiltinForwardPipeline::~BuiltinForwardPipeline
销毁 builtin forward 主场景管线。
```cpp
~BuiltinForwardPipeline() override;
```
## 行为说明
## 当前语义
析构函数会直接调用 [Shutdown](Shutdown.md),把内部 pass sequence 和 builtin forward 共享资源完整释放掉
- 当前析构函数会直接调用 [Shutdown](Shutdown.md)。
- `Shutdown()` 又会通过内部 `m_passSequence` 触发 `BuiltinForwardOpaquePass::Shutdown()`,最终回收到 `DestroyPipelineResources()`
- 因此析构前会清掉 builtin shader handle、pass layout、descriptor set 缓存、pipeline state、fallback 纹理/采样器,以及内部 [RenderResourceCache](../../RenderResourceCache/RenderResourceCache.md)。
## 设计说明
- 这一层析构兜底很重要,因为 [RenderPipeline](../../RenderPipeline/RenderPipeline.md) 基类的虚析构函数本身不会自动执行 `Shutdown()`
- 即使调用方忘记先手动 shutdownbuiltin forward pipeline 也会在对象销毁时补做一次资源释放。
## 相关文档
- [BuiltinForwardPipeline](BuiltinForwardPipeline.md)
- [Shutdown](Shutdown.md)
- [RenderPipeline::Destructor](../../RenderPipeline/Destructor.md)

View File

@@ -0,0 +1,46 @@
# BuildLegacyBuiltinForwardPassResourceBindings
**命名空间**: `XCEngine::Rendering`
**类型**: `function`
**头文件**: `XCEngine/Rendering/RenderMaterialUtility.h`
## 签名
```cpp
Containers::Array<Resources::ShaderResourceBindingDesc> BuildLegacyBuiltinForwardPassResourceBindings();
```
## 作用
构造 builtin forward 路径在没有显式 `resources` 声明时使用的 legacy fallback 绑定列表。
## 当前实现行为
当前固定返回四条绑定:
| `set` | `binding` | `semantic` | `type` |
|------|------|------|------|
| `1` | `0` | `PerObject` | `ConstantBuffer` |
| `2` | `0` | `Material` | `ConstantBuffer` |
| `3` | `0` | `BaseColorTexture` | `Texture2D` |
| `4` | `0` | `LinearClampSampler` | `Sampler` |
## 当前使用位置
- [BuiltinForwardPipeline](../Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md) 在 shader pass 没有显式资源声明时,会先调用这条 helper。
- 随后再交给 [TryBuildBuiltinPassResourceBindingPlan](TryBuildBuiltinPassResourceBindingPlan.md) 解析成统一 plan。
## 测试覆盖
`tests/Rendering/unit/test_builtin_forward_pipeline.cpp` 当前验证了:
- 返回值包含四条绑定
- 经 binding-plan 解析后,对应语义会落到 `set 1/2/3/4`
## 相关文档
- [TryBuildBuiltinPassResourceBindingPlan](TryBuildBuiltinPassResourceBindingPlan.md)
- [BuiltinForwardPipeline](../Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md)
- [RenderMaterialUtility](RenderMaterialUtility.md)

View File

@@ -0,0 +1,44 @@
# BuildLegacyBuiltinObjectIdPassResourceBindings
**命名空间**: `XCEngine::Rendering`
**类型**: `function`
**头文件**: `XCEngine/Rendering/RenderMaterialUtility.h`
## 签名
```cpp
Containers::Array<Resources::ShaderResourceBindingDesc> BuildLegacyBuiltinObjectIdPassResourceBindings();
```
## 作用
构造 builtin object-id 路径在没有显式 `resources` 声明时使用的 legacy fallback 绑定列表。
## 当前实现行为
当前固定只返回一条绑定:
| `set` | `binding` | `semantic` | `type` |
|------|------|------|------|
| `0` | `0` | `PerObject` | `ConstantBuffer` |
## 当前使用位置
- [BuiltinObjectIdPass](../Passes/BuiltinObjectIdPass/BuiltinObjectIdPass.md) 在 shader pass 没有显式资源声明时,会先回退到这份绑定列表。
- 后续同样交给 [TryBuildBuiltinPassResourceBindingPlan](TryBuildBuiltinPassResourceBindingPlan.md) 统一解析。
## 测试覆盖
`tests/Rendering/unit/test_builtin_forward_pipeline.cpp` 当前验证了:
- 返回值只有一条绑定
- 解析后的 plan 只包含 `PerObject`
- `firstDescriptorSet == 0``descriptorSetCount == 1`
## 相关文档
- [TryBuildBuiltinPassResourceBindingPlan](TryBuildBuiltinPassResourceBindingPlan.md)
- [BuiltinObjectIdPass](../Passes/BuiltinObjectIdPass/BuiltinObjectIdPass.md)
- [RenderMaterialUtility](RenderMaterialUtility.md)

View File

@@ -0,0 +1,31 @@
# BuiltinMaterialPass
**命名空间**: `XCEngine::Rendering`
**类型**: `enum class`
**头文件**: `XCEngine/Rendering/RenderMaterialUtility.h`
## 枚举值
| 枚举值 | 说明 |
|------|------|
| `ForwardLit` | 默认前向受光通道。 |
| `Unlit` | 非受光通道。 |
| `DepthOnly` | depth-only 通道。 |
| `ShadowCaster` | 阴影投射通道。 |
| `ObjectId` | object-id 输出通道。 |
| `Forward` | `ForwardLit` 的别名。 |
## 当前语义
- [MatchesBuiltinPass](MatchesBuiltinPass.md) 用它表达材质最终应进入的 builtin path。
- [BuiltinForwardPipeline](../Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md) 当前只消费 `ForwardLit``Unlit`
- [BuiltinObjectIdPass](../Passes/BuiltinObjectIdPass/BuiltinObjectIdPass.md) 当前消费 `ObjectId`
## 相关文档
- [MatchesBuiltinPass](MatchesBuiltinPass.md)
- [MatchesBuiltinPassName](MatchesBuiltinPassName.md)
- [ShaderPassMatchesBuiltinPass](ShaderPassMatchesBuiltinPass.md)
- [RenderMaterialUtility](RenderMaterialUtility.md)

View File

@@ -0,0 +1,26 @@
# BuiltinPassResourceBindingDesc
**命名空间**: `XCEngine::Rendering`
**类型**: `struct`
**头文件**: `XCEngine/Rendering/RenderMaterialUtility.h`
## 字段
| 字段 | 类型 | 说明 |
|------|------|------|
| `semantic` | [BuiltinPassResourceSemantic](BuiltinPassResourceSemantic.md) | 这条绑定对应的 builtin 语义。 |
| `resourceType` | `Resources::ShaderResourceType` | shader 声明的资源类型。 |
| `location` | [PassResourceBindingLocation](PassResourceBindingLocation.md) | 最终 `set/binding` 槽位。 |
## 当前语义
- 这是把原始 `ShaderResourceBindingDesc` 归一化之后的描述形式。
- [TryBuildBuiltinPassResourceBindingPlan](TryBuildBuiltinPassResourceBindingPlan.md) 会按输入顺序构造它们。
## 相关文档
- [BuiltinPassResourceBindingPlan](BuiltinPassResourceBindingPlan.md)
- [TryBuildBuiltinPassResourceBindingPlan](TryBuildBuiltinPassResourceBindingPlan.md)
- [ResolveBuiltinPassResourceSemantic](ResolveBuiltinPassResourceSemantic.md)

View File

@@ -0,0 +1,39 @@
# BuiltinPassResourceBindingPlan
**命名空间**: `XCEngine::Rendering`
**类型**: `struct`
**头文件**: `XCEngine/Rendering/RenderMaterialUtility.h`
## 字段
| 字段 | 类型 | 说明 |
|------|------|------|
| `bindings` | `Containers::Array<BuiltinPassResourceBindingDesc>` | 归一化后的绑定列表。 |
| `maxSetIndex` | `Core::uint32` | 当前绑定里出现过的最大 set index。 |
| `firstDescriptorSet` | `Core::uint32` | 当前绑定里最小的 set index。 |
| `descriptorSetCount` | `Core::uint32` | 从最小 set 到最大 set 的连续区间长度。 |
| `usesConstantBuffers` | `bool` | 是否出现过 constant buffer。 |
| `usesTextures` | `bool` | 是否出现过纹理。 |
| `usesSamplers` | `bool` | 是否出现过 sampler。 |
| `perObject` | [PassResourceBindingLocation](PassResourceBindingLocation.md) | `PerObject` 的槽位。 |
| `material` | [PassResourceBindingLocation](PassResourceBindingLocation.md) | `Material` 的槽位。 |
| `baseColorTexture` | [PassResourceBindingLocation](PassResourceBindingLocation.md) | `BaseColorTexture` 的槽位。 |
| `linearClampSampler` | [PassResourceBindingLocation](PassResourceBindingLocation.md) | `LinearClampSampler` 的槽位。 |
## `FindBinding()` 语义
- 顺序扫描 `bindings`,返回首个匹配目标语义的条目。
- 当前每种 builtin 语义至多允许出现一次若重复binding-plan 构建会失败。
## 当前使用位置
- [BuiltinForwardPipeline](../Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md) 会先拿到这份 plan再继续创建 pass layout 和 descriptor set。
- [BuiltinObjectIdPass](../Passes/BuiltinObjectIdPass/BuiltinObjectIdPass.md) 也用同一份 plan 解析 object-id 的 `PerObject` 绑定。
## 相关文档
- [BuiltinPassResourceBindingDesc](BuiltinPassResourceBindingDesc.md)
- [TryBuildBuiltinPassResourceBindingPlan](TryBuildBuiltinPassResourceBindingPlan.md)
- [RenderMaterialUtility](RenderMaterialUtility.md)

View File

@@ -0,0 +1,28 @@
# BuiltinPassResourceSemantic
**命名空间**: `XCEngine::Rendering`
**类型**: `enum class`
**头文件**: `XCEngine/Rendering/RenderMaterialUtility.h`
## 枚举值
| 枚举值 | 说明 |
|------|------|
| `Unknown` | 当前 builtin 路径不识别的语义。 |
| `PerObject` | 逐物体 constant-buffer 语义。 |
| `Material` | 逐材质 constant-buffer 语义。 |
| `BaseColorTexture` | base-color 贴图语义。 |
| `LinearClampSampler` | 线性 clamp sampler 语义。 |
## 当前语义
- [ResolveBuiltinPassResourceSemantic](ResolveBuiltinPassResourceSemantic.md) 会把 shader resource binding 的 `semantic``name` 映射到这个枚举。
- [IsBuiltinPassResourceTypeCompatible](IsBuiltinPassResourceTypeCompatible.md) 负责校验它和 `ShaderResourceType` 的组合是否合法。
## 相关文档
- [ResolveBuiltinPassResourceSemantic](ResolveBuiltinPassResourceSemantic.md)
- [IsBuiltinPassResourceTypeCompatible](IsBuiltinPassResourceTypeCompatible.md)
- [BuiltinPassResourceBindingDesc](BuiltinPassResourceBindingDesc.md)

View File

@@ -0,0 +1,38 @@
# FindShaderPropertyBySemantic
**命名空间**: `XCEngine::Rendering`
**类型**: `function`
**头文件**: `XCEngine/Rendering/RenderMaterialUtility.h`
## 签名
```cpp
const Resources::ShaderPropertyDesc* FindShaderPropertyBySemantic(
const Resources::Material* material,
const Containers::String& semantic);
```
## 作用
在材质当前绑定的 shader property 列表中,按 semantic 查找匹配项。
## 当前实现行为
1. 如果 `material == nullptr``material->GetShader() == nullptr`,返回 `nullptr`
2. 对输入 `semantic``Trim().ToLower()` 归一化。
3. 顺序遍历 `material->GetShader()->GetProperties()`
4. 只要某个 property 的 `semantic` 归一化后相同,就返回该 property 指针。
5. 找不到则返回 `nullptr`
## 当前使用位置
- [ResolveBuiltinBaseColorFactor](ResolveBuiltinBaseColorFactor.md) 用它优先查找 `BaseColor` 语义。
- [ResolveBuiltinBaseColorTexture](ResolveBuiltinBaseColorTexture.md) 用它优先查找 `BaseColorTexture` 语义。
## 相关文档
- [ResolveBuiltinBaseColorFactor](ResolveBuiltinBaseColorFactor.md)
- [ResolveBuiltinBaseColorTexture](ResolveBuiltinBaseColorTexture.md)
- [NormalizeBuiltinPassMetadataValue](NormalizeBuiltinPassMetadataValue.md)

View File

@@ -0,0 +1,39 @@
# IsBuiltinPassResourceTypeCompatible
**命名空间**: `XCEngine::Rendering`
**类型**: `function`
**头文件**: `XCEngine/Rendering/RenderMaterialUtility.h`
## 签名
```cpp
bool IsBuiltinPassResourceTypeCompatible(
BuiltinPassResourceSemantic semantic,
Resources::ShaderResourceType type);
```
## 作用
判断 builtin 资源语义和 shader 资源类型的组合是否合法。
## 当前实现行为
| 语义 | 当前接受的类型 |
|------|------|
| `PerObject` | `ConstantBuffer` |
| `Material` | `ConstantBuffer` |
| `BaseColorTexture` | `Texture2D``TextureCube` |
| `LinearClampSampler` | `Sampler` |
| `Unknown` | 一律不接受 |
## 当前使用位置
- [TryBuildBuiltinPassResourceBindingPlan](TryBuildBuiltinPassResourceBindingPlan.md) 会在构建 plan 时用它做第一轮类型校验。
## 相关文档
- [BuiltinPassResourceSemantic](BuiltinPassResourceSemantic.md)
- [ResolveBuiltinPassResourceSemantic](ResolveBuiltinPassResourceSemantic.md)
- [TryBuildBuiltinPassResourceBindingPlan](TryBuildBuiltinPassResourceBindingPlan.md)

View File

@@ -0,0 +1,33 @@
# IsDepthOnlyPassName
**命名空间**: `XCEngine::Rendering`
**类型**: `function`
**头文件**: `XCEngine/Rendering/RenderMaterialUtility.h`
## 签名
```cpp
bool IsDepthOnlyPassName(const Containers::String& value);
```
## 作用
判断一个字符串在当前规则下是否可视为 builtin depth-only pass 名称。
## 当前实现行为
- 先调用 [NormalizeBuiltinPassMetadataValue](NormalizeBuiltinPassMetadataValue.md)。
- 当前接受:
- `depthonly`
- `depth`
## 当前使用位置
- [MatchesBuiltinPassName](MatchesBuiltinPassName.md) 在目标 pass 为 `DepthOnly` 时转发到这里。
## 相关文档
- [MatchesBuiltinPassName](MatchesBuiltinPassName.md)
- [BuiltinMaterialPass](BuiltinMaterialPass.md)

View File

@@ -0,0 +1,36 @@
# IsForwardPassName
**命名空间**: `XCEngine::Rendering`
**类型**: `function`
**头文件**: `XCEngine/Rendering/RenderMaterialUtility.h`
## 签名
```cpp
bool IsForwardPassName(const Containers::String& value);
```
## 作用
判断一个字符串在当前规则下是否可视为 builtin forward pass 名称。
## 当前实现行为
- 先调用 [NormalizeBuiltinPassMetadataValue](NormalizeBuiltinPassMetadataValue.md)。
- 当前接受:
- 空串
- `forward`
- `forwardbase`
- `forwardlit`
- `forwardonly`
## 当前使用位置
- [MatchesBuiltinPassName](MatchesBuiltinPassName.md) 在目标 pass 为 `ForwardLit` 时转发到这里。
## 相关文档
- [MatchesBuiltinPassName](MatchesBuiltinPassName.md)
- [BuiltinMaterialPass](BuiltinMaterialPass.md)

View File

@@ -0,0 +1,35 @@
# IsObjectIdPassName
**命名空间**: `XCEngine::Rendering`
**类型**: `function`
**头文件**: `XCEngine/Rendering/RenderMaterialUtility.h`
## 签名
```cpp
bool IsObjectIdPassName(const Containers::String& value);
```
## 作用
判断一个字符串在当前规则下是否可视为 builtin object-id pass 名称。
## 当前实现行为
- 当前会对输入做 `Trim().ToLower()`
- 接受:
- `objectid`
- `editorobjectid`
## 当前使用位置
- [MatchesBuiltinPassName](MatchesBuiltinPassName.md) 在目标 pass 为 `ObjectId` 时转发到这里。
- [BuiltinObjectIdPass](../Passes/BuiltinObjectIdPass/BuiltinObjectIdPass.md) 的 shader pass 选择语义与这里保持一致。
## 相关文档
- [MatchesBuiltinPassName](MatchesBuiltinPassName.md)
- [BuiltinMaterialPass](BuiltinMaterialPass.md)
- [BuiltinObjectIdPass](../Passes/BuiltinObjectIdPass/BuiltinObjectIdPass.md)

View File

@@ -0,0 +1,33 @@
# IsShadowCasterPassName
**命名空间**: `XCEngine::Rendering`
**类型**: `function`
**头文件**: `XCEngine/Rendering/RenderMaterialUtility.h`
## 签名
```cpp
bool IsShadowCasterPassName(const Containers::String& value);
```
## 作用
判断一个字符串在当前规则下是否可视为 builtin shadow-caster pass 名称。
## 当前实现行为
- 先调用 [NormalizeBuiltinPassMetadataValue](NormalizeBuiltinPassMetadataValue.md)。
- 当前接受:
- `shadowcaster`
- `shadow`
## 当前使用位置
- [MatchesBuiltinPassName](MatchesBuiltinPassName.md) 在目标 pass 为 `ShadowCaster` 时转发到这里。
## 相关文档
- [MatchesBuiltinPassName](MatchesBuiltinPassName.md)
- [BuiltinMaterialPass](BuiltinMaterialPass.md)

View File

@@ -0,0 +1,34 @@
# IsUnlitPassName
**命名空间**: `XCEngine::Rendering`
**类型**: `function`
**头文件**: `XCEngine/Rendering/RenderMaterialUtility.h`
## 签名
```cpp
bool IsUnlitPassName(const Containers::String& value);
```
## 作用
判断一个字符串在当前规则下是否可视为 builtin unlit pass 名称。
## 当前实现行为
- 先调用 [NormalizeBuiltinPassMetadataValue](NormalizeBuiltinPassMetadataValue.md)。
- 当前接受:
- `unlit`
- `forwardunlit`
- `srpdefaultunlit`
## 当前使用位置
- [MatchesBuiltinPassName](MatchesBuiltinPassName.md) 在目标 pass 为 `Unlit` 时转发到这里。
## 相关文档
- [MatchesBuiltinPassName](MatchesBuiltinPassName.md)
- [BuiltinMaterialPass](BuiltinMaterialPass.md)

View File

@@ -0,0 +1,43 @@
# MatchesBuiltinPassName
**命名空间**: `XCEngine::Rendering`
**类型**: `function`
**头文件**: `XCEngine/Rendering/RenderMaterialUtility.h`
## 签名
```cpp
bool MatchesBuiltinPassName(
const Containers::String& value,
BuiltinMaterialPass pass);
```
## 作用
判断一段字符串在当前规则下是否匹配目标 builtin pass。
## 当前实现行为
- 所有输入都会先经过 [NormalizeBuiltinPassMetadataValue](NormalizeBuiltinPassMetadataValue.md)。
- 然后按 `pass` 分派到对应别名集合:
| 目标 pass | 当前接受的名称 |
|------|------|
| `ForwardLit` | 空串、`forward``forwardbase``forwardlit``forwardonly` |
| `Unlit` | `unlit``forwardunlit``srpdefaultunlit` |
| `DepthOnly` | `depthonly``depth` |
| `ShadowCaster` | `shadowcaster``shadow` |
| `ObjectId` | `objectid``editorobjectid` |
## 当前使用位置
- [MatchesBuiltinPass](MatchesBuiltinPass.md) 用它匹配材质级 `shaderPass` / `LightMode`
- [ShaderPassMatchesBuiltinPass](ShaderPassMatchesBuiltinPass.md) 用它匹配 shader pass 名称和 tag。
## 相关文档
- [BuiltinMaterialPass](BuiltinMaterialPass.md)
- [MatchesBuiltinPass](MatchesBuiltinPass.md)
- [ShaderPassMatchesBuiltinPass](ShaderPassMatchesBuiltinPass.md)

View File

@@ -0,0 +1,30 @@
# MaterialConstantLayoutView
**命名空间**: `XCEngine::Rendering`
**类型**: `struct`
**头文件**: `XCEngine/Rendering/RenderMaterialUtility.h`
## 字段
| 字段 | 类型 | 说明 |
|------|------|------|
| `fields` | `const Resources::MaterialConstantFieldDesc*` | 指向字段描述数组首地址。 |
| `count` | `size_t` | 当前字段数量。 |
| `size` | `size_t` | 整个常量缓冲的总字节数。 |
## `IsValid()` 语义
- 只有 `fields != nullptr && count > 0 && size > 0` 时返回 `true`
## 当前语义
- 这是对 `Material::GetConstantLayout()` 的非 owning 视图。
- [MaterialConstantPayloadView](MaterialConstantPayloadView.md) 会把它和 payload 字节一起打包返回。
## 相关文档
- [MaterialConstantPayloadView](MaterialConstantPayloadView.md)
- [ResolveSchemaMaterialConstantPayload](ResolveSchemaMaterialConstantPayload.md)
- [RenderMaterialUtility](RenderMaterialUtility.md)

View File

@@ -6,7 +6,7 @@
**头文件**: `XCEngine/Rendering/RenderMaterialUtility.h`
**描述**: 指向 schema-driven 材质常量缓冲字节的非 owning 视图,用于把 `Material::GetConstantBufferData()` 直接写入渲染 descriptor set。
**描述**: 指向 schema-driven 材质常量缓冲字节及其布局的非 owning 视图,用于把 `Material::GetConstantBufferData()` 直接写入渲染 descriptor set。
## 概述
@@ -23,28 +23,34 @@ constant buffer 的 set 上调用 `WriteConstant(binding, data, size)` 写入 de
|------|------|------|
| `data` | `const void*` | 指向常量缓冲字节首地址。 |
| `size` | `size_t` | 当前 payload 字节数。 |
| `layout` | [MaterialConstantLayoutView](MaterialConstantLayoutView.md) | 与这段 payload 对应的字段布局视图。 |
## `IsValid()` 语义
- 当前判定条件是 `data != nullptr && size > 0`
- `Material` 没有 shader、没有生成常量缓冲或常量缓冲为空时resolver 会返回无效 view。
- 当前判定条件是
- `data != nullptr`
- `size > 0`
- `layout.IsValid()`
- `layout.size == size`
- `Material` 没有 shader、没有生成常量布局、没有生成常量缓冲或布局大小和 payload 大小不一致时resolver 都会返回无效 view。
- 无效 view 本身不是错误;当前 `BuiltinForwardPipeline` 会在这种情况下回退到 `BuiltinForwardMaterialData`
## 所有权与生命周期
- 它不拥有 `data` 指向的内存。
- 当前 view 指向 `Material::GetConstantBufferData()` 的内部数组;`Material` 销毁或常量缓冲重建后,旧 view 不再可靠。
- 当前 view 指向 `Material::GetConstantBufferData()``Material::GetConstantLayout()` 的内部数组;`Material` 销毁或常量缓冲 / 布局重建后,旧 view 不再可靠。
- 调用方应把它当成“本次绘制阶段即时消费”的借用数据,而不是长期缓存的稳定块。
## 测试覆盖
`tests/Rendering/unit/test_render_scene_extractor.cpp` 当前验证了:
`Material` 绑定 shader 并生成 `_BaseColor` 常量时,
[ResolveSchemaMaterialConstantPayload](ResolveSchemaMaterialConstantPayload.md) 会返回有效的 `16` 字节 payload view。
[ResolveSchemaMaterialConstantPayload](ResolveSchemaMaterialConstantPayload.md) 会返回有效 layout `16` 字节 payload view。
## 相关文档
- [ResolveSchemaMaterialConstantPayload](ResolveSchemaMaterialConstantPayload.md)
- [MaterialConstantLayoutView](MaterialConstantLayoutView.md)
- [BuiltinForwardMaterialData](BuiltinForwardMaterialData.md)
- [BuiltinForwardPipeline](../Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md)
- [RenderMaterialUtility](RenderMaterialUtility.md)

View File

@@ -0,0 +1,41 @@
# MaterialRenderStateHash
**命名空间**: `XCEngine::Rendering`
**类型**: `functor struct`
**头文件**: `XCEngine/Rendering/RenderMaterialUtility.h`
## 作用
`Resources::MaterialRenderState` 提供哈希函数,供 `unordered_map` 等哈希容器复用。
## 当前实现行为
- 以一个固定初值开始组合哈希。
- 依次纳入这些字段:
- `blendEnable`
- `srcBlend`
- `dstBlend`
- `srcBlendAlpha`
- `dstBlendAlpha`
- `blendOp`
- `blendOpAlpha`
- `colorWriteMask`
- `depthTestEnable`
- `depthWriteEnable`
- `depthFunc`
- `cullMode`
## 当前使用位置
- [BuiltinForwardPipeline](../Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md) 的 `PipelineStateKeyHash` 会复用这份哈希结果来缓存 pipeline state。
## 当前边界
- 这只是哈希 functor不负责判等判等仍依赖 `MaterialRenderState` 自身的 `operator==` 语义。
## 相关文档
- [RenderMaterialUtility](RenderMaterialUtility.md)
- [BuiltinForwardPipeline](../Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md)

View File

@@ -0,0 +1,34 @@
# NormalizeBuiltinPassMetadataValue
**命名空间**: `XCEngine::Rendering`
**类型**: `function`
**头文件**: `XCEngine/Rendering/RenderMaterialUtility.h`
## 签名
```cpp
Containers::String NormalizeBuiltinPassMetadataValue(const Containers::String& value);
```
## 作用
统一 builtin pass 元数据比较前的字符串归一化规则。
## 当前实现行为
-`Trim()` 去掉首尾空白。
-`ToLower()` 做大小写归一化。
## 当前使用位置
- [MatchesBuiltinPassName](MatchesBuiltinPassName.md) 用它统一比较 pass 名称与 `LightMode`
- [ResolveBuiltinPassResourceSemantic](ResolveBuiltinPassResourceSemantic.md) 用它比较 `semantic` / `name` 别名。
- [FindShaderPropertyBySemantic](FindShaderPropertyBySemantic.md) 也依赖同一规则。
## 相关文档
- [MatchesBuiltinPassName](MatchesBuiltinPassName.md)
- [ResolveBuiltinPassResourceSemantic](ResolveBuiltinPassResourceSemantic.md)
- [FindShaderPropertyBySemantic](FindShaderPropertyBySemantic.md)

View File

@@ -0,0 +1,30 @@
# PassResourceBindingLocation
**命名空间**: `XCEngine::Rendering`
**类型**: `struct`
**头文件**: `XCEngine/Rendering/RenderMaterialUtility.h`
## 字段
| 字段 | 类型 | 说明 |
|------|------|------|
| `set` | `Core::uint32` | descriptor set 索引。 |
| `binding` | `Core::uint32` | set 内 binding 索引。 |
## `IsValid()` 语义
- 只有 `set != UINT32_MAX && binding != UINT32_MAX` 时返回 `true`
- 默认值表示“尚未绑定 / 不存在这个语义槽位”。
## 当前使用位置
- [BuiltinPassResourceBindingDesc](BuiltinPassResourceBindingDesc.md) 用它记录单条 builtin 资源绑定。
- [BuiltinPassResourceBindingPlan](BuiltinPassResourceBindingPlan.md) 用它暴露 `PerObject``Material``BaseColorTexture``LinearClampSampler` 的最终槽位。
## 相关文档
- [BuiltinPassResourceBindingDesc](BuiltinPassResourceBindingDesc.md)
- [BuiltinPassResourceBindingPlan](BuiltinPassResourceBindingPlan.md)
- [TryBuildBuiltinPassResourceBindingPlan](TryBuildBuiltinPassResourceBindingPlan.md)

View File

@@ -33,6 +33,37 @@
| `ObjectId` | object-id 输出通道。 |
| `Forward` | `ForwardLit` 的别名。 |
## builtin pass 元数据与资源绑定契约
当前这份头文件除了材质解析 helper还公开了一组“shader pass 如何映射到 builtin path、资源声明如何落成 descriptor-set 计划”的契约类型:
- [PassResourceBindingLocation](PassResourceBindingLocation.md)
统一表示一个 `set/binding` 槽位。
- [BuiltinPassResourceSemantic](BuiltinPassResourceSemantic.md)
把 shader 资源语义收口成 builtin forward / object-id 当前识别的白名单枚举。
- [BuiltinPassResourceBindingDesc](BuiltinPassResourceBindingDesc.md)
记录单个 builtin 语义、资源类型与绑定位置。
- [BuiltinPassResourceBindingPlan](BuiltinPassResourceBindingPlan.md)
`BuiltinForwardPipeline` / `BuiltinObjectIdPass` 当前真正消费的 binding-plan 结果。
与这些类型配套的 helper 包括:
- [IsForwardPassName](IsForwardPassName.md)
- [IsUnlitPassName](IsUnlitPassName.md)
- [IsDepthOnlyPassName](IsDepthOnlyPassName.md)
- [IsShadowCasterPassName](IsShadowCasterPassName.md)
- [IsObjectIdPassName](IsObjectIdPassName.md)
- [MatchesBuiltinPassName](MatchesBuiltinPassName.md)
- [ShaderPassHasExplicitBuiltinMetadata](ShaderPassHasExplicitBuiltinMetadata.md)
- [ShaderPassMatchesBuiltinPass](ShaderPassMatchesBuiltinPass.md)
- [ResolveBuiltinPassResourceSemantic](ResolveBuiltinPassResourceSemantic.md)
- [BuildLegacyBuiltinForwardPassResourceBindings](BuildLegacyBuiltinForwardPassResourceBindings.md)
- [BuildLegacyBuiltinObjectIdPassResourceBindings](BuildLegacyBuiltinObjectIdPassResourceBindings.md)
- [IsBuiltinPassResourceTypeCompatible](IsBuiltinPassResourceTypeCompatible.md)
- [TryBuildBuiltinPassResourceBindingPlan](TryBuildBuiltinPassResourceBindingPlan.md)
这组页面对应的是当前 builtin pipeline 的真实入口shader pass 可以显式声明 `resources`;如果没声明,再退到 legacy fallback 绑定;最终都要先落成统一的 binding plan后续 pass-layout / descriptor-set / pipeline-state 才能继续创建。
## 当前 pass 匹配策略
[MatchesBuiltinPass](MatchesBuiltinPass.md) 的判断顺序是:
@@ -52,12 +83,13 @@
## 逐材质常量契约
同一个头文件里当前公开了两类逐材质数据:
同一个头文件里当前公开了两类逐材质数据和一份布局视图
| 类型 | 说明 |
|------|------|
| [BuiltinForwardMaterialData](BuiltinForwardMaterialData.md) | builtin forward 的兼容 fallback 常量结构,当前只收口 `baseColorFactor`。 |
| [MaterialConstantPayloadView](MaterialConstantPayloadView.md) | 指向 `Material::GetConstantBufferData()` 的非 owning 字节视图。 |
| [MaterialConstantLayoutView](MaterialConstantLayoutView.md) | 指向 `Material::GetConstantLayout()` 的非 owning 布局视图。 |
| [MaterialConstantPayloadView](MaterialConstantPayloadView.md) | 指向 `Material::GetConstantBufferData()` 及其布局的非 owning 视图。 |
对应 helper 的当前职责是:
@@ -68,7 +100,7 @@
- [BuildBuiltinForwardMaterialData](BuildBuiltinForwardMaterialData.md)
构造 builtin forward 的兼容 fallback 常量。
- [ResolveSchemaMaterialConstantPayload](ResolveSchemaMaterialConstantPayload.md)
直接暴露当前 `Material` 已按 shader schema 生成的常量缓冲字节视图。
直接暴露当前 `Material` 已按 shader schema 生成的常量缓冲 payload 与布局视图。
`BuiltinForwardPipeline` 当前会优先用 [ResolveSchemaMaterialConstantPayload](ResolveSchemaMaterialConstantPayload.md)
`Material::GetConstantBufferData()` 写入 `Material` 语义的 constant buffer 绑定;只有拿不到有效 payload 时,
@@ -101,13 +133,35 @@
| 类型 | 说明 |
|------|------|
| [BuiltinMaterialPass](BuiltinMaterialPass.md) | builtin 渲染通道枚举。 |
| [PassResourceBindingLocation](PassResourceBindingLocation.md) | 一个 `set/binding` 位置。 |
| [BuiltinPassResourceSemantic](BuiltinPassResourceSemantic.md) | builtin pass 识别的资源语义白名单。 |
| [BuiltinPassResourceBindingDesc](BuiltinPassResourceBindingDesc.md) | 单个资源绑定条目的语义化描述。 |
| [BuiltinPassResourceBindingPlan](BuiltinPassResourceBindingPlan.md) | builtin pipeline 消费的绑定计划。 |
| [BuiltinForwardMaterialData](BuiltinForwardMaterialData.md) | builtin forward 的兼容 fallback 常量结构。 |
| [MaterialConstantLayoutView](MaterialConstantLayoutView.md) | schema-driven 常量布局视图。 |
| [MaterialConstantPayloadView](MaterialConstantPayloadView.md) | schema-driven 逐材质常量 payload 的借用视图。 |
| [MaterialRenderStateHash](MaterialRenderStateHash.md) | `MaterialRenderState` 的哈希 functor。 |
## 公开函数
| 函数 | 说明 |
|------|------|
| [NormalizeBuiltinPassMetadataValue](NormalizeBuiltinPassMetadataValue.md) | 统一 builtin pass 元数据的归一化规则。 |
| [IsForwardPassName](IsForwardPassName.md) | 判断名称是否匹配 forward pass。 |
| [IsUnlitPassName](IsUnlitPassName.md) | 判断名称是否匹配 unlit pass。 |
| [IsDepthOnlyPassName](IsDepthOnlyPassName.md) | 判断名称是否匹配 depth-only pass。 |
| [IsShadowCasterPassName](IsShadowCasterPassName.md) | 判断名称是否匹配 shadow-caster pass。 |
| [IsObjectIdPassName](IsObjectIdPassName.md) | 判断名称是否匹配 object-id pass。 |
| [MatchesBuiltinPassName](MatchesBuiltinPassName.md) | 判断字符串是否匹配某个 builtin pass。 |
| [ShaderPassHasExplicitBuiltinMetadata](ShaderPassHasExplicitBuiltinMetadata.md) | 判断 shader pass 是否显式声明了 builtin 元数据。 |
| [ShaderPassMatchesBuiltinPass](ShaderPassMatchesBuiltinPass.md) | 判断 shader pass 是否匹配某个 builtin pass。 |
| [ResolveBuiltinPassResourceSemantic](ResolveBuiltinPassResourceSemantic.md) | 把 shader resource binding 解析成 builtin 语义。 |
| [BuildLegacyBuiltinForwardPassResourceBindings](BuildLegacyBuiltinForwardPassResourceBindings.md) | 构造 forward 路径的 legacy fallback 绑定列表。 |
| [BuildLegacyBuiltinObjectIdPassResourceBindings](BuildLegacyBuiltinObjectIdPassResourceBindings.md) | 构造 object-id 路径的 legacy fallback 绑定列表。 |
| [IsBuiltinPassResourceTypeCompatible](IsBuiltinPassResourceTypeCompatible.md) | 判断 builtin 语义和 shader 资源类型是否兼容。 |
| [TryBuildBuiltinPassResourceBindingPlan](TryBuildBuiltinPassResourceBindingPlan.md) | 把 shader 资源绑定解析成统一 binding plan。 |
| [FindShaderPropertyBySemantic](FindShaderPropertyBySemantic.md) | 按 semantic 查找 shader property。 |
| [ResolveMaterial](ResolveMaterial.md) | 解析当前可见物体最终应使用的材质。 |
| [ResolveMaterialRenderQueue](ResolveMaterialRenderQueue.md) | 读取材质 render queue空材质时回退到 `Geometry`。 |
| [IsTransparentRenderQueue](IsTransparentRenderQueue.md) | 判断 queue 是否处于透明区间。 |
@@ -119,6 +173,10 @@
| [BuildRasterizerState](BuildRasterizerState.md) | 构建栅格化状态。 |
| [BuildBlendState](BuildBlendState.md) | 构建混合状态。 |
| [BuildDepthStencilState](BuildDepthStencilState.md) | 构建深度状态。 |
| [ToRHICullMode](ToRHICullMode.md) | 把材质剔除模式映射到 RHI。 |
| [ToRHIComparisonFunc](ToRHIComparisonFunc.md) | 把材质比较函数映射到 RHI。 |
| [ToRHIBlendFactor](ToRHIBlendFactor.md) | 把材质混合因子映射到 RHI。 |
| [ToRHIBlendOp](ToRHIBlendOp.md) | 把材质混合操作映射到 RHI。 |
| [ApplyMaterialRenderState](ApplyMaterialRenderState.md) | 一次性写入图形管线状态。 |
## 相关文档

View File

@@ -0,0 +1,44 @@
# ResolveBuiltinPassResourceSemantic
**命名空间**: `XCEngine::Rendering`
**类型**: `function`
**头文件**: `XCEngine/Rendering/RenderMaterialUtility.h`
## 签名
```cpp
BuiltinPassResourceSemantic ResolveBuiltinPassResourceSemantic(
const Resources::ShaderResourceBindingDesc& binding);
```
## 作用
把 shader 资源绑定描述映射成当前 builtin pipeline 识别的语义枚举。
## 当前实现行为
1. 优先读取 `binding.semantic`
2. 如果 `semantic` 为空,再回退到 `binding.name`
3. 统一做 `Trim().ToLower()`
4. 按下表映射:
| 输入值 | 输出语义 |
|------|------|
| `perobject` / `perobjectconstants` | `PerObject` |
| `material` / `materialconstants` | `Material` |
| `basecolortexture` / `maintex` | `BaseColorTexture` |
| `linearclampsampler` | `LinearClampSampler` |
| 其它值 | `Unknown` |
## 当前语义
- 这一步只做“名字到 builtin 语义”的映射,不检查资源类型是否合法。
- 类型兼容性校验由 [IsBuiltinPassResourceTypeCompatible](IsBuiltinPassResourceTypeCompatible.md) 负责。
## 相关文档
- [BuiltinPassResourceSemantic](BuiltinPassResourceSemantic.md)
- [IsBuiltinPassResourceTypeCompatible](IsBuiltinPassResourceTypeCompatible.md)
- [TryBuildBuiltinPassResourceBindingPlan](TryBuildBuiltinPassResourceBindingPlan.md)

View File

@@ -14,7 +14,7 @@ MaterialConstantPayloadView ResolveSchemaMaterialConstantPayload(const Resources
## 作用
返回当前 `Material` 已按 shader schema 生成的逐材质 constant-buffer payload 视图。
返回当前 `Material` 已按 shader schema 生成的逐材质 constant-buffer payload 与布局视图。
## 当前实现行为
@@ -22,13 +22,27 @@ MaterialConstantPayloadView ResolveSchemaMaterialConstantPayload(const Resources
1. 如果 `material == nullptr`,返回无效 view。
2. 如果 `material->GetShader() == nullptr`,返回无效 view。
3. 读取 `material->GetConstantBufferData()`
4. 如果常量缓冲为空,返回无效 view。
5. 否则返回 `{ constantBufferData.Data(), constantBufferData.Size() }`
3. 读取 `material->GetConstantLayout()``material->GetConstantBufferData()`
4. 只要布局数组或常量缓冲数组任一为空,返回无效 view。
5. 否则先构造:
```cpp
MaterialConstantLayoutView layoutView = {};
layoutView.fields = constantLayout.Data();
layoutView.count = constantLayout.Size();
layoutView.size = constantBufferData.Size();
```
6. 最终返回:
```cpp
{ constantBufferData.Data(), constantBufferData.Size(), layoutView }
```
## 当前语义要点
- 这条 helper 不做重新打包,也不推断 fallback 字段;它只暴露 `Material` 当前已经准备好的字节块。
- 返回值里的 `layout` 直接借用 `Material::GetConstantLayout()`,不会复制字段描述。
- 返回值是借用视图,不拥有 `Material` 内部数组。
- 它只处理 `Material` constant buffer payload不解析纹理、采样器或 render state。
@@ -48,6 +62,7 @@ MaterialConstantPayloadView ResolveSchemaMaterialConstantPayload(const Resources
## 相关文档
- [MaterialConstantPayloadView](MaterialConstantPayloadView.md)
- [MaterialConstantLayoutView](MaterialConstantLayoutView.md)
- [BuildBuiltinForwardMaterialData](BuildBuiltinForwardMaterialData.md)
- [BuiltinForwardMaterialData](BuiltinForwardMaterialData.md)
- [BuiltinForwardPipeline](../Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md)

View File

@@ -0,0 +1,37 @@
# ShaderPassHasExplicitBuiltinMetadata
**命名空间**: `XCEngine::Rendering`
**类型**: `function`
**头文件**: `XCEngine/Rendering/RenderMaterialUtility.h`
## 签名
```cpp
bool ShaderPassHasExplicitBuiltinMetadata(const Resources::ShaderPass& shaderPass);
```
## 作用
判断一个 `ShaderPass` 是否显式声明了 builtin pass 元数据。
## 当前实现行为
满足以下任一条件就返回 `true`
- `shaderPass.name` 非空且不等于 `Default`
- `shaderPass.tags` 里存在名字为 `LightMode` 的 tag
否则返回 `false`
## 当前语义
- 这条 helper 的主要作用是区分“显式声明了其它 pass”与“完全没有元数据应继续走 `ForwardLit` 默认回退”。
- [MatchesBuiltinPass](MatchesBuiltinPass.md) 会在 shader 级遍历失败后用它决定是否关闭隐式 forward fallback。
## 相关文档
- [ShaderPassMatchesBuiltinPass](ShaderPassMatchesBuiltinPass.md)
- [MatchesBuiltinPass](MatchesBuiltinPass.md)
- [RenderMaterialUtility](RenderMaterialUtility.md)

View File

@@ -0,0 +1,37 @@
# ShaderPassMatchesBuiltinPass
**命名空间**: `XCEngine::Rendering`
**类型**: `function`
**头文件**: `XCEngine/Rendering/RenderMaterialUtility.h`
## 签名
```cpp
bool ShaderPassMatchesBuiltinPass(
const Resources::ShaderPass& shaderPass,
BuiltinMaterialPass pass);
```
## 作用
判断一个 shader pass 的显式元数据是否匹配目标 builtin pass。
## 当前实现行为
1. 如果 `shaderPass.name` 非空且不等于 `Default`,就把它当成显式元数据,并要求它必须匹配目标 pass。
2. 再遍历 `shaderPass.tags`;对每个名字为 `LightMode` 的 tag同样要求其值必须匹配目标 pass。
3. 只要出现过至少一处显式 metadata 且全部匹配,返回 `true`
4. 如果完全没有显式 metadata则返回 `false`
## 当前语义
- 这条 helper 不提供“没有 metadata 时默认 ForwardLit”的兜底那个兜底属于 [MatchesBuiltinPass](MatchesBuiltinPass.md) 的更高层策略。
- 名称和 `LightMode` 同时存在时,两者都必须匹配同一个目标 pass。
## 相关文档
- [MatchesBuiltinPassName](MatchesBuiltinPassName.md)
- [ShaderPassHasExplicitBuiltinMetadata](ShaderPassHasExplicitBuiltinMetadata.md)
- [MatchesBuiltinPass](MatchesBuiltinPass.md)

View File

@@ -0,0 +1,31 @@
# ToRHIBlendFactor
**命名空间**: `XCEngine::Rendering`
**类型**: `function`
**头文件**: `XCEngine/Rendering/RenderMaterialUtility.h`
## 签名
```cpp
RHI::BlendFactor ToRHIBlendFactor(Resources::MaterialBlendFactor factor);
```
## 作用
把材质层的 `MaterialBlendFactor` 映射成 RHI 层的 `BlendFactor`
## 当前实现行为
- `Zero``SrcColor``InvSrcColor``SrcAlpha``InvSrcAlpha``DstAlpha``InvDstAlpha``DstColor``InvDstColor``SrcAlphaSat``BlendFactor``InvBlendFactor``Src1Color``InvSrc1Color``Src1Alpha``InvSrc1Alpha` 都映射到同名 RHI 枚举。
- `One` 和默认回退到 `RHI::BlendFactor::One`
## 当前使用位置
- [BuildBlendState](BuildBlendState.md) 用它填充颜色和 alpha 混合因子。
## 相关文档
- [BuildBlendState](BuildBlendState.md)
- [RenderMaterialUtility](RenderMaterialUtility.md)

View File

@@ -0,0 +1,36 @@
# ToRHIBlendOp
**命名空间**: `XCEngine::Rendering`
**类型**: `function`
**头文件**: `XCEngine/Rendering/RenderMaterialUtility.h`
## 签名
```cpp
RHI::BlendOp ToRHIBlendOp(Resources::MaterialBlendOp op);
```
## 作用
把材质层的 `MaterialBlendOp` 映射成 RHI 层的 `BlendOp`
## 当前实现行为
| 输入 | 输出 |
|------|------|
| `Subtract` | `RHI::BlendOp::Subtract` |
| `ReverseSubtract` | `RHI::BlendOp::ReverseSubtract` |
| `Min` | `RHI::BlendOp::Min` |
| `Max` | `RHI::BlendOp::Max` |
| `Add` / 默认 | `RHI::BlendOp::Add` |
## 当前使用位置
- [BuildBlendState](BuildBlendState.md) 用它填充颜色和 alpha 混合操作。
## 相关文档
- [BuildBlendState](BuildBlendState.md)
- [RenderMaterialUtility](RenderMaterialUtility.md)

View File

@@ -0,0 +1,31 @@
# ToRHIComparisonFunc
**命名空间**: `XCEngine::Rendering`
**类型**: `function`
**头文件**: `XCEngine/Rendering/RenderMaterialUtility.h`
## 签名
```cpp
RHI::ComparisonFunc ToRHIComparisonFunc(Resources::MaterialComparisonFunc func);
```
## 作用
把材质层的深度比较函数映射成 RHI 层的 `ComparisonFunc`
## 当前实现行为
- `Never``Equal``LessEqual``Greater``NotEqual``GreaterEqual``Always` 都映射到同名 RHI 枚举。
- `Less` 和默认回退到 `RHI::ComparisonFunc::Less`
## 当前使用位置
- [BuildDepthStencilState](BuildDepthStencilState.md) 用它写入 `DepthStencilStateDesc::depthFunc`
## 相关文档
- [BuildDepthStencilState](BuildDepthStencilState.md)
- [RenderMaterialUtility](RenderMaterialUtility.md)

View File

@@ -0,0 +1,35 @@
# ToRHICullMode
**命名空间**: `XCEngine::Rendering`
**类型**: `function`
**头文件**: `XCEngine/Rendering/RenderMaterialUtility.h`
## 签名
```cpp
RHI::CullMode ToRHICullMode(Resources::MaterialCullMode mode);
```
## 作用
把材质层的 `MaterialCullMode` 映射成 RHI 层的 `CullMode`
## 当前实现行为
| 输入 | 输出 |
|------|------|
| `Front` | `RHI::CullMode::Front` |
| `Back` | `RHI::CullMode::Back` |
| `None` | `RHI::CullMode::None` |
| 其它 / 默认 | `RHI::CullMode::None` |
## 当前使用位置
- [BuildRasterizerState](BuildRasterizerState.md) 用它写入 `RasterizerDesc::cullMode`
## 相关文档
- [BuildRasterizerState](BuildRasterizerState.md)
- [RenderMaterialUtility](RenderMaterialUtility.md)

View File

@@ -0,0 +1,63 @@
# TryBuildBuiltinPassResourceBindingPlan
**命名空间**: `XCEngine::Rendering`
**类型**: `function`
**头文件**: `XCEngine/Rendering/RenderMaterialUtility.h`
## 签名
```cpp
bool TryBuildBuiltinPassResourceBindingPlan(
const Containers::Array<Resources::ShaderResourceBindingDesc>& bindings,
BuiltinPassResourceBindingPlan& outPlan,
Containers::String* outError = nullptr);
```
## 作用
把 shader 资源绑定列表解析成 builtin pipeline 可直接消费的统一 binding plan。
## 当前实现行为
1. 先把 `outPlan` 重置为空。
2. 如果 `bindings.Empty()`,直接返回 `true`,保留空 plan。
3. 逐条绑定执行:
- 用 [ResolveBuiltinPassResourceSemantic](ResolveBuiltinPassResourceSemantic.md) 解析 builtin 语义
- 用 [IsBuiltinPassResourceTypeCompatible](IsBuiltinPassResourceTypeCompatible.md) 校验语义 / 类型组合
- 拒绝同一 builtin 语义重复出现
- 拒绝同一个 `set/binding` 对重复出现
- 记录 `bindings``usesConstantBuffers``usesTextures``usesSamplers`
- 更新 `perObject` / `material` / `baseColorTexture` / `linearClampSampler`
4. 最终计算:
- `firstDescriptorSet = 最小 set`
- `descriptorSetCount = 最大 set - 最小 set + 1`
## 失败条件
当前会返回 `false` 并在 `outError` 可用时写入错误字符串:
- 解析出 `Unknown` 语义
- 语义和 shader 资源类型不兼容
- 同一 builtin 语义出现多次
- 同一个 `set/binding` 对出现多次
## 当前边界
- 这里还不会检查“是否缺少 `PerObject`”或“同一 set 是否混用 sampler / 非 sampler”这些更靠后的布局规则属于 `BuiltinForwardPipeline` / `BuiltinObjectIdPass` 的后续阶段。
## 测试覆盖
`tests/Rendering/unit/test_builtin_forward_pipeline.cpp` 当前验证了:
- 显式 `ForwardLit` / `Unlit` shader 资源声明能正确落成 plan
- legacy forward fallback 绑定也能正确落成 plan
- legacy object-id fallback 绑定会得到只含 `PerObject` 的 plan
## 相关文档
- [BuiltinPassResourceBindingPlan](BuiltinPassResourceBindingPlan.md)
- [BuildLegacyBuiltinForwardPassResourceBindings](BuildLegacyBuiltinForwardPassResourceBindings.md)
- [BuildLegacyBuiltinObjectIdPassResourceBindings](BuildLegacyBuiltinObjectIdPassResourceBindings.md)
- [RenderMaterialUtility](RenderMaterialUtility.md)

View File

@@ -8,16 +8,19 @@ virtual ~RenderPipeline() = default;
## 当前语义
- 这是一个虚析构函数,保证通过 `RenderPipeline*` 删除派生对象时行为正确。
- 析构函数本身没有定义额外 shutdown 流程;资源释放语义仍应由 [Shutdown](Shutdown.md) 和派生类自己的析构实现共同承担
- 这是一个虚析构函数,保证通过 `RenderPipeline*` 删除具体 pipeline 时行为正确。
- 基类析构函数本身不会主动调用 [Shutdown](Shutdown.md)。
- 因此 GPU 资源释放策略由调用方和派生类共同决定:
- `CameraRenderer` 会在替换或销毁 pipeline 前显式调用 `Shutdown()`
- 某些派生类会在自己的析构函数里再次兜底,例如 builtin forward pipeline。
## 当前所有权模型
## 设计说明
按当前渲染主链路runtime pipeline 通常由 [CameraRenderer](../CameraRenderer/CameraRenderer.md) 以 `std::unique_ptr<RenderPipeline>` 独占持有
这也是为什么基类必须提供虚析构,而不是让调用方了解每个 concrete pipeline 的真实类型
-`Shutdown()` 与 C++ 析构分开,可以让调用方在对象仍然存活时就提前回收 GPU 资源,而不是把所有释放时机都拖到对象真正销毁的最后一刻
- 这也意味着“对象被 delete”并不天然等价于“已经执行过规范的渲染资源 shutdown 路径”
## 相关文档
- [返回类型总览](RenderPipeline.md)
- [RenderPipeline::Shutdown](Shutdown.md)
- [BuiltinForwardPipeline](../Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md)
- [RenderPipeline](RenderPipeline.md)
- [Shutdown](Shutdown.md)
- [Initialize](Initialize.md)

View File

@@ -20,6 +20,7 @@ virtual bool Render(
它不负责:
- 多相机 request 规划与排序
- shadow-caster / depth-only scene pass
- object-id pass
- `preScenePasses` / `postScenePasses` / `overlayPasses` 编排
@@ -30,10 +31,12 @@ virtual bool Render(
`engine/src/Rendering/CameraRenderer.cpp`,当前主链路顺序是:
1. `preScenePasses`
2. `m_pipeline->Render(...)`
3. `ObjectIdPass`
4. `postScenePasses`
5. `overlayPasses`
2. `shadowCaster`
3. `depthOnly`
4. `m_pipeline->Render(...)`
5. `ObjectIdPass`
6. `postScenePasses`
7. `overlayPasses`
因此这里代表的是“主场景绘制槽位”,不是整次相机提交的全部流程。

View File

@@ -35,6 +35,7 @@
`RenderPipeline` 只负责主场景绘制本身,不负责:
- 多相机 request 规划和排序
- shadow-caster / depth-only scene pass
- object-id pass 与 object-id 输出目标
- `preScenePasses` / `postScenePasses` / `overlayPasses` 的外层编排

View File

@@ -1,6 +1,6 @@
# RenderPipeline::Shutdown
关闭这条主场景 runtime 管线并释放其持有资源。
关闭这条 runtime 渲染管线并释放其持有资源。
```cpp
virtual void Shutdown() = 0;
@@ -8,22 +8,27 @@ virtual void Shutdown() = 0;
## 当前调用语义
`engine/src/Rendering/CameraRenderer.cpp` 可以看到,当前调用方会在这些时机直接调用它:
`engine/src/Rendering/CameraRenderer.cpp` 可以看到,当前主要调用方会在这些时机直接调用它:
- `CameraRenderer` 析构时
- `CameraRenderer::ResetPipeline()` 替换旧主管线时
- `CameraRenderer` 析构时
- `CameraRenderer::ResetPipeline()` 替换旧 pipeline 时。
调用方不会额外区分“这条管线是否做过显式 [Initialize](Initialize.md)”
调用方不会额外区分“这条管线是否已经显式 `Initialize()` 过”;因此实现应能容忍未初始化或已清空状态上的 shutdown
## 对实现的要求
- 应释放这条 runtime pipeline 自己有的 RHI 资源、缓存和临时对象。
- 最好能容忍“尚未显式初始化就被关闭”或“曾经在 [Render](Render.md) 内部惰性初始化过”的调用路径
- 不应把 object-id pass 或外层 request / `RenderPassSequence` 编排状态混进这里
- 应释放这条 runtime pipeline 自己有的 RHI 资源、缓存和临时对象。
- 应支持重复调用,避免把 teardown 变成一次性、脆弱的操作
- 不应把 object-id pass`CameraRenderRequest` 或外部 `RenderPassSequence` 的生命周期混进这里;这些属于管线外层协调逻辑
## 设计说明
- 这是显式生命周期接口,不等同于 C++ 析构。
- 某些实现会在析构函数里再次兜底调用 `Shutdown()`,但基类本身不提供这一保证。
## 相关文档
- [返回类型总览](RenderPipeline.md)
- [RenderPipeline::Initialize](Initialize.md)
- [CameraRenderer](../CameraRenderer/CameraRenderer.md)
- [RenderPipeline](RenderPipeline.md)
- [Initialize](Initialize.md)
- [Destructor](Destructor.md)
- [BuiltinForwardPipeline::Shutdown](../Pipelines/BuiltinForwardPipeline/Shutdown.md)

View File

@@ -1,16 +1,24 @@
# RenderPipelineAsset::~RenderPipelineAsset
销毁渲染管线资产对象。
销毁渲染管线资产基类对象。
```cpp
virtual ~RenderPipelineAsset() = default;
```
## 行为说明
## 当前语义
这是一个虚析构函数,用于保证通过基类指针销毁派生资产对象时行为正确。
- 这是一个虚析构函数,保证通过 `RenderPipelineAsset*``std::shared_ptr<const RenderPipelineAsset>` 销毁派生 asset 时行为正确。
- 析构函数本身不负责关闭已经创建出来的 runtime [RenderPipeline](../RenderPipeline/RenderPipeline.md) 实例。
- 这符合当前分层asset 是“工厂和配置描述”,不是 runtime pipeline 的所有者。
## 调用方影响
- 销毁 asset 不会自动回收 `CameraRenderer` 当前已经持有的 pipeline那部分生命周期仍由 runtime pipeline 持有者负责。
- 因此不能把“asset 已析构”误解成“由它创建的所有 pipeline 都已关闭”。
## 相关文档
- [返回类型总览](RenderPipelineAsset.md)
- [RenderPipelineAsset](RenderPipelineAsset.md)
- [CreatePipeline](CreatePipeline.md)
- [RenderPipeline](../RenderPipeline/RenderPipeline.md)

View File

@@ -1,16 +1,25 @@
# RenderResourceCache::~RenderResourceCache
销毁资源缓存对象。
销毁渲染资源缓存对象。
```cpp
~RenderResourceCache();
```
## 行为说明
## 当前语义
当前析构函数调用 [Shutdown](Shutdown.md),释放 mesh 与 texture cache 中的所有 RHI 资源
- 当前析构函数唯一的显式动作就是调用 [Shutdown](Shutdown.md)。
- 因此对象销毁前会释放 mesh cache 和 texture cache 中持有的全部 GPU buffer、texture 和 resource view。
- 析构完成后,之前发给调用方的 `CachedMesh*` / `CachedTexture*` 指针全部失效。
## 调用方影响
- 如果调用方把缓存条目指针长期保存到外部结构中,必须保证它们不会越过 cache 本身的生命周期。
- 因为析构路径和手动 [Shutdown](Shutdown.md) 使用同一套清理逻辑,所以两者对外部观察到的“缓存条目失效”语义是一样的。
## 相关文档
- [返回类型总览](RenderResourceCache.md)
- [RenderResourceCache](RenderResourceCache.md)
- [Shutdown](Shutdown.md)
- [GetOrCreateMesh](GetOrCreateMesh.md)
- [GetOrCreateTexture](GetOrCreateTexture.md)

View File

@@ -1,38 +1,43 @@
# RenderResourceCache::GetOrCreateMesh
获取或创建某个 `Mesh` 的 GPU 缓存。
```cpp
const CachedMesh* GetOrCreateMesh(RHI::RHIDevice* device, const Resources::Mesh* mesh);
```
## 参数
- `device` - 用于创建 GPU buffer 与 view 的设备。
- `mesh` - 需要上传并缓存的网格资源。
## 行为说明
当前实现会:
1. 检查 `device``mesh` `mesh->IsValid()`
2. 若缓存已存在,直接返回
3. 否则上传顶点/索引数据并创建对应 view
4. 把结果放入 `m_meshCache` 并返回。
## 参数
- `device` - 用于创建 GPU buffer 与 view 的设备
- `mesh` - 要缓存的网格资源
1. 拒绝 `device == nullptr``mesh == nullptr` `!mesh->IsValid()` 的输入
2. `mesh` 指针地址作为 cache key 查找 `m_meshCache`
3. 命中时直接返回已有 `CachedMesh`
4. 未命中时调用内部 `UploadMesh(...)`
- 顶点数据必须非空,大小大于 `0`,且 `vertexStride > 0`
- 一定会创建 vertex buffer 和 vertex-buffer view。
- 只有在索引数据存在且计数有效时,才会额外创建 index buffer 和 index-buffer view。
5. 如果上传失败,会立即清理这次临时创建 GPU 对象,并返回 `nullptr`
6. 上传成功后把结果插入缓存并返回
## 返回值
- 成功时返回 `CachedMesh*`
- 失败时返回 `nullptr`
- 输入无效或上传失败时返回 `nullptr`
## 当前实现限制
## 当前实现边界
- 当前不会检测 mesh 数据后续是否被修改
- 当前要求顶点数据非空、`vertexStride > 0`
- 若上传过程中途失败,会清理当前临时创建的资源,但不会记录失败原因
- 缓存键是资源指针身份不是资源内容摘要mesh 内容后续被修改时,这里不会自动失效或重建
- 返回的是缓存内部对象地址;调用 [Shutdown](Shutdown.md) 或析构后这些地址会失效
- 当前主消费者是 [BuiltinForwardPipeline](../Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md) 的 `DrawVisibleItem(...)` 路径
## 相关文档
- [返回类型总览](RenderResourceCache.md)
- [RenderResourceCache](RenderResourceCache.md)
- [GetOrCreateTexture](GetOrCreateTexture.md)
- [Shutdown](Shutdown.md)
- [BuiltinForwardPipeline](../Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md)

View File

@@ -1,38 +1,44 @@
# RenderResourceCache::GetOrCreateTexture
获取或创建某个 `Texture` 的 GPU 缓存。
```cpp
const CachedTexture* GetOrCreateTexture(RHI::RHIDevice* device, const Resources::Texture* texture);
```
## 参数
- `device` - 用于创建 GPU texture 与 SRV 的设备。
- `texture` - 需要上传并缓存的纹理资源。
## 行为说明
当前实现会:
1. 检查 `device``texture` `texture->IsValid()`
2. 若缓存已存在,直接返回
3. 否则把纹理上传成 RHI texture并创建 shader resource view
4. 把结果放入 `m_textureCache` 并返回。
## 参数
- `device` - 用于创建 GPU 纹理与 SRV 的设备
- `texture` - 要缓存的纹理资源
1. 拒绝 `device == nullptr``texture == nullptr` `!texture->IsValid()` 的输入
2. `texture` 指针地址作为 cache key 查找 `m_textureCache`
3. 命中时直接返回已有 `CachedTexture`
4. 未命中时调用内部 `UploadTexture(...)`
- 要求像素数据非空且大小大于 `0`
- 当前只接受能映射到 `RHI::Format::R8G8B8A8_UNorm``R8G8B8A8_SRGB` 的资源格式。
- `rowPitch` 当前固定按 `width * 4` 计算。
- 创建的 shader-resource view 维度固定为 `Texture2D`
5. 如果上传失败,会清理这次临时创建的 texture 与 SRV并返回 `nullptr`
6. 上传成功后把结果插入缓存并返回。
## 返回值
- 成功时返回 `CachedTexture*`
- 失败时返回 `nullptr`
- 输入无效、格式不支持或上传失败时返回 `nullptr`
## 当前实现限制
## 当前实现边界
- 当前仅支持很少的纹理格式映射
- 当前默认创建 `Texture2D` 维度的 SRV
- 纹理缓存同样不具备内容变更失效机制
- 虽然 `TextureType` 会被映射到多个 RHI texture type但当前上传路径仍把 `arraySize` 固定为 `1`SRV 维度也固定为 `Texture2D`
- 缓存同样不会因为纹理内容变化而自动失效
- 当前主消费者是 [BuiltinForwardPipeline](../Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md) 中解析 base-color 纹理的材质路径
## 相关文档
- [返回类型总览](RenderResourceCache.md)
- [RenderResourceCache](RenderResourceCache.md)
- [GetOrCreateMesh](GetOrCreateMesh.md)
- [Shutdown](Shutdown.md)
- [BuiltinForwardPipeline](../Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md)

View File

@@ -1,28 +1,35 @@
# RenderResourceCache::Shutdown
释放所有已缓存的 GPU 资源。
释放当前缓存里持有的全部 GPU 资源。
```cpp
void Shutdown();
```
## 行为说明
## 当前语义
当前实现会:
当前实现会按缓存类型依次回收
- 逐个关闭并删除 `CachedMesh` 中的 buffer / view。
- 清空 `m_meshCache`
- 逐个关闭并删除 `CachedTexture` 中的 texture / SRV。
- 清空 `m_textureCache`
1. 遍历 `m_meshCache`,关闭并删除 `vertexBufferView``indexBufferView``vertexBuffer``indexBuffer`
2. 清空 `m_meshCache`
3. 遍历 `m_textureCache`,关闭并删除 `shaderResourceView``texture`
4. 清空 `m_textureCache`
## 注意事项
## 调用后效果
- 当前不会通知上层资源系统
- 当前不会保留缓存统计信息
- 调用后之前返回的 `CachedMesh*` / `CachedTexture*` 都会失效
- 调用之后,之前从 [GetOrCreateMesh](GetOrCreateMesh.md) / [GetOrCreateTexture](GetOrCreateTexture.md) 拿到的缓存指针全部失效
- 这是一次“完全清空缓存”的操作,不会保留命中记录、失败标记或脏状态
- 后续如果再次请求同一份 mesh 或 texture会重新走上传路径并生成新的缓存条目
## 当前实现边界
- 当前实现不是线程安全的。
- 它清理的是 `RenderResourceCache` 自己创建并拥有的 GPU 副本,不会反向销毁 `Resources::Mesh` / `Resources::Texture` 资源本体。
- 它也不会通知资源系统“某份 CPU 资源刚失去 GPU 副本”;外层如果需要更复杂的失效传播,需要自行处理。
## 相关文档
- [返回类型总览](RenderResourceCache.md)
- [RenderResourceCache](RenderResourceCache.md)
- [Destructor](Destructor.md)
- [GetOrCreateMesh](GetOrCreateMesh.md)
- [GetOrCreateTexture](GetOrCreateTexture.md)

View File

@@ -1,17 +1,26 @@
# RenderSurface::ClearClearColorOverride
清除清屏色覆盖标记
关闭 surface 级 clear-color override
```cpp
void ClearClearColorOverride();
```
## 行为说明
## 当前语义
当前实现只会把 `m_hasClearColorOverride` `false`,不会重置保存的颜色值
- 当前实现只会把 `m_hasClearColorOverride` `false`
- 已保存的 `m_clearColorOverride` 不会被清零,也不会恢复成黑色。
- 因此这是“停用当前 override”不是“删除最后一次写入的颜色值”。
## 调用方影响
- 调用之后,[HasClearColorOverride](HasClearColorOverride.md) 会返回 `false`
- `BuiltinForwardPipeline::Render()` 后续会退回使用 `sceneData.cameraData.clearColor`,而不是这里缓存的颜色。
- 如果稍后再次调用 [SetClearColorOverride](SetClearColorOverride.md),新的颜色值会重新启用 override如果重新写入同一个值也会再次生效。
## 相关文档
- [返回类型总览](RenderSurface.md)
- [RenderSurface](RenderSurface.md)
- [SetClearColorOverride](SetClearColorOverride.md)
- [HasClearColorOverride](HasClearColorOverride.md)
- [GetClearColorOverride](GetClearColorOverride.md)

View File

@@ -1,18 +1,42 @@
# RenderSurface::RenderSurface
构造渲染表面
构造一个只描述渲染目标状态的 `RenderSurface`
```cpp
RenderSurface() = default;
RenderSurface();
RenderSurface(uint32_t width, uint32_t height);
```
## 行为说明
## 参数
- 默认构造会得到一个空尺寸表面,宽高初始为 `0`
- 带参数构造会直接把宽高设为给定值
- `width` - 初始逻辑宽度
- `height` - 初始逻辑高度
## 当前语义
- 默认构造得到 `0 x 0` 的空 surface带参构造只写入 `width / height`
- 构造函数不会自动创建颜色附件、深度附件或任何底层 render target 资源。
- 初始状态下:
- 没有颜色附件。
- 深度附件为 `nullptr`
- 未启用自定义 render area。
- 未启用 clear-color override。
- 自动颜色状态切换开关为开启。
- `colorStateBefore``colorStateAfter` 都默认是 `Present`
## 设计说明
- `RenderSurface` 只是一次渲染提交使用的“目标描述”,不是 swap chain、framebuffer 或纹理资源的拥有者。
- 调用方通常先构造 surface再通过 [SetColorAttachment](SetColorAttachment.md)、[SetDepthAttachment](SetDepthAttachment.md)、[SetRenderArea](SetRenderArea.md) 等接口补齐实际目标配置。
## 测试覆盖
- `tests/Rendering/unit/test_camera_scene_renderer.cpp` 验证了仅设置宽高的 surface 也会生成覆盖整张 surface 的默认 render area。
- `tests/Editor/test_viewport_host_surface_utils.cpp` 验证了编辑器辅助函数会基于构造出的 surface 继续注入附件和颜色状态。
## 相关文档
- [返回类型总览](RenderSurface.md)
- [RenderSurface](RenderSurface.md)
- [SetSize](SetSize.md)
- [SetColorAttachment](SetColorAttachment.md)
- [SetDepthAttachment](SetDepthAttachment.md)

View File

@@ -1,6 +1,6 @@
# RenderSurface::GetClearColorOverride
获取当前清屏色覆盖值。
返回当前保存的 clear-color override 值。
```cpp
const Math::Color& GetClearColorOverride() const;
@@ -8,13 +8,22 @@ const Math::Color& GetClearColorOverride() const;
## 返回值
- 返回内部保存的清屏色覆盖值引用。
- 返回内部保存的 `Math::Color` 常量引用。
## 注意事项
## 当前语义
- 即便 [HasClearColorOverride](HasClearColorOverride.md)`false`,内部仍然保留最近一次写入过的颜色值
- 该访问器不会检查 override 是否启用;调用方通常应先看 [HasClearColorOverride](HasClearColorOverride.md)。
- 如果从未调用过 [SetClearColorOverride](SetClearColorOverride.md),默认值是 `Math::Color::Black()`
- 调用 [ClearClearColorOverride](ClearClearColorOverride.md) 后,这里仍会返回上一次保存的颜色,只是它不再被视为生效中的 override。
## 调用方影响
- `BuiltinForwardPipeline::Render()` 只会在 [HasClearColorOverride](HasClearColorOverride.md) 为 `true` 时读取这里的值作为清屏颜色。
- 如果 override 未启用forward pipeline 会退回 `sceneData.cameraData.clearColor`;这意味着 surface 级 clear-color 覆盖不会自动影响所有渲染路径。
## 相关文档
- [返回类型总览](RenderSurface.md)
- [RenderSurface](RenderSurface.md)
- [HasClearColorOverride](HasClearColorOverride.md)
- [SetClearColorOverride](SetClearColorOverride.md)
- [ClearClearColorOverride](ClearClearColorOverride.md)

View File

@@ -1,6 +1,6 @@
# RenderSurface::GetColorAttachments
获取颜色附件数组。
读取当前颜色附件数组。
```cpp
const std::vector<RHI::RHIResourceView*>& GetColorAttachments() const;
@@ -8,15 +8,28 @@ const std::vector<RHI::RHIResourceView*>& GetColorAttachments() const;
## 返回值
- 对内部颜色附件数组的常量引用
- 返回内部 `std::vector<RHI::RHIResourceView*>` 的常量引用,而不是副本
## 注意事项
## 当前语义
- 当前返回的是内部容器引用,不是拷贝
- 调用方需要自己保证其中指针的生命周期有效
- [SetColorAttachment](SetColorAttachment.md) 会把数组重置为 `0``1` 个元素;[SetColorAttachments](SetColorAttachments.md) 会整体拷贝调用方提供的数组
- 数组元素是非拥有的裸指针,`RenderSurface` 不负责这些 view 的生命周期。
- [SetColorAttachments](SetColorAttachments.md) 不会自动过滤 `nullptr`,因此数组里可能出现空洞。
## 调用方影响
- `CameraRenderRequest::ObjectIdRenderRequest::IsRequested()``ScenePassRenderRequest::IsRequested()` 都仅通过“数组是否为空”判断该 pass 路径是否被请求。
- `ScenePassRenderRequest::IsValid()`、[BuiltinDepthStylePassBase::Execute](../Passes/BuiltinDepthStylePassBase/Execute.md)、`CameraRenderRequest::ObjectIdRenderRequest::IsValid()``BuiltinObjectIdPass::Render()``BuiltinInfiniteGridPass::Render()` 都进一步要求第一个颜色附件非空。
- `BuiltinForwardPipeline::Render()` 允许多 render target 数组存在,但状态前后值仍按“整组颜色附件共享一个 before/after 状态”解释,而不是逐附件描述。
## 测试覆盖
- `tests/Editor/test_viewport_host_surface_utils.cpp``tests/Editor/test_viewport_render_targets.cpp` 都验证了编辑器 surface 构建结果会携带预期的第一个颜色附件。
## 相关文档
- [返回类型总览](RenderSurface.md)
- [RenderSurface](RenderSurface.md)
- [SetColorAttachment](SetColorAttachment.md)
- [SetColorAttachments](SetColorAttachments.md)
- [GetColorStateBefore](GetColorStateBefore.md)
- [GetColorStateAfter](GetColorStateAfter.md)

View File

@@ -1,6 +1,6 @@
# RenderSurface::GetColorStateAfter
获取颜色附件渲染后状态。
返回颜色附件在本次渲染结束后预期应落到的状态。
```cpp
RHI::ResourceStates GetColorStateAfter() const;
@@ -8,9 +8,26 @@ RHI::ResourceStates GetColorStateAfter() const;
## 返回值
- 当前记录的渲染后颜色状态
- 返回内部保存的颜色附件“结束状态”;默认值是 `Present`
## 当前语义
- 当 [IsAutoTransitionEnabled](IsAutoTransitionEnabled.md) 为 `true` 时,`BuiltinForwardPipeline::Render()``BuiltinObjectIdPass::Render()` 会把这里作为从 `RenderTarget` 过渡出去的目标状态。
- 编辑器 `SceneViewportEditorOverlayPassRenderer::Render()` 也会把这里视为主颜色目标在 overlay pass 之前已经处于的状态,并在绘制结束后再切回这个状态。
- 与 before 状态一样,这里描述的是整组颜色附件的统一 after 状态,不是每个 attachment 的独立状态。
## 调用方影响
- 这个值不仅影响“主场景渲染结束后资源会去哪里”,还会影响后续 editor overlay、shader-resource 采样或 present 等消费方接管该颜色目标的起点状态。
- 如果调用方把 after 状态声明错了,后续 pass 可能在错误状态上继续工作,而 `RenderSurface` 本身不会做保护。
## 测试覆盖
- `tests/Editor/test_viewport_host_surface_utils.cpp` 验证了 viewport surface 会保留传入的 after 状态。
## 相关文档
- [返回类型总览](RenderSurface.md)
- [RenderSurface](RenderSurface.md)
- [SetColorStateAfter](SetColorStateAfter.md)
- [GetColorStateBefore](GetColorStateBefore.md)
- [SetAutoTransitionEnabled](SetAutoTransitionEnabled.md)

View File

@@ -1,6 +1,6 @@
# RenderSurface::GetColorStateBefore
获取颜色附件渲染前状态。
返回颜色附件进入本次渲染前预期所处的状态。
```cpp
RHI::ResourceStates GetColorStateBefore() const;
@@ -8,9 +8,26 @@ RHI::ResourceStates GetColorStateBefore() const;
## 返回值
- 当前记录的渲染前颜色状态
- 返回内部保存的颜色附件“起始状态”;默认值是 `Present`
## 当前语义
- 这不是逐附件状态表,而是对整组颜色附件共享的统一描述。
- 当 [IsAutoTransitionEnabled](IsAutoTransitionEnabled.md) 为 `true` 时,`BuiltinForwardPipeline::Render()``BuiltinObjectIdPass::Render()` 会把它作为 `TransitionBarrier(..., before, RenderTarget)` 的来源状态。
- 如果颜色附件实际并不处于这里声明的状态,`RenderSurface` 自身不会发现或纠正这个问题。
## 调用方影响
- 编辑器 viewport 常通过辅助函数把这里设置成 `Common``PixelShaderResource`,以匹配离屏颜色纹理在进入本次 pass 前的真实消费状态。
- 对 MRT 场景来说,这里仍只表达“整组颜色附件共享同一个 before 状态”,并不支持为不同 attachment 分别声明不同起始状态。
## 测试覆盖
- `tests/Editor/test_viewport_host_surface_utils.cpp``tests/Editor/test_viewport_render_targets.cpp` 都验证了 viewport surface 会正确保留传入的 before 状态。
## 相关文档
- [返回类型总览](RenderSurface.md)
- [RenderSurface](RenderSurface.md)
- [SetColorStateBefore](SetColorStateBefore.md)
- [GetColorStateAfter](GetColorStateAfter.md)
- [SetAutoTransitionEnabled](SetAutoTransitionEnabled.md)

View File

@@ -1,6 +1,6 @@
# RenderSurface::GetDepthAttachment
获取当前深度附件。
返回当前绑定的深度附件指针
```cpp
RHI::RHIResourceView* GetDepthAttachment() const;
@@ -8,9 +8,28 @@ RHI::RHIResourceView* GetDepthAttachment() const;
## 返回值
- 当前记录的深度附件指针。
- 返回内部缓存的深度附件指针;如果未设置则返回 `nullptr`
## 当前语义
- 返回值完全由 [SetDepthAttachment](SetDepthAttachment.md) 最近一次写入决定。
- `RenderSurface` 不会检查这个 view 是否仍然存活,也不会校验它是否真的是 depth-stencil 视图。
- 该指针是非拥有引用,生命周期仍由外部资源管理方负责。
## 调用方影响
- `BuiltinForwardPipeline::Render()` 会把它传给 `SetRenderTargets(...)`,并在需要清深度时调用 `ClearDepthStencil(...)`
- `ScenePassRenderRequest::IsValid()` 与 [BuiltinDepthStylePassBase::Execute](../Passes/BuiltinDepthStylePassBase/Execute.md) 都要求这里非空,否则 depth-only / shadow-caster 路径不会执行。
- `BuiltinObjectIdPass::Render()``BuiltinInfiniteGridPass::Render()` 都把 `nullptr` 视为无效输入。
- `ObjectIdRenderRequest::IsValid()` 也要求这里非空,才能把 object-id surface 判定为合法。
## 测试覆盖
- `tests/Editor/test_viewport_host_surface_utils.cpp``tests/Editor/test_viewport_render_targets.cpp` 都断言了构建出来的 surface 能返回正确 depth view。
## 相关文档
- [返回类型总览](RenderSurface.md)
- [RenderSurface](RenderSurface.md)
- [SetDepthAttachment](SetDepthAttachment.md)
- [GetColorAttachments](GetColorAttachments.md)
- [GetRenderArea](GetRenderArea.md)

View File

@@ -1,6 +1,6 @@
# RenderSurface::GetHeight
获取当前表面高度。
返回 `RenderSurface` 当前记录的逻辑高度。
```cpp
uint32_t GetHeight() const;
@@ -8,10 +8,27 @@ uint32_t GetHeight() const;
## 返回值
- 当前记录的高度
- 返回内部缓存的 `m_height`
## 当前语义
- 该值只由构造函数和 [SetSize](SetSize.md) 写入,不会从附件对象反推。
- 当没有启用自定义 render area 时,[GetRenderArea](GetRenderArea.md) 会把整个 surface 解释为 `(0, 0, width, height)`,因此这里的高度也会成为默认渲染区域高度。
- 即使后续绑定的真实纹理高度不同,`GetHeight()` 仍然只反映 `RenderSurface` 自己记录的高度。
## 调用方影响
- `CameraRenderer::Render()` 会用 render area 的高度参与有效性判断;默认 render area 又直接依赖这里的值。
- `SceneRenderer` 和 editor viewport 构建请求时,都会把这里的高度当成初始 viewport 尺寸来源。
## 测试覆盖
- `tests/Rendering/unit/test_camera_scene_renderer.cpp` 验证了默认 render area 会继承 `RenderSurface(640, 480)` 的高度。
- `tests/Editor/test_viewport_host_surface_utils.cpp` 验证了编辑器 viewport surface 会保留传入高度。
## 相关文档
- [返回类型总览](RenderSurface.md)
- [RenderSurface](RenderSurface.md)
- [GetWidth](GetWidth.md)
- [SetSize](SetSize.md)
- [GetRenderArea](GetRenderArea.md)

View File

@@ -1,6 +1,6 @@
# RenderSurface::GetRenderArea
获取当前实际生效的渲染区域
获取当前实际生效的 render area
```cpp
Math::RectInt GetRenderArea() const;
@@ -8,16 +8,29 @@ Math::RectInt GetRenderArea() const;
## 返回值
- 如果没有启用自定义 render area返回 `(0, 0, width, height)`
- 如果启用了自定义 render area返回经过当前 surface 尺寸再次夹取后的矩形
- 如果没有启用自定义 render area返回 `(0, 0, width, height)`
- 如果启用了自定义 render area返回当前 surface 尺寸再次 clamp 后的矩形
## 行为说明
## 当前语义
当前实现即使在 `SetRenderArea(...)` 时已经做过一次夹取,取回时也会再次调用内部 `ClampRenderArea(...)`。这保证了在 `SetSize(...)` 之后,返回值仍然不会越界
- 即使在 [SetRenderArea](SetRenderArea.md) 时已经做过一次 clamp读取时仍会再次调用内部 `ClampRenderArea(...)`
- 这保证了在 [SetSize](SetSize.md) 之后,即便旧 render area 还保存在成员里,返回值也仍然不会越界。
- 因此这里返回的是“当前时刻真正生效的区域”,而不是调用 `SetRenderArea(...)` 时写入的原始输入值。
## 调用方影响
- `BuiltinForwardPipeline::Render()`、[BuiltinDepthStylePassBase::Execute](../Passes/BuiltinDepthStylePassBase/Execute.md) 和 `BuiltinObjectIdPass::Render()` 都会基于这里返回的矩形设置 viewport / scissor并在宽高不大于 `0` 时拒绝渲染。
- `CameraRenderer::Render()` 通过 [GetRenderAreaWidth](GetRenderAreaWidth.md) / [GetRenderAreaHeight](GetRenderAreaHeight.md) 做有效性判断;那两个访问器本质上也都是从这里派生出来的。
- `SceneRenderer` 在构建相机请求时,会把相机 viewport 进一步解析到已有 surface render area 之内,所以这里也是“父级渲染区域”的来源。
## 测试覆盖
- `tests/Rendering/unit/test_camera_scene_renderer.cpp` 覆盖了默认整 surface 区域、嵌套 surface render area以及相机 viewport 叠加后的最终结果。
- `tests/Editor/test_viewport_render_flow_utils.cpp` 验证了 scene viewport 主 surface 与 object-id surface 会共享解析后的 render area。
## 相关文档
- [返回类型总览](RenderSurface.md)
- [RenderSurface](RenderSurface.md)
- [SetRenderArea](SetRenderArea.md)
- [HasCustomRenderArea](HasCustomRenderArea.md)
- [GetRenderAreaWidth](GetRenderAreaWidth.md)

View File

@@ -1,6 +1,6 @@
# RenderSurface::GetRenderAreaHeight
获取当前渲染区域高度。
返回当前生效 render area 的高度。
```cpp
uint32_t GetRenderAreaHeight() const;
@@ -8,14 +8,28 @@ uint32_t GetRenderAreaHeight() const;
## 返回值
- 当前 `GetRenderArea().height` 的非负版本
- 返回 `max(GetRenderArea().height, 0)` 的无符号结果。
## 行为说明
## 当前语义
当前实现会先取 `GetRenderArea()`,再对 `height``max(height, 0)`,最后转成 `uint32_t`。因此它反映的是当前实际生效 render area 的稳定高度
- 该值不是独立存储字段,而是每次根据 [GetRenderArea](GetRenderArea.md) 的结果即时计算
- 如果没有启用自定义 render area则结果等于 surface 的逻辑高度。
- 如果 render area 经过 clamp 后高度变成 `0`,这里也会返回 `0`
## 调用方影响
- `CameraRenderer::Render()` 会把高度为 `0` 的 surface 视为不可渲染输入。
- `ObjectIdRenderRequest::IsValid()` 同样要求这里大于 `0`,否则 object-id 路径不会被接受。
- 上层逻辑通常把 `GetRenderAreaWidth() / GetRenderAreaHeight()` 作为“本帧真实 viewport 尺寸”,而不是 surface 构造尺寸。
## 测试覆盖
- `tests/Rendering/unit/test_camera_scene_renderer.cpp` 验证了相机提交到 pipeline 的 viewport 高度来自最终 render area。
- `tests/Rendering/unit/test_scene_render_request_utils.cpp` 验证了父 surface render area 与相机 viewport 组合后,高度会按解析结果更新。
## 相关文档
- [返回类型总览](RenderSurface.md)
- [RenderSurface](RenderSurface.md)
- [GetRenderArea](GetRenderArea.md)
- [GetRenderAreaWidth](GetRenderAreaWidth.md)
- [SetRenderArea](SetRenderArea.md)

View File

@@ -1,6 +1,6 @@
# RenderSurface::GetRenderAreaWidth
获取当前渲染区域宽度。
返回当前生效 render area 的宽度。
```cpp
uint32_t GetRenderAreaWidth() const;
@@ -8,14 +8,28 @@ uint32_t GetRenderAreaWidth() const;
## 返回值
- 当前 `GetRenderArea().width` 的非负版本
- 返回 `max(GetRenderArea().width, 0)` 的无符号结果。
## 行为说明
## 当前语义
当前实现会先取 `GetRenderArea()`,再对 `width``max(width, 0)`,最后转成 `uint32_t`。因此即使内部矩形来源异常,返回值也不会出现负数
- 这里没有单独缓存宽度;每次都会先调用 [GetRenderArea](GetRenderArea.md) 再取 `width`
- 如果未启用自定义 render area则结果等于 surface 的逻辑宽度。
- 如果自定义 render area 在设置时或 resize 后被 clamp 成空区域,这里会返回 `0`
## 调用方影响
- `CameraRenderer::Render()` 会在宽度或高度为 `0` 时直接拒绝本次渲染。
- `ObjectIdRenderRequest::IsValid()` 也要求 render area 宽度大于 `0`,否则 object-id pass 会被视为无效请求。
- 因为这是从 [GetRenderArea](GetRenderArea.md) 动态推导出来的,所以它反映的是“当前实际可绘制宽度”,而不是调用 [SetRenderArea](SetRenderArea.md) 时的原始输入值。
## 测试覆盖
- `tests/Rendering/unit/test_camera_scene_renderer.cpp` 验证了相机渲染使用的 viewport 宽度来自 surface 的最终 render area。
- `tests/Rendering/unit/test_scene_render_request_utils.cpp` 验证了嵌套 viewport 计算后render area 宽度会按父区域和相机 viewport 共同解析。
## 相关文档
- [返回类型总览](RenderSurface.md)
- [RenderSurface](RenderSurface.md)
- [GetRenderArea](GetRenderArea.md)
- [GetRenderAreaHeight](GetRenderAreaHeight.md)
- [SetRenderArea](SetRenderArea.md)

View File

@@ -1,6 +1,6 @@
# RenderSurface::GetWidth
获取当前表面宽度。
返回 `RenderSurface` 当前记录的逻辑宽度。
```cpp
uint32_t GetWidth() const;
@@ -8,10 +8,27 @@ uint32_t GetWidth() const;
## 返回值
- 当前记录的宽度
- 返回内部缓存的 `m_width`
## 当前语义
- 该值只由构造函数和 [SetSize](SetSize.md) 写入,不会从颜色附件或深度附件反推。
- 当没有启用自定义 render area 时,[GetRenderArea](GetRenderArea.md) 会把整个 surface 解释为 `(0, 0, width, height)`,因此这里的宽度也会成为默认渲染区域宽度。
- 即使后续绑定的实际附件尺寸与这里不一致,`GetWidth()` 仍然只返回 surface 自己记录的值。
## 调用方影响
- [CameraRenderer](../CameraRenderer/Render.md) 会通过 render area 的宽高决定是否继续渲染;默认 render area 又直接依赖这里的宽度。
- `SceneRenderer` 构建请求时,也会把 surface 的宽高传播到每个相机请求的默认 viewport 尺寸。
## 测试覆盖
- `tests/Rendering/unit/test_camera_scene_renderer.cpp` 验证了默认 render area 会继承 `RenderSurface(640, 480)` 的宽高。
- `tests/Editor/test_viewport_host_surface_utils.cpp` 验证了编辑器 viewport 辅助函数构建出的 surface 会保留传入宽度。
## 相关文档
- [返回类型总览](RenderSurface.md)
- [RenderSurface](RenderSurface.md)
- [GetHeight](GetHeight.md)
- [SetSize](SetSize.md)
- [GetRenderArea](GetRenderArea.md)

View File

@@ -1,6 +1,6 @@
# RenderSurface::HasClearColorOverride
判断当前是否启用了清屏色覆盖。
查询当前是否启用了 surface 级 clear-color 覆盖。
```cpp
bool HasClearColorOverride() const;
@@ -8,11 +8,23 @@ bool HasClearColorOverride() const;
## 返回值
- 若已设置覆盖色则返回 `true`
- 否则返回 `false`
- 返回 `true` 表示 [GetClearColorOverride](GetClearColorOverride.md) 当前应被视为有效覆盖色
- 返回 `false` 表示即使内部还保留了颜色值,本帧也不应把它当作生效中的 override
## 当前语义
- [SetClearColorOverride](SetClearColorOverride.md) 会把该标志置为 `true`,并同步写入颜色值。
- [ClearClearColorOverride](ClearClearColorOverride.md) 只会把该标志清回 `false`,不会重置已保存的颜色内容。
- 因此这里描述的是“是否启用”,而不是“是否存过一个颜色值”。
## 调用方影响
- `BuiltinForwardPipeline::Render()` 会优先检查这里;只有为 `true` 时才使用 [GetClearColorOverride](GetClearColorOverride.md),否则退回 `sceneData.cameraData.clearColor`
- 这套 surface 级 override 与 `CameraRenderRequest` 的 request 级 clear-color override 是两层概念:前者作用于具体 `RenderSurface`,后者会先改写提交给 pipeline 的 `sceneData.cameraData.clearColor`
## 相关文档
- [返回类型总览](RenderSurface.md)
- [RenderSurface](RenderSurface.md)
- [SetClearColorOverride](SetClearColorOverride.md)
- [ClearClearColorOverride](ClearClearColorOverride.md)
- [GetClearColorOverride](GetClearColorOverride.md)

View File

@@ -1,6 +1,6 @@
# RenderSurface::HasCustomRenderArea
判断当前是否启用了自定义渲染区域
查询当前是否启用了显式 render area
```cpp
bool HasCustomRenderArea() const;
@@ -8,12 +8,23 @@ bool HasCustomRenderArea() const;
## 返回值
- `true`:当前 `GetRenderArea()` 使用的是显式设置过的 render area
- `false`:当前 `GetRenderArea()` 会退回到整张 surface
- 返回 `true` 表示曾通过 [SetRenderArea](SetRenderArea.md) 写入自定义区域,当前 [GetRenderArea](GetRenderArea.md) 不再直接等于整张 surface。
- 返回 `false` 表示当前仍使用默认的整 surface 区域。
## 当前语义
- 该标志由 [SetRenderArea](SetRenderArea.md) 置为 `true`,由 [ResetRenderArea](ResetRenderArea.md) 清回 `false`
- 调用 [SetSize](SetSize.md) 不会重置这个标志;如果 surface 尺寸变化,内部只会把已保存的 render area 重新 clamp 到新边界内。
- “启用了自定义 render area”和“最终区域是否刚好等于整张 surface”不是一回事。即使 clamp 后矩形看起来与整 surface 相同,这个标志仍可能保持 `true`
## 调用方影响
- `SceneRenderer` 会在已有 surface render area 的基础上继续解析相机 viewport因此这个标志会影响后续请求是否被视为“嵌套 viewport”场景。
- 对外部调用方来说,判断当前是否存在显式子区域时,应优先看这里,而不是仅比较 [GetRenderArea](GetRenderArea.md) 的数值。
## 相关文档
- [返回类型总览](RenderSurface.md)
- [RenderSurface](RenderSurface.md)
- [SetRenderArea](SetRenderArea.md)
- [ResetRenderArea](ResetRenderArea.md)
- [GetRenderArea](GetRenderArea.md)

View File

@@ -1,6 +1,6 @@
# RenderSurface::IsAutoTransitionEnabled
查询是否启用了颜色附件自动状态切换。
查询当前是否允许渲染路径自动处理颜色附件状态切换。
```cpp
bool IsAutoTransitionEnabled() const;
@@ -8,10 +8,24 @@ bool IsAutoTransitionEnabled() const;
## 返回值
- 已启用返回 `true`
- 否则返回 `false`
- 返回内部保存的 `m_autoTransition`
## 当前语义
- 当返回 `true` 时,`BuiltinForwardPipeline::Render()``BuiltinObjectIdPass::Render()` 会按
`colorStateBefore -> RenderTarget -> colorStateAfter`
的方式自动为颜色附件插入 barrier。
- 当返回 `false` 时,这两条路径不会替调用方做上述颜色状态切换。
- 这个开关只描述颜色附件,不包含深度附件状态。
## 当前实现边界
- 它不是对所有 pass 的全局强约束。`SceneViewportEditorOverlayPassRenderer::Render()` 会显式读取 [GetColorStateAfter](GetColorStateAfter.md),自己从该状态切到 `RenderTarget` 再切回去,而不是依赖这个布尔开关。
- 因此这里更像“供部分内建渲染路径采纳的策略位”,不是统一的 RHI 状态机。
## 相关文档
- [返回类型总览](RenderSurface.md)
- [RenderSurface](RenderSurface.md)
- [SetAutoTransitionEnabled](SetAutoTransitionEnabled.md)
- [GetColorStateBefore](GetColorStateBefore.md)
- [GetColorStateAfter](GetColorStateAfter.md)

View File

@@ -1,23 +1,26 @@
# RenderSurface::ResetRenderArea
清除自定义渲染区域
清除自定义 render area恢复“整张 surface 可渲染”的默认语义
```cpp
void ResetRenderArea();
```
## 行为说明
## 当前语义
当前实现会
- 当前实现会`m_hasCustomRenderArea` 设回 `false`
- 同时把内部缓存的 `m_renderArea` 重置为空矩形 `{}`
- 重置后,[GetRenderArea](GetRenderArea.md) 不会返回这个空矩形,而是重新按 `(0, 0, width, height)` 解释整张 surface。
-`m_hasCustomRenderArea` 设回 `false`
- 把内部缓存的 `m_renderArea` 重置为空矩形
## 调用方影响
重置后,`GetRenderArea()` 会重新回到“整张 surface”的默认语义
- 这会直接撤销此前通过 [SetRenderArea](SetRenderArea.md) 设置的子区域限制
- 之后即使 surface 先前经历过 clamp、resize 或嵌套 viewport 组合,默认读取路径也会重新回到“整 surface”。
- 如果上层逻辑想保留一个显式子区域,只是希望它在 resize 后重新适配边界,应继续保留自定义区域并依赖 [SetSize](SetSize.md) 的 reclamp 行为,而不是调用这里。
## 相关文档
- [返回类型总览](RenderSurface.md)
- [RenderSurface](RenderSurface.md)
- [SetRenderArea](SetRenderArea.md)
- [HasCustomRenderArea](HasCustomRenderArea.md)
- [GetRenderArea](GetRenderArea.md)

View File

@@ -1,6 +1,6 @@
# RenderSurface::SetAutoTransitionEnabled
设置是否自动切换颜色附件资源状态。
设置是否让部分渲染路径自动切换颜色附件状态。
```cpp
void SetAutoTransitionEnabled(bool enabled);
@@ -8,15 +8,22 @@ void SetAutoTransitionEnabled(bool enabled);
## 参数
- `enabled` - 是否启用自动状态切换
- `enabled` - `true` 表示允许读取 `colorStateBefore / colorStateAfter` 并自动插入颜色附件 barrier`false` 表示由调用方或 pass 自己管理
## 行为说明
## 当前语义
当前实现只记录这个布尔值。像 [BuiltinForwardPipeline](../Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md) 这样的管线会在渲染前后读取它,决定是否调用 `TransitionBarrier()`
- `BuiltinForwardPipeline::Render()``BuiltinObjectIdPass::Render()` 会读取这个开关
- 打开时,它们会把颜色附件从 [GetColorStateBefore](GetColorStateBefore.md) 过渡到 `RenderTarget`,结束后再过渡到 [GetColorStateAfter](GetColorStateAfter.md)。
- 关闭时,这两条路径仍会继续渲染,但默认假设调用方已经保证目标颜色资源处于正确状态。
## 当前实现边界
- 这个开关不处理深度附件状态。
- 它也不会阻止其他 pass 显式做自己的 barrier。编辑器 overlay pass 就会无视该开关,直接把颜色附件从 `GetColorStateAfter()` 切到 `RenderTarget` 并在结束后切回去。
## 相关文档
- [返回类型总览](RenderSurface.md)
- [RenderSurface](RenderSurface.md)
- [IsAutoTransitionEnabled](IsAutoTransitionEnabled.md)
- [SetColorStateBefore](SetColorStateBefore.md)
- [SetColorStateAfter](SetColorStateAfter.md)

View File

@@ -1,22 +1,30 @@
# RenderSurface::SetClearColorOverride
设置清屏色覆盖。
设置 surface 级别的 clear-color 覆盖
```cpp
void SetClearColorOverride(const Math::Color& clearColor);
```
## 参数
- `clearColor` - 希望优先用于清屏的颜色。
## 行为说明
当前实现会:
-`m_hasClearColorOverride` 设为 `true`
- 保存给定颜色到内部覆盖值
-`m_hasClearColorOverride` 设为 `true`
- 把传入颜色保存到 `m_clearColorOverride`
之后像 [BuiltinForwardPipeline](../Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md) 这类管线会优先使用这个颜色,而不是相机清屏色。
## 当前语义
- 这是一种“显式启用并写值”的操作;之后 [HasClearColorOverride](HasClearColorOverride.md) 会返回 `true`
- 当前 [BuiltinForwardPipeline](../Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md) 在执行颜色清屏时,会优先使用这里保存的颜色,而不是 `sceneData.cameraData.clearColor`
- 如果只是想保留颜色值但暂时停用覆盖,应调用 [ClearClearColorOverride](ClearClearColorOverride.md) 清掉启用标志。
## 相关文档
- [返回类型总览](RenderSurface.md)
- [ClearClearColorOverride](ClearClearColorOverride.md)
- [RenderSurface](RenderSurface.md)
- [HasClearColorOverride](HasClearColorOverride.md)
- [GetClearColorOverride](GetClearColorOverride.md)
- [ClearClearColorOverride](ClearClearColorOverride.md)

View File

@@ -1,26 +1,30 @@
# RenderSurface::SetColorAttachment
设置单个颜色附件。
把 surface 的颜色附件重置为单个附件。
```cpp
void SetColorAttachment(RHI::RHIResourceView* colorAttachment);
```
## 行为说明
当前实现会先清空现有颜色附件数组;如果参数非空,再把它作为唯一颜色附件压入数组。
## 参数
- `colorAttachment` - 颜色附件视图。
- `colorAttachment` - 要绑定的颜色附件视图;允许传入 `nullptr`
## 注意事项
## 行为说明
- 这是“替换整个颜色附件列表”的语义,不是追加。
- 传入 `nullptr` 会让颜色附件数组变为空。
当前实现会先清空整个颜色附件数组,然后:
- 如果 `colorAttachment != nullptr`,把它作为唯一元素压入数组。
- 如果 `colorAttachment == nullptr`,保留一个空数组,等价于“当前没有颜色附件”。
## 当前实现边界
- 这里保存的是非拥有 `RHIResourceView*`,不会增加引用,也不会负责释放。
- 不会验证 view 类型、格式或尺寸是否真的适合作为 render target。
- 这是“单 render target 快捷写法”;如果需要 MRT应改用 [SetColorAttachments](SetColorAttachments.md)。
## 相关文档
- [返回类型总览](RenderSurface.md)
- [RenderSurface](RenderSurface.md)
- [SetColorAttachments](SetColorAttachments.md)
- [GetColorAttachments](GetColorAttachments.md)
- [SetDepthAttachment](SetDepthAttachment.md)

View File

@@ -1,26 +1,30 @@
# RenderSurface::SetColorAttachments
设置一组颜色附件。
整体替换 surface 的颜色附件数组
```cpp
void SetColorAttachments(const std::vector<RHI::RHIResourceView*>& colorAttachments);
```
## 参数
- `colorAttachments` - 颜色附件数组。
- `colorAttachments` - 新的颜色附件数组,按调用方给出的顺序整体复制
## 行为说明
当前实现直接拷贝这组指针到内部数组
- 当前实现直接执行 `m_colorAttachments = colorAttachments`
- 这意味着多 render target 场景可以通过这里一次性注入多个颜色附件。
- 已有颜色附件会被整体覆盖,不做增量合并。
## 注意事项
## 当前实现边界
- 当前不会过滤空指针
- 当前不会检查附件数量是否与具体管线能力匹配
- 不会过滤 `nullptr` 项,也不会压缩空洞
- 不会检查附件数量、格式组合或尺寸一致性
- 当前多个 builtin pass 只真正依赖首个颜色附件,或者至少要求第一项可用;数组里出现空指针时,后续行为由具体 pass 决定。
## 相关文档
- [返回类型总览](RenderSurface.md)
- [RenderSurface](RenderSurface.md)
- [SetColorAttachment](SetColorAttachment.md)
- [GetColorAttachments](GetColorAttachments.md)
- [SetColorStateBefore](SetColorStateBefore.md)
- [SetColorStateAfter](SetColorStateAfter.md)

View File

@@ -1,6 +1,6 @@
# RenderSurface::SetColorStateAfter
设置颜色附件在渲染完成后要回到的资源状态。
设置颜色附件在本次渲染结束后期望落到的统一状态。
```cpp
void SetColorStateAfter(RHI::ResourceStates state);
@@ -8,14 +8,27 @@ void SetColorStateAfter(RHI::ResourceStates state);
## 参数
- `state` - 渲染后状态。
- `state` - 调用方期望整组颜色附件在本次 pass 结束后处于的资源状态。
## 行为说明
## 当前语义
当前实现会把这个状态保存到内部统一字段中,供自动状态切换逻辑使用
- 当前实现只保存这个值,不会验证它是否真的与后续消费者的预期一致
- 默认值是 `Present`
- 当 [IsAutoTransitionEnabled](IsAutoTransitionEnabled.md) 为 `true` 时,主 forward/object-id 路径会在渲染结束时把颜色附件过渡到这里指定的状态。
## 调用方影响
- 编辑器 overlay pass 会把这里当作“接管主颜色附件前的既有状态”,并在绘制完 overlay 后再切回这个状态。
- 因此它不只是“主场景 pass 的收尾配置”,也会影响后续 pass 如何重新进入同一张颜色目标。
- 与 before 状态一样,这里对整组颜色附件只支持一个统一 after 状态。
## 测试覆盖
- `tests/Editor/test_viewport_host_surface_utils.cpp` 验证了编辑器 surface 会正确保留写入的 after 状态。
## 相关文档
- [返回类型总览](RenderSurface.md)
- [RenderSurface](RenderSurface.md)
- [GetColorStateAfter](GetColorStateAfter.md)
- [SetColorStateBefore](SetColorStateBefore.md)
- [SetAutoTransitionEnabled](SetAutoTransitionEnabled.md)

View File

@@ -1,6 +1,6 @@
# RenderSurface::SetColorStateBefore
设置颜色附件在进入渲染前被视为所处的资源状态。
设置颜色附件在本次渲染开始前预期所处的统一状态。
```cpp
void SetColorStateBefore(RHI::ResourceStates state);
@@ -8,14 +8,26 @@ void SetColorStateBefore(RHI::ResourceStates state);
## 参数
- `state` - 渲染前状态。
- `state` - 调用方认为整组颜色附件当前所处的资源状态。
## 行为说明
## 当前语义
当前实现把这个状态保存到内部统一字段中,供自动状态切换逻辑使用
- 当前实现只是把这个状态写入内部字段,不会验证颜色附件是否真的已经处于该状态
- 默认值是 `Present`
- 当 [IsAutoTransitionEnabled](IsAutoTransitionEnabled.md) 为 `true` 时,`BuiltinForwardPipeline::Render()``BuiltinObjectIdPass::Render()` 会把它当作自动 barrier 的来源状态。
## 当前实现边界
- 这是“整组颜色附件共享一个 before 状态”的模型,不支持每个 MRT attachment 单独配置。
- 如果调用方关闭自动状态切换,这个值可能不会被主渲染路径消费,但仍可能被其他显式状态管理逻辑当作约定信息。
## 测试覆盖
- `tests/Editor/test_viewport_host_surface_utils.cpp``tests/Editor/test_viewport_render_targets.cpp` 都验证了编辑器 surface 会保留调用方写入的 before 状态。
## 相关文档
- [返回类型总览](RenderSurface.md)
- [RenderSurface](RenderSurface.md)
- [GetColorStateBefore](GetColorStateBefore.md)
- [SetAutoTransitionEnabled](SetAutoTransitionEnabled.md)
- [SetColorStateAfter](SetColorStateAfter.md)

View File

@@ -1,6 +1,6 @@
# RenderSurface::SetDepthAttachment
设置深度附件。
设置 surface 的深度附件。
```cpp
void SetDepthAttachment(RHI::RHIResourceView* depthAttachment);
@@ -8,13 +8,28 @@ void SetDepthAttachment(RHI::RHIResourceView* depthAttachment);
## 参数
- `depthAttachment` - 深度模板附件视图。
- `depthAttachment` - 深度/模板视图;允许传入 `nullptr`
## 行为说明
## 当前语义
当前实现只会记录这个指针
- 当前实现只是把指针直接写入 `m_depthAttachment`,不会做额外资源操作
- 新值会覆盖旧值,不会尝试关闭、释放或验证旧附件。
- 保存的是非拥有裸指针,`RenderSurface` 不负责它的生命周期。
## 调用方影响
- `BuiltinForwardPipeline::Render()` 可以在深度附件为空时继续绑定颜色目标,只是深度清除和深度写入是否真正可用取决于具体后端与 pass 配置。
- `ScenePassRenderRequest::IsValid()` 与 [BuiltinDepthStylePassBase::Execute](../Passes/BuiltinDepthStylePassBase/Execute.md) 也把“深度附件非空”当作必要条件;否则 depth-only / shadow-caster 请求不会通过校验。
- `BuiltinObjectIdPass::Render()``BuiltinInfiniteGridPass::Render()` 都要求深度附件非空;否则会直接返回失败。
- `ObjectIdRenderRequest::IsValid()` 也把“深度附件非空”列为必要条件之一。
## 测试覆盖
- `tests/Editor/test_viewport_host_surface_utils.cpp``tests/Editor/test_viewport_render_targets.cpp` 都验证了 viewport surface 会把 depth view 写入这里。
## 相关文档
- [返回类型总览](RenderSurface.md)
- [RenderSurface](RenderSurface.md)
- [GetDepthAttachment](GetDepthAttachment.md)
- [SetColorAttachment](SetColorAttachment.md)
- [SetColorAttachments](SetColorAttachments.md)

View File

@@ -1,25 +1,32 @@
# RenderSurface::SetSize
设置当前表面尺寸
更新 surface 的宽度和高度
```cpp
void SetSize(uint32_t width, uint32_t height);
```
## 参数
- `width` - 宽度。
- `height` - 高度。
- `width` - 新的 surface 宽度。
- `height` - 新的 surface 高度。
## 行为说明
当前实现会更新内部记录的宽高,但不会同步修改附件对象本身。
当前实现会
如果当前已经启用了自定义 render area`SetSize(...)` 还会把现有 `m_renderArea` 重新夹到新的 surface 尺寸范围内,避免保留越界区域
1. 直接覆盖内部 `m_width``m_height`
2. 如果当前启用了自定义 render area再把已保存的矩形重新 clamp 到新的尺寸范围内。
3. 不修改颜色附件、深度附件、clear-color override、自动状态切换开关和颜色状态前后值。
## 当前实现边界
- `SetSize()` 不会验证已绑定附件的真实尺寸是否与新 surface 一致。
- 如果尺寸改小,自定义 render area 可能被裁剪,甚至变成 `0 x 0` 的空区域。
- 如果没有启用自定义 render area后续 [GetRenderArea](GetRenderArea.md) 会自动退回 `(0, 0, width, height)`
## 相关文档
- [返回类型总览](RenderSurface.md)
- [RenderSurface](RenderSurface.md)
- [GetWidth](GetWidth.md)
- [GetHeight](GetHeight.md)
- [SetRenderArea](SetRenderArea.md)

View File

@@ -4,37 +4,61 @@
**类型**: `module`
**描述**: 当前场景渲染主链路所在模块,覆盖 request 规划、场景提取、主管线执行、object-id 输出,以及调用方注入的 post / overlay pass。
**描述**: 当前场景渲染主链路所在模块,覆盖 request 规划、场景提取、主管线执行、shadow-caster / depth-only / object-id 输出,以及调用方注入的 pre / post / overlay pass。
## 概览
当前 `Rendering` 模块已经不是简单的“scene -> pipeline”两段式结构而是一条更完整的提交
当前 `Rendering` 模块已经不是简单的“scene -> pipeline”两段式结构而是一条更完整的提交流程
1. [SceneRenderer](SceneRenderer/SceneRenderer.md) 规划并排序 `CameraRenderRequest`
2. [CameraRenderer](CameraRenderer/CameraRenderer.md) 执行单个 request。
3. [RenderSceneExtractor](RenderSceneExtractor/RenderSceneExtractor.md) 生成 `RenderSceneData`
4. [RenderPipelineAsset](RenderPipelineAsset/RenderPipelineAsset.md) 决定当前主管线实例如何创建。
5. [RenderPipeline](RenderPipeline/RenderPipeline.md) 执行主场景绘制。
6. [ObjectIdPass](ObjectIdPass/ObjectIdPass.md) [Passes](Passes/Passes.md) 子模块补上 object-id、grid、outline 等附加阶段。
6. [ObjectIdPass](ObjectIdPass/ObjectIdPass.md) [Passes](Passes/Passes.md) 子模块补上 shadow-caster、depth-only、object-id、grid、outline 等附加阶段。
默认主链路当前是:
- [BuiltinForwardPipelineAsset](Pipelines/BuiltinForwardPipelineAsset/BuiltinForwardPipelineAsset.md)
- [BuiltinForwardPipeline](Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md)
这套分层本身就是当前渲染架构最重要的设计点。
- `SceneRenderer` / `SceneRenderRequestPlanner` 处理“这次该画什么、顺序是什么”
- `CameraRenderer` 处理“单个 request 怎样被真正执行”
- `RenderSceneExtractor` 处理“场景语义怎样压平成渲染语义”
- `RenderPipeline` 处理“压平后的渲染数据怎样落到 GPU”
对商业级引擎来说,这种拆法的价值很直接:
- 相机编排规则不会和具体 pipeline 绑死
- Editor 可以在 request 层注入 object-id、outline、overlay而不必改主管线
- 同一条主管线既能服务运行时,也能服务 Scene View、离屏目标和工具链
## 当前主流程
对一台相机的大致流程是:
1. `SceneRenderer` 生成 `CameraRenderRequest`
2. `CameraRenderer` 校验 request render-area。
2. `CameraRenderer` 校验 request render-area。
3. `RenderSceneExtractor` 基于相机和 render-area 提取 `RenderSceneData`
4. `RenderPipeline` 绘制主颜色目标
5. 如有需要,执行 object-id pass。
6. 执行 `postScenePasses``overlayPasses`
4. 执行 `preScenePasses`
5. 如有需要,执行 shadow-caster / depth-only scene pass。
6. `RenderPipeline` 绘制主颜色目标
7. 如有需要,执行 object-id pass。
8. 执行 `postScenePasses``overlayPasses`
Scene View 里的无限网格、选中轮廓和编辑器 overlay当前都不是 `CameraRenderer` 内部动态规划出来的,而是先在 Editor 层组装成 request plan再通过 `postScenePasses` / `overlayPasses` 接入这条主链。
如果你想理解这条链路里最容易写错的部分,优先看:
- 哪些相机会进入本次提交
- base / overlay 如何排序
- `CameraClearMode::Auto` 为什么不是无脑清颜色
- normalized viewport 怎样和已有 `RenderSurface::renderArea` 叠加
这些规则目前都集中收口在 request planning 这一层,而不是散落在 `CameraRenderer` 或 builtin pipeline 里。
## 材质与 shader 语义如何进入主链路
[RenderMaterialUtility](RenderMaterialUtility/RenderMaterialUtility.md) 当前负责把材质里的:
@@ -92,6 +116,7 @@ Scene View 里的无限网格、选中轮廓和编辑器 overlay当前都不
## 相关指南
- [Camera Request Planning And Clear Rules](../../_guides/Rendering/Camera-Request-Planning-And-Clear-Rules.md)
- [Scene Extraction And Builtin Forward Pipeline](../../_guides/Rendering/Scene-Extraction-And-Builtin-Forward-Pipeline.md)
## 相关文档

View File

@@ -11,9 +11,15 @@
## 概览
`SceneRenderRequestPlanner` 处在 [SceneRenderer](../SceneRenderer/SceneRenderer.md) 和 [SceneRenderRequestUtils](../SceneRenderRequestUtils/SceneRenderRequestUtils.md) 之间。
它不亲自渲染任何东西,而是把“应该渲染哪些相机、按什么顺序、哪些请求应该被丢弃”整理成一组 [CameraRenderRequest](../CameraRenderRequest/CameraRenderRequest.md)。
这种“先规划 request再执行 request”的拆法很接近商业引擎里常见的 camera scheduling 思路。它的价值不是抽象更漂亮,而是把两类会频繁变化的逻辑拆开:
- 场景侧规则相机收集、stack/depth 排序、clear 推导、viewport 解析
- 执行侧规则scene extraction、主管线、object-id、post/overlay pass
这样 Editor、离屏渲染和手工 request 注入都能复用同一套规划规则,而不用直接碰 `CameraRenderer` 内部执行链。
## 公开方法
| 方法 | 说明 |
@@ -40,9 +46,21 @@
- 已成功生成的 request 数量
这两个计数会影响自动 clear flag 的推导。
如果某个相机最终解析出的 render area 宽高为 `0`,该请求会被直接丢弃,而且不会错误地推进 base camera 计数。
## 设计取舍
当前 planner 故意保持“只做一件事”:
- 负责决定 request 集合
- 不负责 request 执行
- 不负责附加 pass 组装
这是一种比很多早期引擎实现更稳的做法。否则 Scene View 一旦要加 object-id、grid、selection outline、editor overlay规划逻辑和执行逻辑很容易在一个类里互相缠死。
另一个重要取舍是:当前只支持 base / overlay + depth 的线性排序,而不是更复杂的 stacking 依赖图。
这不是文档漏写,而是当前实现的真实边界。它优先保证顺序简单、稳定、可测试。
## 真实使用位置
- `engine/include/XCEngine/Rendering/SceneRenderer.h` 持有一个 `SceneRenderRequestPlanner` 实例。
@@ -63,3 +81,4 @@
- [SceneRenderer](../SceneRenderer/SceneRenderer.md)
- [SceneRenderRequestUtils](../SceneRenderRequestUtils/SceneRenderRequestUtils.md)
- [CameraRenderRequest](../CameraRenderRequest/CameraRenderRequest.md)
- [Camera Request Planning And Clear Rules](../../../_guides/Rendering/Camera-Request-Planning-And-Clear-Rules.md)

View File

@@ -11,12 +11,20 @@
## 概览
`SceneRenderRequestUtils.h` 是当前相机请求规划链路的规则库。
和 [SceneRenderRequestPlanner](../SceneRenderRequestPlanner/SceneRenderRequestPlanner.md) 的职责分工是:
- planner 决定“要处理哪些相机”
- utils 决定“这些相机和请求该怎样排序、怎样计算 clear、怎样落成具体 request”
从工程角度看,`SceneRenderRequestUtils` 其实承担的是“统一规则口径”的角色。它把多相机渲染里最容易在不同调用方之间写散掉的逻辑收口成一套 header-level helper
- 相机是否可用
- base / overlay 与 depth 的稳定排序
- `CameraClearMode::Auto` 的默认推导
- viewport 到最终 render area 的换算
这样 `SceneRenderer``SceneRenderRequestPlanner` 以及手工 request 提交路径,都能复用完全相同的规则。
## 公开规则
### 相机可用性
@@ -30,7 +38,7 @@
### 排序
`SortSceneCamerasForRendering()` `SortCameraRenderRequests()` 都使用 `std::stable_sort()`,因此在排序键完全相同的情况下,会保留原始相对顺序。
`SortSceneCamerasForRendering()` `SortCameraRenderRequests()` 都使用 `std::stable_sort()`,因此在排序键完全相同的情况下,会保留原始相对顺序。
当前排序键分别是:
@@ -45,16 +53,21 @@
- `DepthOnly` -> `RenderClearFlags::Depth`
- `None` -> `RenderClearFlags::None`
- `Auto`
- overlay camera: 本次若还是个已渲染 request则清 `All`,否则只清 `Depth`
- overlay camera: 本次若还是第一个已渲染 request则清 `All`,否则只清 `Depth`
- base camera: 若还没有任何成功渲染的 base camera则清 `All`,否则只清 `Depth`
这里最值得注意的是overlay camera 不是永远只清 `Depth`
如果场景里根本没有 base camera第一个成功进入队列的 overlay request 仍然会回退到 `All`。这保证了“纯 overlay 场景”也能得到一个稳定起始帧,而不会直接叠到未定义颜色上。
### render area 计算
`ResolveCameraRenderArea()` 会把相机 `viewportRect` 解释`RenderSurface` 当前 render area 的归一化子矩形:
`ResolveCameraRenderArea()` 会把相机 `viewportRect` 解释`RenderSurface` 当前 render area 的归一化子矩形:
- 左上边界使用 `floor`
- 右下边界使用 `ceil`
这意味着当前系统支持“在已有 render area 上再切子视口”,而不只是对整张 surface 做 0..1 映射。这对 Scene View、离屏窗口和分块渲染都很关键。
### request 组装
`BuildCameraRenderRequest()` 当前会:
@@ -87,3 +100,4 @@
- [SceneRenderRequestPlanner](../SceneRenderRequestPlanner/SceneRenderRequestPlanner.md)
- [CameraRenderRequest](../CameraRenderRequest/CameraRenderRequest.md)
- [SceneRenderer](../SceneRenderer/SceneRenderer.md)
- [Camera Request Planning And Clear Rules](../../../_guides/Rendering/Camera-Request-Planning-And-Clear-Rules.md)

View File

@@ -1,24 +1,30 @@
# SceneRenderer::SceneRenderer
构造一个场景级渲染器。
```cpp
SceneRenderer();
explicit SceneRenderer(std::unique_ptr<RenderPipeline> pipeline);
explicit SceneRenderer(std::shared_ptr<const RenderPipelineAsset> pipelineAsset);
```
## 行为说明
## 当前语义
三个构造路径都只是决定内部 `m_cameraRenderer` 如何初始化
- 默认构造:使用默认构造的 `CameraRenderer`
- `std::unique_ptr<RenderPipeline>`:把手工注入的 runtime pipeline 交给 `CameraRenderer`
- `std::shared_ptr<const RenderPipelineAsset>`:让 `CameraRenderer` 从 asset 创建 runtime pipeline。
- 三个构造路径的差别只在于内部 `m_cameraRenderer` 如何初始化
- 默认构造:使用 `CameraRenderer` 的默认构造路径,最终回退到默认 builtin forward pipeline asset。
- `std::unique_ptr<RenderPipeline>` 构造:把调用方提供的 runtime pipeline 直接交给内部 `CameraRenderer` 持有
- `std::shared_ptr<const RenderPipelineAsset>` 构造:让内部 `CameraRenderer` 通过 asset 创建 runtime pipeline
## 当前实现细节
- 默认构造函数本身没有额外逻辑,`SceneRenderer::SceneRenderer() = default;`
- 如果传入的 `pipeline` 为空`CameraRenderer` 内部会回退到默认 pipeline asset 并重新创建默认主管线
- 如果传入的 `pipelineAsset` 为空,`CameraRenderer` 也会回退到默认 [BuiltinForwardPipelineAsset](../Pipelines/BuiltinForwardPipelineAsset/BuiltinForwardPipelineAsset.md)
- `SceneRenderer` 自己不在构造阶段创建额外的 GPU 资源;真正的 runtime pipeline 创建和回退逻辑都委托给 `CameraRenderer`
- 如果传入的 `pipeline` 是空指针`CameraRenderer` 会回退到默认 pipeline asset,而不是保留一个永久空 pipeline
- 如果传入的 `pipelineAsset` 是空指针,也会回退到默认 builtin forward asset
## 测试覆盖
- `tests/Rendering/unit/test_camera_scene_renderer.cpp` 验证了默认构造的 `SceneRenderer` 能创建默认 pipeline 并完成渲染。
- 同一测试文件也覆盖了注入 runtime pipeline 和注入 pipeline asset 两条构造路径。
## 相关文档

View File

@@ -1,19 +1,30 @@
# SceneRenderer::~SceneRenderer
销毁场景级渲染器对象。
```cpp
~SceneRenderer() = default;
```
## 行为说明
## 当前语义
`SceneRenderer` 自身没有自定义析构逻辑。真正的资源关闭发生在成员析构阶段:
- `SceneRenderer` 自身没有自定义析构逻辑。
- 真正的 teardown 发生在成员对象析构阶段:
- `m_cameraRenderer` 会关闭当前 runtime pipeline 和 object-id pass。
- `m_requestPlanner` 作为普通值成员按常规方式销毁。
- `SceneRenderer` 不拥有外部传入请求上的 `RenderPassSequence`,因此析构时不会回收这些外部序列对象。
- `m_cameraRenderer` 会在自身析构里关闭当前主管线和 object-id passrequest 级 `RenderPassSequence` 的生命周期则由每次 `Render()` 调用自行初始化和回收。
- `m_requestPlanner` 按普通值成员销毁。
## 调用方影响
因此当前析构语义是“把 teardown 责任完全交给内部 `CameraRenderer`”,而不是在 `SceneRenderer` 层重复写一套 shutdown 流程
- 即使 `SceneRenderer` 的析构函数是 `= default`,离开作用域时仍会触发内部 `CameraRenderer` 的资源释放路径
- 任何此前通过 [GetPipeline](GetPipeline.md) 或 [GetPipelineAsset](GetPipelineAsset.md) 观察到的非拥有指针,都会在 `SceneRenderer` 销毁后失效。
## 测试覆盖
- `tests/Rendering/unit/test_camera_scene_renderer.cpp` 使用作用域退出断言了 `SceneRenderer` 内部持有的 pipeline 会在对象销毁时执行 `Shutdown()`
## 相关文档
- [SceneRenderer](SceneRenderer.md)
- [CameraRenderer](../CameraRenderer/CameraRenderer.md)
- [GetPipeline](GetPipeline.md)
- [Render](Render.md)

View File

@@ -1,22 +1,32 @@
# SceneRenderer::GetPipeline
返回当前场景渲染器正在使用的 runtime pipeline。
```cpp
RenderPipeline* GetPipeline() const;
```
## 行为说明
直接返回内部 `m_cameraRenderer.GetPipeline()` 的结果。
## 返回值
- 当前主管线的非拥有指针
- 返回内部 `m_cameraRenderer.GetPipeline()` 的结果
## 注意事项
## 当前语义
-个指针既可能指向手工注入的 runtime pipeline也可能指向由 pipeline asset 创建的实例。
- 调用 [SetPipeline](SetPipeline.md) 或 [SetPipelineAsset](SetPipelineAsset.md) 后,返回的对象可能变化。
- 默认构造下通常会返回由默认 [BuiltinForwardPipelineAsset](../Pipelines/BuiltinForwardPipelineAsset/BuiltinForwardPipelineAsset.md) 创建的主管线实例
-是一个非拥有裸指针,只用于观察当前绑定的是哪一个 `RenderPipeline` 实例。
- 该指针可能指向:
- 手动注入的 runtime pipeline
- 由当前 pipeline asset 创建出的 runtime pipeline。
- 在空指针回退路径中自动补出的默认 builtin forward pipeline。
- 调用 [SetPipeline](SetPipeline.md) 或 [SetPipelineAsset](SetPipelineAsset.md) 后,这个指针都可能变化。
## 调用方影响
- 不应跨生命周期长期缓存这个指针;`SceneRenderer` 销毁、替换 pipeline 或回退默认 pipeline 后,它都可能失效。
- 它也不是“可由外部 delete 的所有权句柄”;真正的持有者仍是内部 `CameraRenderer`
## 测试覆盖
- `tests/Rendering/unit/test_camera_scene_renderer.cpp` 覆盖了替换 pipeline 前后 `GetPipeline()` 返回值的变化,以及旧 pipeline 被 `Shutdown()` 的行为。
## 相关文档

View File

@@ -1,21 +1,30 @@
# SceneRenderer::GetPipelineAsset
返回当前场景渲染器绑定的 pipeline asset。
```cpp
const RenderPipelineAsset* GetPipelineAsset() const;
```
## 行为说明
直接返回内部 `m_cameraRenderer.GetPipelineAsset()` 的结果。
## 返回值
- 当前绑定的 pipeline asset 的非拥有指针
- 如果最近一次切换是通过 [SetPipeline](SetPipeline.md) 手工注入 runtime pipeline则这里可能为 `nullptr`
- 返回内部 `m_cameraRenderer.GetPipelineAsset()` 的结果
## 当前默认行为
## 当前语义
默认构造的 `SceneRenderer` 通常会返回默认 [BuiltinForwardPipelineAsset](../Pipelines/BuiltinForwardPipelineAsset/BuiltinForwardPipelineAsset.md)
- 这是一个非拥有观察指针,用来回答“当前 runtime pipeline 是由哪个 asset 工厂派生出来的”
- 默认构造的 `SceneRenderer` 通常会返回默认 builtin forward pipeline asset。
- 如果最近一次切换是 [SetPipeline](SetPipeline.md) 且传入了非空 runtime pipeline这里会变成 `nullptr`,因为那条路径会清掉当前 asset 绑定。
- 如果 [SetPipelineAsset](SetPipelineAsset.md) 传入空指针,内部不会保留 `nullptr`,而是回退到默认 builtin forward asset。
## 调用方影响
- 这不是 `shared_ptr` 的外露别名,不提供所有权,也不保证在 `SceneRenderer` 生命周期之外继续有效。
- 对外部来说,它更适合做调试、状态展示或测试断言,而不适合做长期缓存键。
## 测试覆盖
- `tests/Rendering/unit/test_camera_scene_renderer.cpp` 覆盖了默认 asset、替换 asset以及替换 runtime pipeline 后 asset 观察值的变化。
## 相关文档

View File

@@ -20,6 +20,15 @@
1. `SceneRenderer` 负责“这次要渲染哪些相机、按什么顺序、每个请求的 surface/render-area/clear-flags 是什么”。
2. `CameraRenderer` 负责“单个请求如何真正跑完”。
这条边界是当前 Rendering 模块里最值得保留的设计决定之一。
如果把相机规划和 request 执行重新揉回一个类里Editor 的 Scene View、object-id picking、overlay 注入和离屏渲染很快就会和主管线细节耦合到一起。
现在的拆法则让 `SceneRenderer` 更像一个稳定的编排入口:
-`Scene` 直接提交时,它负责生成 request
- 从外部手工提交 request 时,它负责复用同一排序规则
- 不管 request 来源是什么,真正执行都统一落到 `CameraRenderer`
## 当前执行路径
### `BuildRenderRequests(...)`
@@ -50,6 +59,8 @@ return Render(BuildRenderRequests(scene, overrideCamera, context, surface));
这里不会额外改写 request 里的 `objectId` 或各类 pass sequence如果上层已经补好了这些字段`SceneRenderer` 只负责排序后转交执行。
这也是为什么手工 request 提交路径仍然会再次排序。当前实现明确认为“stack/depth 规则”属于 `SceneRenderer` 的稳定契约,而不是调用方各自维护的一套隐式约定。
### `Render(const CameraRenderRequest&)`
这是最薄的一层,直接转发到 `m_cameraRenderer.Render(request)`
@@ -66,7 +77,7 @@ return Render(BuildRenderRequests(scene, overrideCamera, context, surface));
- 不直接做 scene extraction真正的 `RenderSceneExtractor` 调用发生在 `CameraRenderer` 里。
- 不直接操作 `RenderPipeline` 的初始化或渲染细节;它只负责请求规划和排序。
- 不负责替 request 自动补 `objectId` 或各类 `RenderPassSequence`;这类附加阶段通常由 Editor 或其上层调用方在提交前写入。
- 不负责替 request 自动补 `objectId` 或各类 `RenderPassSequence`;这类附加阶段通常由 Editor 或其上层调用方在提交前写入。
- 对手工提交的请求数组,会再次按相机优先级稳定排序,而不是按调用方原始顺序盲目执行。
## 测试覆盖
@@ -77,6 +88,13 @@ return Render(BuildRenderRequests(scene, overrideCamera, context, surface));
- 手工提交请求数组时的排序和稳定性。
- `SetPipeline()` / `SetPipelineAsset()` 的转发、替换与 shutdown 行为。
这些测试锚点说明,`SceneRenderer` 当前不是一个“薄到没有语义”的转发器。它真正承担了 request planning 契约本身,包括:
- override camera 的回退语义
- base / overlay 排序
- `Auto` clear 的默认策略
- 手工 request 重新排序的稳定性
## 公开方法
| 方法 | 说明 |
@@ -97,3 +115,4 @@ return Render(BuildRenderRequests(scene, overrideCamera, context, surface));
- [SceneRenderRequestPlanner](../SceneRenderRequestPlanner/SceneRenderRequestPlanner.md)
- [SceneRenderRequestUtils](../SceneRenderRequestUtils/SceneRenderRequestUtils.md)
- [RenderSceneExtractor](../RenderSceneExtractor/RenderSceneExtractor.md)
- [Camera Request Planning And Clear Rules](../../../_guides/Rendering/Camera-Request-Planning-And-Clear-Rules.md)

View File

@@ -1,26 +1,34 @@
# SceneRenderer::SetPipelineAsset
切换当前场景渲染器使用的 pipeline asset。
```cpp
void SetPipelineAsset(std::shared_ptr<const RenderPipelineAsset> pipelineAsset);
```
## 行为说明
## 参数
当前实现直接转发到内部 `m_cameraRenderer.SetPipelineAsset(...)`
- `pipelineAsset` - 目标 pipeline asset;允许传入空指针
## 当前语义
- 如果传入 asset 非空,后续主管线实例来自这个 asset
- 如果传入 asset 空,会回退到默认 [BuiltinForwardPipelineAsset](../Pipelines/BuiltinForwardPipelineAsset/BuiltinForwardPipelineAsset.md)
- 被替换掉的旧 runtime pipeline 会先执行 `Shutdown()`,再由新 asset 创建新的实例
- 当前实现直接转发到内部 `m_cameraRenderer.SetPipelineAsset(...)`
- 如果传入 asset 空,后续 runtime pipeline 会由该 asset 创建
- 如果传入 asset 为空,内部会回退到默认 builtin forward pipeline asset而不是保留空绑定
- 被替换掉的旧 runtime pipeline 会先执行 `Shutdown()`,再由新 asset 创建新实例。
## 参数
## 调用方影响
- `pipelineAsset` - 当前主管线工厂,可为空
- 调用之后,[GetPipelineAsset](GetPipelineAsset.md) 和 [GetPipeline](GetPipeline.md) 的返回值都可能变化
- 任何此前缓存的旧 pipeline 指针都应视为潜在失效。
- 如果调用方只是想直接接管 runtime pipeline而不是保留 asset 工厂关系,应改用 [SetPipeline](SetPipeline.md)。
## 测试覆盖
- `tests/Rendering/unit/test_camera_scene_renderer.cpp` 验证了替换 asset 时旧 pipeline 会被 `Shutdown()`,并且新 asset 会创建新的 runtime pipeline 实例。
## 相关文档
- [SceneRenderer](SceneRenderer.md)
- [SetPipeline](SetPipeline.md)
- [GetPipelineAsset](GetPipelineAsset.md)
- [CameraRenderer::SetPipelineAsset](../CameraRenderer/SetPipelineAsset.md)