diff --git a/docs/api/XCEngine/Rendering/CameraRenderer/CameraRenderer.md b/docs/api/XCEngine/Rendering/CameraRenderer/CameraRenderer.md index 94ebc8a9..b144f7c4 100644 --- a/docs/api/XCEngine/Rendering/CameraRenderer/CameraRenderer.md +++ b/docs/api/XCEngine/Rendering/CameraRenderer/CameraRenderer.md @@ -6,80 +6,90 @@ **头文件**: `XCEngine/Rendering/CameraRenderer.h` -**描述**: 面向单个 `CameraRenderRequest` 的渲染执行器,负责场景提取、主管线提交、object-id 输出和 builtin post-process 串接。 +**描述**: 单个 `CameraRenderRequest` 的执行器。它负责在一次相机提交里完成场景提取、主管线渲染、object-id 输出,以及 builtin post-process / overlay pass 的串接。 ## 概览 -`CameraRenderer` 是当前渲染模块里的“单相机执行层”。它不负责从场景里挑哪些相机,也不负责对多个请求排序;这些工作由 [SceneRenderer](../SceneRenderer/SceneRenderer.md) 处理。它关心的是如何把一份 [CameraRenderRequest](../CameraRenderRequest/CameraRenderRequest.md) 真正跑完: +`CameraRenderer` 是当前渲染模块里的“单请求执行层”。和 [SceneRenderer](../SceneRenderer/SceneRenderer.md) 的分工是: -1. 校验请求和 render area。 -2. 用 `RenderSceneExtractor` 提取该相机视角下的 `RenderSceneData`。 -3. 执行主 `RenderPipeline`。 -4. 按需执行 `ObjectIdPass`。 -5. 执行调用方注入的 pre / post / overlay pass。 -6. 构建并执行 builtin post-process 序列。 +- `SceneRenderer` 负责规划和排序 `CameraRenderRequest`。 +- `CameraRenderer` 负责把一份 request 真正跑完。 -因此它已经不只是“单纯把场景交给 pipeline”,而是当前 camera submission 的主要编排器。 +因此这里关心的不是“该渲染哪些相机”,而是“这一个相机请求如何被执行”。 -## 持有的运行时对象 +## 当前持有的运行时对象 -- `m_sceneExtractor`:负责按相机和 render area 抽取可见物体。 -- `m_pipelineAsset`:可选,表示当前管线来自哪份资产工厂。 -- `m_pipeline`:当前实际执行主场景绘制的管线实例。 -- `m_objectIdPass`:主场景之后的 object-id 输出 pass,默认是 `Passes::BuiltinObjectIdPass`。 -- `m_builtinPostProcessBuilder`:把无限网格、selection outline、debug mask 组装成 `RenderPassSequence`。 - -## 生命周期与所有权 - -- 默认构造会回退到内建前向管线资产,并默认创建 builtin object-id pass。 -- 手动注入 `RenderPipeline` 时,`CameraRenderer` 通过 `std::unique_ptr` 接管所有权。 -- 通过 [SetPipelineAsset](SetPipelineAsset.md) 走的是“资产创建实例”路径;通过 [SetPipeline](SetPipeline.md) 走的是“手动注入实例”路径。 -- 析构时会依次 `Shutdown()` 当前管线、当前 object-id pass,以及 builtin post-process builder。 +- `m_sceneExtractor` + 使用 `request.surface` 的 render-area 尺寸调用 `ExtractForCamera(...)`,生成这次提交要用的 `RenderSceneData`。 +- `m_pipelineAsset` + 当前主管线的来源工厂;可能为空。 +- `m_pipeline` + 当前实际执行主场景绘制的 runtime [RenderPipeline](../RenderPipeline/RenderPipeline.md)。 +- `m_objectIdPass` + 主场景之后的 object-id pass;默认是 [Passes::BuiltinObjectIdPass](../Passes/BuiltinObjectIdPass/BuiltinObjectIdPass.md)。 +- `m_builtinPostProcessBuilder` + 把 builtin grid、selection outline、debug mask 请求翻译成临时 `RenderPassSequence`。 ## 当前执行顺序 -对一份有效请求,`Render()` 的顺序是: +对一份有效 request,当前 `Render()` 的主顺序是: -1. `preScenePasses` -2. 主 `m_pipeline->Render(...)` -3. `m_objectIdPass->Render(...)`,如果请求了 object-id 输出 -4. `postScenePasses` -5. builtin post-process 序列 -6. `overlayPasses` +1. 校验 request、自身主管线、render-area、object-id 请求和 builtin post-process 前置条件。 +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. 如请求了 builtin post-process,先由 builder 生成临时 sequence,再执行它。 +9. 执行 `overlayPasses`。 +10. 按已初始化的 sequence 逆向 `Shutdown()`。 -这条顺序在 `tests/Rendering/unit/test_camera_scene_renderer.cpp` 里被明确验证过。 +这条顺序被 `tests/Rendering/unit/test_camera_scene_renderer.cpp` 明确覆盖。 + +## 生命周期与回退策略 + +- 默认构造会使用静态共享的 [BuiltinForwardPipelineAsset](../Pipelines/BuiltinForwardPipelineAsset/BuiltinForwardPipelineAsset.md)。 +- `SetPipeline()` 走“手动注入 runtime pipeline”路径,并清空当前 `m_pipelineAsset`。 +- `SetPipelineAsset()` 走“由 asset 创建 runtime pipeline”路径;传空时会回退到默认 asset。 +- `ResetPipeline()` 会先 `Shutdown()` 旧主管线,再接管新实例;若新实例为空,则再次回退到默认 asset 并创建 builtin forward。 +- `SetObjectIdPass()` 同样会先关闭旧 pass;传空时回退到 builtin object-id pass。 + +## 当前验证规则 + +`Render()` 目前会显式拒绝: + +- `request.IsValid()` 为假。 +- 当前 `m_pipeline == nullptr`。 +- `request.surface` 的 render-area 宽或高为 `0`。 +- 请求了 object-id,但 `request.objectId.IsValid()` 为假。 +- 请求了 builtin post-process,且提供了 `objectIdTextureView`,但这次 request 并没有真正请求 fresh object-id 输出。 ## 当前实现边界 -- 只处理单个相机请求,多相机排序和 camera stack 语义在更上层完成。 -- 主场景提取尺寸取自 `surface` 的 render area,而不是整张 surface 的宽高。 -- builtin post-process 当前依赖 object-id SRV、scene viewport grid 数据和 `Passes` 子模块,不是通用 render graph。 -- 没有内部锁;替换管线、替换 object-id pass 和执行渲染都假定由拥有明确时序的线程调用。 +- 只执行单个 request;多相机排序、stack 顺序和 clear 规则在 `SceneRenderer` / `SceneRenderRequestPlanner` 层完成。 +- 不直接决定“默认主管线是什么”,而是通过 pipeline asset seam 解决。 +- builtin post-process 仍然是顺序执行的 pass sequence,不是 render graph。 ## 公开方法 | 方法 | 说明 | |------|------| -| [Constructor](Constructor.md) | 创建渲染器,并建立默认或注入的主管线 / object-id pass。 | -| [Destructor](Destructor.md) | 关闭当前管线、object-id pass 和 builtin post-process builder。 | -| [SetPipeline](SetPipeline.md) | 手动替换当前主管线实例,并清空当前 pipeline asset 来源。 | -| [SetPipelineAsset](SetPipelineAsset.md) | 通过 `RenderPipelineAsset` 重建主管线实例。 | +| [Constructor](Constructor.md) | 构造 `CameraRenderer`,并建立默认或注入的主管线 / object-id pass。 | +| [Destructor](Destructor.md) | 关闭当前主管线、object-id pass 和 builtin post-process builder。 | +| [SetPipeline](SetPipeline.md) | 手动替换当前 runtime pipeline。 | +| [SetPipelineAsset](SetPipelineAsset.md) | 通过 `RenderPipelineAsset` 重建当前 runtime pipeline。 | | [SetObjectIdPass](SetObjectIdPass.md) | 替换当前 object-id pass。 | -| [GetPipeline](GetPipeline.md) | 读取当前主管线裸指针。 | -| [GetPipelineAsset](GetPipelineAsset.md) | 读取当前 pipeline asset 裸指针。 | -| [GetObjectIdPass](GetObjectIdPass.md) | 读取当前 object-id pass 裸指针。 | -| [Render](Render.md) | 执行一次完整的单相机渲染提交流程。 | - -## 真实使用位置 - -- `SceneRenderer::Render(...)` 会把排序后的 `CameraRenderRequest` 逐个交给它。 -- 编辑器 scene viewport 通过 `CameraRenderRequest.objectId` 与 `builtinPostProcess` 接到这里。 -- `tests/Rendering/unit/test_camera_scene_renderer.cpp` 覆盖了 clear override、render area、注入 pass 顺序、pipeline asset 替换和 object-id 失败回退等关键行为。 +| [GetPipeline](GetPipeline.md) | 读取当前主管线的非拥有指针。 | +| [GetPipelineAsset](GetPipelineAsset.md) | 读取当前 pipeline asset 的非拥有指针。 | +| [GetObjectIdPass](GetObjectIdPass.md) | 读取当前 object-id pass 的非拥有指针。 | +| [Render](Render.md) | 执行一次完整的单相机提交。 | ## 相关文档 -- [CameraRenderRequest](../CameraRenderRequest/CameraRenderRequest.md) +- [Rendering](../Rendering.md) - [SceneRenderer](../SceneRenderer/SceneRenderer.md) +- [CameraRenderRequest](../CameraRenderRequest/CameraRenderRequest.md) +- [RenderSceneExtractor](../RenderSceneExtractor/RenderSceneExtractor.md) - [RenderPipeline](../RenderPipeline/RenderPipeline.md) -- [Passes](../Passes/Passes.md) - [Scene Extraction And Builtin Forward Pipeline](../../../_guides/Rendering/Scene-Extraction-And-Builtin-Forward-Pipeline.md) diff --git a/docs/api/XCEngine/Rendering/CameraRenderer/Constructor.md b/docs/api/XCEngine/Rendering/CameraRenderer/Constructor.md index 87dcc672..b9793830 100644 --- a/docs/api/XCEngine/Rendering/CameraRenderer/Constructor.md +++ b/docs/api/XCEngine/Rendering/CameraRenderer/Constructor.md @@ -1,13 +1,5 @@ # CameraRenderer::Constructor -**命名空间**: `XCEngine::Rendering` - -**类型**: `constructor` - -**头文件**: `XCEngine/Rendering/CameraRenderer.h` - -## 签名 - ```cpp CameraRenderer(); explicit CameraRenderer(std::unique_ptr pipeline); @@ -17,39 +9,42 @@ CameraRenderer( std::unique_ptr objectIdPass); ``` -## 作用 +## 行为说明 -创建一个能够执行单相机请求的 `CameraRenderer`,并为它准备主管线来源与 object-id pass。 +构造函数的核心职责是决定两件事: -## 当前实现行为 +- 当前主管线实例从哪里来。 +- 当前 object-id pass 是否使用默认 builtin 实现。 + +## 当前构造路径 ### 默认构造 -- 通过内部静态 `CreateDefaultPipelineAsset()` 取得 `Pipelines::BuiltinForwardPipelineAsset`。 -- 再走 pipeline asset 构造路径创建默认主管线。 -- 同时默认创建 `Passes::BuiltinObjectIdPass`。 +- 调用内部静态 `CreateDefaultPipelineAsset()`。 +- 默认 asset 是共享的 [BuiltinForwardPipelineAsset](../Pipelines/BuiltinForwardPipelineAsset/BuiltinForwardPipelineAsset.md)。 +- 随后走 asset 构造路径生成主管线。 ### `std::unique_ptr` 重载 -- 接管调用方给出的主管线实例。 -- 如果 `objectIdPass` 没显式传入,则默认补一个 `Passes::BuiltinObjectIdPass`。 +- 交由 `(pipeline, objectIdPass)` 这个双参重载处理。 +- 如果未显式提供 object-id pass,默认补一个 [Passes::BuiltinObjectIdPass](../Passes/BuiltinObjectIdPass/BuiltinObjectIdPass.md)。 ### `std::shared_ptr` 重载 -- 保存 asset 指针。 -- 通过 `SetPipelineAsset()` 立即从 asset 创建一个新的主管线实例。 -- 同时默认创建 `Passes::BuiltinObjectIdPass`。 +- 先保存 asset。 +- 再调用 [SetPipelineAsset](SetPipelineAsset.md),立即由 asset 创建 runtime pipeline。 +- 默认同时创建 builtin object-id pass。 ### `(pipeline, objectIdPass)` 重载 -- 同时接管主管线和 object-id pass。 -- 如果传入的 `objectIdPass` 为空,会自动回退成 `Passes::BuiltinObjectIdPass`。 -- 如果传入的 `pipeline` 为空,`ResetPipeline()` 会进一步回退到默认 pipeline asset 创建的内建前向管线。 +- 若 `objectIdPass` 为空,自动回退到 builtin object-id pass。 +- 调用内部 `ResetPipeline(std::move(pipeline))`。 +- 如果传入 `pipeline` 为空,`ResetPipeline()` 会继续回退到默认 pipeline asset,并创建 builtin forward 主管线。 ## 所有权 -- `RenderPipeline` 与 `ObjectIdPass` 都由 `CameraRenderer` 独占持有。 -- `RenderPipelineAsset` 以 `shared_ptr` 形式共享持有,仅作为“如何创建管线实例”的来源。 +- `RenderPipeline` 和 `ObjectIdPass` 由 `CameraRenderer` 以 `std::unique_ptr` 独占持有。 +- `RenderPipelineAsset` 以 `std::shared_ptr` 共享持有,只作为 runtime pipeline 的创建来源。 ## 相关文档 diff --git a/docs/api/XCEngine/Rendering/CameraRenderer/Render.md b/docs/api/XCEngine/Rendering/CameraRenderer/Render.md index 6c68a8bd..87714876 100644 --- a/docs/api/XCEngine/Rendering/CameraRenderer/Render.md +++ b/docs/api/XCEngine/Rendering/CameraRenderer/Render.md @@ -1,81 +1,68 @@ # CameraRenderer::Render -**命名空间**: `XCEngine::Rendering` - -**类型**: `method` - -**头文件**: `XCEngine/Rendering/CameraRenderer.h` - -## 签名 - ```cpp bool Render(const CameraRenderRequest& request); ``` -## 作用 +## 行为说明 -执行一次完整的单相机渲染提交,包括主场景、object-id 输出、调用方注入 pass 和 builtin 后处理。 +执行一次完整的单相机提交。当前实现会把主场景、object-id、注入 pass 和 builtin post-process 串成一条固定顺序的执行链。 -## 当前实现流程 +## 当前流程 -按 `engine/src/Rendering/CameraRenderer.cpp`,当前流程是: - -1. 如果 `request.IsValid()` 为假,或 `m_pipeline == nullptr`,返回 `false`。 -2. 如果 `request.surface` 的 render area 宽高为 `0`,返回 `false`。 -3. 如果请求了 `objectId` 但 `objectId.IsValid()` 为假,返回 `false`。 -4. 如果 builtin post-process 里提供了 `objectIdTextureView`,但这次请求并没有真正请求 `objectId` 输出,返回 `false`。 +1. 校验 `request.IsValid()`,并确认 `m_pipeline` 非空。 +2. 拒绝 render-area 宽高为 `0` 的 surface。 +3. 如果请求了 object-id,要求 `request.objectId.IsValid()` 为真。 +4. 如果 builtin post-process 依赖 `objectIdTextureView`,则要求本次 request 真的请求了 fresh object-id 输出。 5. 用 `request.surface.GetRenderAreaWidth()` / `GetRenderAreaHeight()` 调用 `m_sceneExtractor.ExtractForCamera(...)`。 -6. 如果提取结果 `sceneData.HasCamera()` 为假,返回 `false`。 -7. 用 `request.clearFlags` 覆盖 `sceneData.cameraData.clearFlags`;如有需要,再用 `clearColorOverride` 覆盖 `sceneData.cameraData.clearColor`。 -8. 依次执行: +6. 若 `sceneData.HasCamera()` 为假,则返回 `false`。 +7. 用 request 覆盖 `sceneData.cameraData.clearFlags`;如果 request 提供了 clear-color override,则继续覆盖 `sceneData.cameraData.clearColor`。 +8. 依次初始化并执行: - `preScenePasses` - - 主 `m_pipeline->Render(...)` - - `m_objectIdPass->Render(...)`,如果请求了 object-id + - `m_pipeline->Render(...)` + - `m_objectIdPass->Render(...)` - `postScenePasses` - - builtin post-process 序列 + - builtin post-process 临时 sequence - `overlayPasses` -9. 每个阶段失败时,按已经初始化过的 pass 序列倒序 `Shutdown()` 并返回 `false`。 +9. 按已经成功初始化的 sequence 做逆向 `Shutdown()`。 ## builtin post-process 接入点 -如果 `request.builtinPostProcess.IsRequested()` 为真,`Render()` 会: +当 `request.builtinPostProcess.IsRequested()` 为真时,当前实现会: -1. 调用 `m_builtinPostProcessBuilder.Build(...)` 生成一个临时 `RenderPassSequence`。 -2. 对这个序列执行 `Initialize(context)`。 +1. 调用 `m_builtinPostProcessBuilder.Build(...)` 生成一条临时 `RenderPassSequence`。 +2. 对这条临时 sequence 调用 `Initialize(context)`。 3. 在 `postScenePasses` 之后、`overlayPasses` 之前执行它。 -这意味着 scene viewport 的无限网格、selection outline 和 debug mask 都是在主场景绘制完成之后叠加的。 +这意味着 scene viewport 的 builtin grid、selection outline 和 debug mask 都是主场景之后叠加的。 + +## 失败与清理语义 + +- 任一验证失败会直接返回 `false`。 +- 任一 sequence 初始化失败会立即执行对应 `Shutdown()` 回滚。 +- 主主管线、object-id pass、post-process 或 overlay 任一阶段失败,都会按已经初始化过的 sequence 做清理再返回 `false`。 ## 参数 -| 参数 | 说明 | -|------|------| -| `request` | 本次单相机渲染的完整输入。 | +- `request` - 本次单相机渲染的完整输入。 ## 返回值 -- 返回 `true`:主流程和所有已请求的附加阶段都成功执行。 -- 返回 `false`:请求校验失败、场景提取失败、主管线失败,或任意一个附加 pass 阶段失败。 - -## 关键语义 - -- 相机视口尺寸来自 `surface` 的 render area,而不是整张 surface 的宽高。 -- object-id pass 位于主场景之后、`postScenePasses` 之前。 -- builtin post-process 位于 `postScenePasses` 之后、`overlayPasses` 之前。 -- builder 负责决定 selection outline / debug mask 的具体回退策略,`CameraRenderer` 只负责执行 builder 给出的结果。 +- 整条提交链成功执行时返回 `true`。 +- request 校验失败、场景提取失败、主管线失败,或任一附加阶段失败时返回 `false`。 ## 测试覆盖 `tests/Rendering/unit/test_camera_scene_renderer.cpp` 当前验证了: -- render area 会影响提取到的相机视口尺寸 -- `clearFlags` 和 clear color override 会写回 `sceneData.cameraData` -- pre / post / object-id pass 的执行顺序 -- object-id pass 失败和 post-pass 初始化失败时的清理路径 -- builtin post-process 在缺少 fresh object-id 数据时会被拒绝 +- render-area 会影响提取到的相机 viewport 尺寸。 +- clear-flags 与 clear-color override 会写回 `sceneData.cameraData`。 +- pre / pipeline / object-id / post / builtin / overlay 的执行顺序。 +- object-id 失败、post-pass 初始化失败和 builtin post-process 验证失败时的回滚路径。 ## 相关文档 +- [CameraRenderer](CameraRenderer.md) - [CameraRenderRequest](../CameraRenderRequest/CameraRenderRequest.md) - [RenderSceneExtractor](../RenderSceneExtractor/RenderSceneExtractor.md) - [RenderPipeline::Render](../RenderPipeline/Render.md)