diff --git a/tests/RHI/CMakeLists.txt b/tests/RHI/CMakeLists.txt index 9851fef2..0495f978 100644 --- a/tests/RHI/CMakeLists.txt +++ b/tests/RHI/CMakeLists.txt @@ -9,3 +9,53 @@ add_subdirectory(D3D12) add_subdirectory(OpenGL) add_subdirectory(unit) add_subdirectory(integration) + +add_custom_target(rhi_abstraction_unit_tests + DEPENDS + rhi_unit_tests +) + +add_custom_target(rhi_abstraction_integration_tests + DEPENDS + rhi_integration_minimal + rhi_integration_triangle + rhi_integration_quad + rhi_integration_sphere + rhi_integration_backpack +) + +add_custom_target(rhi_abstraction_tests + DEPENDS + rhi_abstraction_unit_tests + rhi_abstraction_integration_tests +) + +add_custom_target(rhi_backend_unit_tests + DEPENDS + rhi_d3d12_tests + rhi_opengl_tests +) + +add_custom_target(rhi_backend_integration_tests + DEPENDS + d3d12_minimal_test + d3d12_triangle_test + d3d12_quad_test + d3d12_sphere_test + opengl_minimal_test + opengl_triangle_test + opengl_quad_test + opengl_sphere_test +) + +add_custom_target(rhi_backend_tests + DEPENDS + rhi_backend_unit_tests + rhi_backend_integration_tests +) + +add_custom_target(rhi_all_tests + DEPENDS + rhi_abstraction_tests + rhi_backend_tests +) diff --git a/tests/RHI/integration/README.md b/tests/RHI/integration/README.md index 82e976a9..5635b6b4 100644 --- a/tests/RHI/integration/README.md +++ b/tests/RHI/integration/README.md @@ -1,25 +1,64 @@ # RHI Integration Tests -This folder will contain integration tests for the RHI abstraction layer. +This directory contains backend-agnostic integration tests for the RHI abstraction layer. -Integration tests verify the interaction between multiple RHI components working together. +Current goals: -## Planned Tests +- Verify that the same RHI scene code runs on `D3D12`, `OpenGL`, and `Vulkan` +- Verify real rendering output, not just object creation +- Catch abstraction regressions through golden-image comparison -- Full render pipeline test (device -> swap chain -> command list -> present) -- Multi-threaded command recording -- Resource state transitions across multiple objects -- Frame synchronization with fences +## Current scenes -## Running Tests +- `minimal`: clear, present, screenshot, GT compare +- `triangle`: minimal graphics pipeline and vertex input +- `quad`: textured quad rendering +- `sphere`: textured sphere and descriptor-set path with `firstSet != 0` +- `backpack`: real OBJ model rendering through the RHI abstraction + +## Golden image rule + +Each scene directory keeps exactly one baseline image: + +```text +GT.ppm +``` + +Runtime screenshots are backend-specific: + +- `_d3d12.ppm` +- `_opengl.ppm` +- `_vulkan.ppm` + +All backends must compare against the same `GT.ppm`. + +## Build + +Build all abstraction-layer integration tests: ```bash -# Build once, run against different backends -cmake --build build --config Debug - -# Test D3D12 backend -RHI_BACKEND=D3D12 ./build/tests/RHI/unit/rhi_unit_tests.exe - -# Test OpenGL backend -RHI_BACKEND=OpenGL ./build/tests/RHI/unit/rhi_unit_tests.exe +cmake --build build --config Debug --target rhi_abstraction_integration_tests ``` + +Build a single scene: + +```bash +cmake --build build --config Debug --target rhi_integration_backpack +``` + +## Run + +Examples: + +```bash +build\tests\RHI\integration\minimal\Debug\rhi_integration_minimal.exe --gtest_filter=Vulkan/MinimalTest.RenderClear/0 +build\tests\RHI\integration\triangle\Debug\rhi_integration_triangle.exe --gtest_filter=D3D12/TriangleTest.RenderTriangle/0 +build\tests\RHI\integration\quad\Debug\rhi_integration_quad.exe --gtest_filter=OpenGL/QuadTest.RenderQuad/0 +build\tests\RHI\integration\backpack\Debug\rhi_integration_backpack.exe --gtest_filter=Vulkan/BackpackTest.RenderBackpack/0 +``` + +## Rules + +- Integration tests in this directory may only depend on public RHI interfaces and shared fixtures. +- If a new scene exposes an abstraction problem, fix the RHI first, then extend the test. +- Do not split golden images by backend unless the abstraction contract itself changes. diff --git a/tests/TEST_SPEC.md b/tests/TEST_SPEC.md index c6ffaef9..97b614a1 100644 --- a/tests/TEST_SPEC.md +++ b/tests/TEST_SPEC.md @@ -1,21 +1,23 @@ # XCEngine 测试规范 -最后更新:2026-03-26 +最后更新:2026-03-27 ## 1. 目标 -本文件只描述当前工作区内已经存在并仍然有效的测试约定,重点覆盖: +本文档只描述当前仓库里已经存在、已经生效、并且应当长期维护的测试规范。 + +重点覆盖: - `tests/` 的整体组织方式 -- CMake / CTest 的基本用法 -- RHI 模块的测试分层 -- RHI 抽象层集成测试的当前规范 +- CMake / CTest 的推荐使用方式 +- RHI 模块测试的分层边界 +- RHI 抽象层集成测试的当前约束 -如果代码、目录结构或 target 名称发生变化,应优先更新本文件,而不是继续累积过时说明。 +如果目录结构、target 名称、后端覆盖范围或 GT 图规则发生变化,必须同步更新本文档。 ## 2. 顶层结构 -`tests/CMakeLists.txt` 当前纳入的测试子目录如下: +`tests/CMakeLists.txt` 当前纳入的主要测试模块如下: ```text tests/ @@ -27,19 +29,19 @@ tests/ ├─ debug/ ├─ components/ ├─ scene/ -├─ rhi/ +├─ RHI/ ├─ resources/ └─ input/ ``` 说明: -- 实际磁盘上的大小写有历史遗留差异;在 Windows 下通常不影响构建。 - 新增测试模块时,必须同时补充对应目录下的 `CMakeLists.txt`,并在 `tests/CMakeLists.txt` 中注册。 +- 测试目录命名、target 命名、文档命名必须和实际仓库状态一致,不保留“计划中但未落地”的旧说明。 ## 3. 基本构建方式 -推荐始终使用 CMake 驱动构建和测试,不再维护额外的手工脚本流程。 +推荐始终使用 CMake 驱动构建与测试。 ### 3.1 配置 @@ -47,19 +49,27 @@ tests/ cmake -S . -B build ``` -当以下内容发生变化时,需要重新执行配置: +以下场景需要重新配置: - 新增或删除源文件 - 修改任意 `CMakeLists.txt` - 修改 target、依赖、编译定义或测试发现方式 -### 3.2 构建 +### 3.2 增量构建 ```bash cmake --build build --config Debug ``` -开发时优先增量构建单个 target,例如: +常用 RHI 聚合 target: + +```bash +cmake --build build --config Debug --target rhi_abstraction_tests +cmake --build build --config Debug --target rhi_backend_tests +cmake --build build --config Debug --target rhi_all_tests +``` + +常用单项 target: ```bash cmake --build build --config Debug --target rhi_unit_tests @@ -67,6 +77,7 @@ cmake --build build --config Debug --target rhi_integration_minimal cmake --build build --config Debug --target rhi_integration_triangle cmake --build build --config Debug --target rhi_integration_quad cmake --build build --config Debug --target rhi_integration_sphere +cmake --build build --config Debug --target rhi_integration_backpack ``` ### 3.3 运行 @@ -83,33 +94,42 @@ ctest --test-dir build -N -C Debug ctest --test-dir build -C Debug --output-on-failure ``` -运行单个可执行测试也可以直接使用 gtest 过滤: +直接运行 gtest 可执行文件也是合法入口。例如: ```bash -build\tests\RHI\integration\triangle\Debug\rhi_integration_triangle.exe --gtest_filter=D3D12/TriangleTest.RenderTriangle/0 -build\tests\RHI\integration\triangle\Debug\rhi_integration_triangle.exe --gtest_filter=OpenGL/TriangleTest.RenderTriangle/0 +build\tests\RHI\unit\Debug\rhi_unit_tests.exe --gtest_brief=1 +build\tests\RHI\integration\triangle\Debug\rhi_integration_triangle.exe --gtest_filter=Vulkan/TriangleTest.RenderTriangle/0 +build\tests\RHI\integration\backpack\Debug\rhi_integration_backpack.exe --gtest_filter=D3D12/BackpackTest.RenderBackpack/0 ``` ## 4. RHI 测试分层 -RHI 当前分成四类测试: +RHI 当前分为四层测试: -| 层级 | 目录 | 目标 | +| 层级 | 目录 / target | 目标 | | --- | --- | --- | -| 抽象层单元测试 | `tests/RHI/unit/` | 验证公共 RHI 接口在 D3D12 / OpenGL 上的一致性 | -| 抽象层集成测试 | `tests/RHI/integration/` | 用同一套 RHI 抽象代码驱动两套后端完成真实渲染 | +| 抽象层单元测试 | `tests/RHI/unit/` / `rhi_unit_tests` | 验证公共 RHI 接口在 `D3D12 / OpenGL / Vulkan` 上的统一语义 | +| 抽象层集成测试 | `tests/RHI/integration/` / `rhi_integration_*` | 用同一套 RHI 抽象代码驱动三后端完成真实渲染并做 GT 图比对 | | D3D12 后端测试 | `tests/RHI/D3D12/` | 验证 D3D12 封装本身 | | OpenGL 后端测试 | `tests/RHI/OpenGL/` | 验证 OpenGL 封装本身 | +补充说明: + +- Vulkan 目前没有独立的 `tests/RHI/Vulkan/` 子树。 +- Vulkan 的后端专项覆盖当前由两部分承担: + - `rhi_unit_tests` 中的三后端参数化通用测试 + - `tests/RHI/unit/test_vulkan_graphics.cpp` 中的 Vulkan 专项测试 +- 如果未来出现明显只属于 Vulkan 的后端语义,应新增独立 Vulkan 测试树,而不是把通用抽象测试继续稀释成后端特判集合。 + 设计边界: - `tests/RHI/unit/` 与 `tests/RHI/integration/` 只能依赖公共 RHI 抽象接口。 -- 后端专有头文件、原生句柄、后端专用 helper,只允许出现在 `tests/RHI/D3D12/**` 与 `tests/RHI/OpenGL/**`。 +- 后端私有头文件、原生句柄、后端专用 helper,只允许出现在对应后端目录。 - 如果抽象层测试为了通过而被迫引入后端 API,优先修 RHI 本身,而不是给测试开后门。 ## 5. 当前 RHI Target -当前已经存在的主要 RHI target: +### 5.1 抽象层 | 类别 | target | | --- | --- | @@ -118,14 +138,28 @@ RHI 当前分成四类测试: | 抽象层集成测试 | `rhi_integration_triangle` | | 抽象层集成测试 | `rhi_integration_quad` | | 抽象层集成测试 | `rhi_integration_sphere` | +| 抽象层集成测试 | `rhi_integration_backpack` | + +### 5.2 后端专用 + +| 类别 | target | +| --- | --- | | D3D12 后端单元测试 | `rhi_d3d12_tests` | | OpenGL 后端单元测试 | `rhi_opengl_tests` | | D3D12 后端集成测试 | `d3d12_minimal_test` `d3d12_triangle_test` `d3d12_quad_test` `d3d12_sphere_test` | | OpenGL 后端集成测试 | `opengl_minimal_test` `opengl_triangle_test` `opengl_quad_test` `opengl_sphere_test` | -说明: +### 5.3 聚合 target -- 抽象层集成测试目前正式包含 `minimal`、`triangle`、`quad` 与 `sphere`。 +| 类别 | target | +| --- | --- | +| 抽象层单测聚合 | `rhi_abstraction_unit_tests` | +| 抽象层集成聚合 | `rhi_abstraction_integration_tests` | +| 抽象层总聚合 | `rhi_abstraction_tests` | +| 后端单测聚合 | `rhi_backend_unit_tests` | +| 后端集成聚合 | `rhi_backend_integration_tests` | +| 后端总聚合 | `rhi_backend_tests` | +| RHI 全量聚合 | `rhi_all_tests` | ## 6. RHI 抽象层集成测试规范 @@ -137,101 +171,100 @@ tests/RHI/integration/ │ ├─ RHIIntegrationFixture.h │ └─ RHIIntegrationFixture.cpp ├─ minimal/ -│ ├─ CMakeLists.txt -│ ├─ GT.ppm -│ └─ main.cpp ├─ triangle/ -│ ├─ CMakeLists.txt -│ ├─ GT.ppm -│ └─ main.cpp ├─ quad/ -│ ├─ CMakeLists.txt -│ ├─ GT.ppm -│ └─ main.cpp ├─ sphere/ -│ ├─ CMakeLists.txt -│ ├─ GT.ppm -│ └─ main.cpp +├─ backpack/ ├─ compare_ppm.py +├─ run_integration_test.py +├─ README.md └─ CMakeLists.txt ``` -### 6.2 约束 +### 6.2 当前场景 + +| 场景 | 目标 | +| --- | --- | +| `minimal` | 验证清屏、present、截图与 GT 比对链路 | +| `triangle` | 验证最小图形管线与顶点输入 | +| `quad` | 验证纹理采样与基础贴图渲染 | +| `sphere` | 验证更复杂顶点布局、纹理与 `firstSet != 0` 的描述符绑定路径 | +| `backpack` | 验证真实模型、资源导入结果与完整 draw path | + +### 6.3 统一约束 抽象层集成测试必须满足以下规则: 1. 只包含公共 RHI 头文件与共享 fixture。 -2. 同一个测试场景通过参数化方式同时跑 D3D12 和 OpenGL。 +2. 同一场景通过参数化方式同时运行 `D3D12 / OpenGL / Vulkan`。 3. 每个场景目录只维护一张基准图:`GT.ppm`。 -4. 截图输出允许按后端区分命名,例如: +4. 运行时截图允许按后端区分命名,例如: - `minimal_d3d12.ppm` - `minimal_opengl.ppm` - - `triangle_d3d12.ppm` - - `triangle_opengl.ppm` - - `quad_d3d12.ppm` - - `quad_opengl.ppm` - - `sphere_d3d12.ppm` - - `sphere_opengl.ppm` -5. 两个后端都必须与同一张 `GT.ppm` 做比对。 -6. 新测试如果暴露抽象层缺口,应先补 RHI,再补测试。 -7. 至少保留一个场景覆盖 `firstSet != 0` 的描述符绑定路径,当前由 `sphere` 负责验证。 -8. `sphere` 需要通过预留 `set0` 把实际 shader 绑定点推进到 `binding = 1`,避免出现“忽略 set 语义也能误通过”的假阳性。 + - `minimal_vulkan.ppm` +5. 所有后端都必须与同一张 `GT.ppm` 做比对。 +6. 新场景如果暴露抽象层缺口,应先补 RHI,再补测试。 +7. `sphere` 必须继续保留对 `firstSet != 0` 绑定路径的覆盖,避免“忽略 set 语义也误通过”的假阳性。 +8. `backpack` 是当前抽象层最接近真实资源渲染的场景,后续新增复杂渲染场景时不应削弱它的回归价值。 -### 6.3 命名 - -- 目录名:`tests/RHI/integration//` -- target 名:`rhi_integration_` -- 截图名:`_d3d12.ppm` / `_opengl.ppm` -- 基准图名:固定为 `GT.ppm` - -### 6.4 CMake 约定 +### 6.4 CMake 约束 每个抽象层集成测试目录都应: - 使用独立 target - 复用 `fixtures/RHIIntegrationFixture.cpp` -- 链接 `XCEngine`、`GTest::gtest` 以及当前两套后端所需系统库 +- 链接 `XCEngine`、`GTest::gtest` +- 在需要时按后端条件加入对应系统库 - 在 `POST_BUILD` 中复制: - `compare_ppm.py` - - 当前目录下的 `GT.ppm` - - 运行所需的 `renderdoc.dll` + - 当前场景的 `GT.ppm` + - 运行所需的资源文件 - 使用 `gtest_discover_tests(...)` -### 6.5 推荐验证步骤 - -以 `triangle` 为例: +### 6.5 推荐验证方式 ```bash -cmake -S . -B build -cmake --build build --config Debug --target rhi_integration_triangle +cmake --build build --config Debug --target rhi_abstraction_integration_tests + +build\tests\RHI\integration\minimal\Debug\rhi_integration_minimal.exe --gtest_filter=Vulkan/MinimalTest.RenderClear/0 build\tests\RHI\integration\triangle\Debug\rhi_integration_triangle.exe --gtest_filter=D3D12/TriangleTest.RenderTriangle/0 -build\tests\RHI\integration\triangle\Debug\rhi_integration_triangle.exe --gtest_filter=OpenGL/TriangleTest.RenderTriangle/0 +build\tests\RHI\integration\quad\Debug\rhi_integration_quad.exe --gtest_filter=OpenGL/QuadTest.RenderQuad/0 +build\tests\RHI\integration\backpack\Debug\rhi_integration_backpack.exe --gtest_filter=Vulkan/BackpackTest.RenderBackpack/0 ``` 通过标准: -- 两个后端都成功渲染 -- 两个后端截图都能通过与同一张 `GT.ppm` 的比对 +- 渲染成功 +- 截图成功 +- 与当前场景 `GT.ppm` 比对通过 -## 7. 新增一个 RHI 抽象层集成测试时 +## 7. 当前体系的完成度与后续方向 -标准流程: +当前状态可以认为是“高完成度、可作为正式基线”,但不是“完全封顶”。 -1. 在 `tests/RHI/integration//` 新建 `main.cpp`、`CMakeLists.txt`、`GT.ppm`。 -2. 在 `tests/RHI/integration/CMakeLists.txt` 中注册 `add_subdirectory()`。 -3. 先只用公共 RHI 接口完成最小可运行版本。 -4. 分别验证 D3D12 / OpenGL。 -5. 若失败源于抽象层能力不足,先修 RHI,再回到测试。 -6. 确认双后端都通过后,再提交。 +已经完成: + +- 抽象层单测正式纳入 `D3D12 / OpenGL / Vulkan` +- 抽象层集成测试已经具备 5 个真实渲染场景 +- GT 图回归链路已经稳定工作 +- D3D12 与 OpenGL 仍保留独立后端测试树 + +仍需继续完善: + +- 为 Vulkan 增加独立的后端测试树 +- 把仍然合理存在的后端专属断言与 skip 场景继续收敛 +- 补充 `resize / swapchain 重建 / 长时间 soak / 多线程录制 / validation layer 负例` 等更工程化的测试 +- 保持文档、CMake target 与实际测试状态同步 ## 8. 文档维护要求 -以下变化必须同步更新本文件: +以下变化必须同步更新本文档: - 测试目录结构变化 - 新增或删除测试 target -- RHI 抽象层集成测试场景变化 -- 基准图管理规则变化 -- 构建与运行命令变化 +- 抽象层集成测试场景变化 +- GT 图管理规则变化 +- CMake 聚合入口变化 +- 后端覆盖范围变化 -禁止继续在文档中保留“计划中但尚未落地”的内容,除非明确标注为未完成状态。 +禁止继续保留和当前仓库状态不一致的旧说明。