diff --git a/tests/RHI/D3D12/TEST_SPEC.md b/tests/RHI/D3D12/TEST_SPEC.md new file mode 100644 index 00000000..610ab5c9 --- /dev/null +++ b/tests/RHI/D3D12/TEST_SPEC.md @@ -0,0 +1,347 @@ +# D3D12 测试规范文档 + +## 1. 测试分类 + +### 1.1 测试层级 + +| 层级 | 位置 | 执行方式 | 目的 | +|------|------|----------|------| +| 单元测试 | `tests/RHI/D3D12/unit/` | CTest 自动运行 | 验证各组件 API 功能 | +| 集成测试 | `tests/RHI/D3D12/integration/` | CTest + Python wrapper | 端到端渲染验证 | + +### 1.2 单元测试规范 + +**框架**: Google Test +**运行方式**: +```bash +cd build/tests/RHI/D3D12/unit +ctest -C Debug --output-on-failure +``` + +**命名约定**: `Component_Category_SubBehavior` +- Component: 组件名 (Device, Buffer, Texture, CommandQueue, etc.) +- Category: 操作类别 (Create, Get, Set, Map, Reset, etc.) +- SubBehavior: 具体行为 (DefaultHeap, GPUAddress, etc.) + +**示例**: +``` +Device_Create_Success +Device_Get_AdapterInfo +Buffer_Create_DefaultHeap +Buffer_Map_Unmap +Texture_Create_2D +``` + +### 1.3 集成测试规范 + +**运行方式**: Python wrapper 通过 CTest 调用 +```bash +cd build/tests/RHI/D3D12/integration +ctest -C Debug --output-on-failure +``` + +**Python Wrapper 职责**: +1. 启动 D3D12 exe +2. 等待进程完成 +3. 检查输出文件 +4. 调用 compare_ppm.py 比对 Golden Image +5. 返回 0(成功)/1(失败) + +**Golden Image 规范**: +- 文件格式: PPM (P6) +- 存储位置: `tests/RHI/D3D12/integration/` +- 命名: `GT_.ppm` +- 阈值: 默认 5% + +--- + +## 2. 测试命名规则 + +### 2.1 禁止模式 + +❌ 不允许: +- `*_Placeholder` - 无意义的占位测试 +- 驼峰+下划线混用 +- 空操作测试 + +### 2.2 标准格式 + +✅ 正确格式: +``` +Component_Category_SubBehavior +``` + +### 2.3 大小写规则 + +- 全小写,单词间用下划线分隔 +- Component 名称与类名一致 (如 `CommandQueue` 不是 `Command_queue`) + +### 2.4 测试前缀对应关系 + +| 类名 | 测试前缀 | +|------|---------| +| D3D12Device | Device | +| D3D12CommandQueue | CommandQueue | +| D3D12CommandAllocator | CommandAllocator | +| D3D12CommandList | CommandList | +| D3D12Buffer | Buffer | +| D3D12Texture | Texture | +| D3D12DescriptorHeap | DescriptorHeap | +| D3D12Fence | Fence | +| D3D12PipelineState | PipelineState | +| D3D12RootSignature | RootSignature | +| D3D12Shader | Shader | +| D3D12RenderTargetView | RTV | +| D3D12DepthStencilView | DSV | + +--- + +## 3. 测试实现规范 + +### 3.1 单元测试结构 + +```cpp +TEST_F(D3D12TestFixture, Component_Category_SubBehavior) { + // Arrange: 准备测试数据 + + // Act: 执行被测操作 + + // Assert: 验证结果 + ASSERT_TRUE(condition); + EXPECT_EQ(expected, actual); +} +``` + +### 3.2 Fixture 使用 + +```cpp +class D3D12TestFixture : public ::testing::Test { +protected: + void SetUp() override; // 创建设备、命令队列等 + void TearDown() override; // 清理资源 + + ID3D12Device* GetDevice(); + ID3D12CommandQueue* GetCommandQueue(); + ID3D12CommandAllocator* GetCommandAllocator(); + ID3D12GraphicsCommandList* GetCommandList(); + + void WaitForGPU(); +}; +``` + +### 3.3 错误处理测试 + +对于负面测试: +```cpp +TEST_F(D3D12TestFixture, Component_Create_InvalidSize) { + // 测试零大小或负数大小应该失败 + ASSERT_FALSE(buffer->Initialize(device, 0)); +} +``` + +--- + +## 4. 集成测试规范 + +### 4.1 Python Wrapper 模板 + +```python +import sys +import os +import subprocess +import time + +def run_integration_test(exe_path, output_ppm, gt_ppm, threshold, timeout=120): + """ + Run a D3D12 integration test and compare output with golden template. + + Args: + exe_path: Path to the test executable + output_ppm: Filename of the output screenshot + gt_ppm: Path to the golden template PPM file + threshold: Pixel difference threshold for comparison + timeout: Maximum time to wait (seconds) + + Returns: + 0 on success, non-zero on failure + """ + # 1. 检查文件存在 + # 2. 删除旧输出 + # 3. 启动进程 + # 4. 等待完成 + # 5. 检查输出 + # 6. 比对图片 + # 7. 返回结果 +``` + +### 4.2 CTest 注册格式 + +```cmake +find_package(Python3 REQUIRED) +enable_testing() + +add_test(NAME TestName + COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/run_integration_test.py + $ + output.ppm + ${CMAKE_CURRENT_SOURCE_DIR}/GT.ppm + 5 + WORKING_DIRECTORY $ +) +``` + +### 4.3 Golden Image 生成 + +1. 在干净硬件环境运行集成测试 +2. 截图保存为 `GT_.ppm` +3. 人工验证截图正确性 +4. 提交到版本控制 + +--- + +## 5. CMakeLists.txt 规范 + +### 5.1 单元测试 CMakeLists.txt + +```cmake +cmake_minimum_required(VERSION 3.15) +get_filename_component(PROJECT_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../.. ABSOLUTE) + +find_package(GTest REQUIRED) + +set(TEST_SOURCES + fixtures/D3D12TestFixture.cpp + test_device.cpp + test_buffer.cpp + # ... 其他测试文件 +) + +add_executable(d3d12_engine_tests ${TEST_SOURCES}) + +target_link_libraries(d3d12_engine_tests PRIVATE + d3d12 + dxgi + d3dcompiler + XCEngine + GTest::gtest + GTest::gtest_main +) + +target_include_directories(d3d12_engine_tests PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/fixtures + ${PROJECT_ROOT_DIR}/engine/include + ${PROJECT_ROOT_DIR}/engine/src +) + +enable_testing() +add_test(NAME D3D12EngineTests COMMAND d3d12_engine_tests) +``` + +### 5.2 集成测试 CMakeLists.txt + +```cmake +cmake_minimum_required(VERSION 3.15) +project(D3D12_Integration) + +set(ENGINE_ROOT_DIR ${CMAKE_SOURCE_DIR}/../engine) +find_package(Python3 REQUIRED) +enable_testing() + +add_executable(D3D12_Test WIN32 main.cpp) + +target_link_libraries(D3D12_Test PRIVATE + d3d12 dxgi d3dcompiler winmm XCEngine +) + +# POST_BUILD: 复制资源文件 +add_custom_command(TARGET D3D12_Test POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory + ${CMAKE_CURRENT_SOURCE_DIR}/Res + $/Res +) + +# CTest 注册 +add_test(NAME D3D12_Test_Integration + COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/run_integration_test.py + $ + output.ppm + ${CMAKE_CURRENT_SOURCE_DIR}/GT.ppm + 5 + WORKING_DIRECTORY $ +) +``` + +--- + +## 6. 测试执行 + +### 6.1 完整测试流程 + +```bash +# 1. 构建 +cd build +cmake .. +cmake --build . --target d3d12_engine_tests D3D12_Test --config Debug + +# 2. 运行单元测试 +cd tests/RHI/D3D12/unit +ctest -C Debug --output-on-failure + +# 3. 运行集成测试 +cd tests/RHI/D3D12/integration +ctest -C Debug --output-on-failure +``` + +### 6.2 输出格式 + +成功: +``` +Test #1: D3D12_Minimal_Integration ....... Passed +``` + +失败: +``` +Test #1: D3D12_Minimal_Integration ....... Failed +[Integration Test] Different pixels: 39.94% +FAIL: Images differ! +``` + +--- + +## 7. 文件结构 + +``` +tests/RHI/D3D12/ +├── CMakeLists.txt +├── TEST_IMPROVEMENT_PLAN.md # 改进计划 +├── TEST_SPEC.md # 本规范 +├── unit/ +│ ├── CMakeLists.txt +│ ├── fixtures/ +│ │ ├── D3D12TestFixture.h +│ │ └── D3D12TestFixture.cpp +│ ├── test_device.cpp +│ ├── test_buffer.cpp +│ └── ... +└── integration/ + ├── CMakeLists.txt + ├── main_minimal.cpp + ├── main_render.cpp + ├── run_integration_test.py + ├── compare_ppm.py + ├── GT.ppm + └── GT_minimal.ppm +``` + +--- + +## 8. 规范更新记录 + +| 版本 | 日期 | 变更 | +|------|------|------| +| 1.0 | 2026-03-20 | 初始版本 | + +--- + +**规范版本**: 1.0 +**最后更新**: 2026-03-20 \ No newline at end of file