2026-03-25 12:28:33 +08:00
|
|
|
|
最最最重要的是,在重构RHI测试的过程中,如果发现了RHI模块设计上的根本问题,需要紧急向我汇报!!!!!!!!
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-03-25 01:31:09 +08:00
|
|
|
|
# RHI 模块单元测试重构计划
|
|
|
|
|
|
|
|
|
|
|
|
## 1. 项目背景
|
|
|
|
|
|
|
|
|
|
|
|
本文档分析 XCEngine RHI(渲染硬件抽象层)模块的三个单元测试层次的覆盖度和质量问题,并提出重构建议。
|
|
|
|
|
|
|
|
|
|
|
|
### 1.1 测试层次结构
|
|
|
|
|
|
|
|
|
|
|
|
| 层次 | 位置 | 测试数量 | 特点 |
|
|
|
|
|
|
|------|------|----------|------|
|
|
|
|
|
|
| **RHI 抽象层** | `tests/RHI/unit/` | 75 tests × 2 backends = 150 | 参数化测试,跨 D3D12/OpenGL |
|
|
|
|
|
|
| **D3D12 后端** | `tests/RHI/D3D12/unit/` | ~58 tests | 非参数化,直接测试 D3D12 API |
|
|
|
|
|
|
| **OpenGL 后端** | `tests/RHI/OpenGL/unit/` | ~58 tests | 非参数化,直接测试 OpenGL API |
|
|
|
|
|
|
|
|
|
|
|
|
### 1.2 当前测试文件分布
|
|
|
|
|
|
|
|
|
|
|
|
#### RHI 抽象层 (`tests/RHI/unit/`)
|
|
|
|
|
|
|
|
|
|
|
|
| 文件 | 测试数 | 测试类 |
|
|
|
|
|
|
|------|--------|--------|
|
|
|
|
|
|
| `test_device.cpp` | 8 | RHIDevice |
|
|
|
|
|
|
| `test_buffer.cpp` | 8 | RHIBuffer |
|
|
|
|
|
|
| `test_texture.cpp` | 5 | RHITexture |
|
|
|
|
|
|
| `test_swap_chain.cpp` | 4 | RHISwapChain |
|
|
|
|
|
|
| `test_command_list.cpp` | 14 | RHICommandList |
|
|
|
|
|
|
| `test_command_queue.cpp` | 6 | RHICommandQueue |
|
2026-03-25 12:28:33 +08:00
|
|
|
|
| `test_shader.cpp` | 7 | RHIShader |
|
2026-03-25 01:31:09 +08:00
|
|
|
|
| `test_fence.cpp` | 10 | RHIFence |
|
|
|
|
|
|
| `test_sampler.cpp` | 4 | RHISampler |
|
|
|
|
|
|
| `test_factory.cpp` | 5 | RHIFactory |
|
2026-03-25 13:05:01 +08:00
|
|
|
|
| `test_pipeline_state.cpp` | 10 | RHIPipelineState |
|
|
|
|
|
|
| `test_render_pass.cpp` | 10 | RHIRenderPass |
|
|
|
|
|
|
| `test_framebuffer.cpp` | 8 | RHIFramebuffer |
|
2026-03-25 15:10:10 +08:00
|
|
|
|
| `test_compute.cpp` | 8 | Compute/Dispatch |
|
2026-03-25 01:31:09 +08:00
|
|
|
|
|
|
|
|
|
|
#### D3D12 后端 (`tests/RHI/D3D12/unit/`)
|
|
|
|
|
|
|
|
|
|
|
|
| 文件 | 测试数 | 测试类/功能 |
|
|
|
|
|
|
|------|--------|-------------|
|
|
|
|
|
|
| `test_device.cpp` | 6 | D3D12Device |
|
|
|
|
|
|
| `test_fence.cpp` | 9 | D3D12Fence |
|
|
|
|
|
|
| `test_command_queue.cpp` | 2 | D3D12CommandQueue |
|
|
|
|
|
|
| `test_command_allocator.cpp` | 3 | D3D12CommandAllocator |
|
|
|
|
|
|
| `test_command_list.cpp` | 2 | D3D12CommandList |
|
|
|
|
|
|
| `test_buffer.cpp` | 6 | D3D12Buffer |
|
|
|
|
|
|
| `test_texture.cpp` | 4 | D3D12Texture |
|
|
|
|
|
|
| `test_descriptor_heap.cpp` | 9 | D3D12DescriptorHeap |
|
|
|
|
|
|
| `test_shader.cpp` | 3 | D3D12Shader (trivial) |
|
|
|
|
|
|
| `test_root_signature.cpp` | 2 | D3D12RootSignature |
|
|
|
|
|
|
| `test_pipeline_state.cpp` | 2 | D3D12 PSO (trivial) |
|
|
|
|
|
|
| `test_views.cpp` | 4 | RTV/DSV/CBV |
|
|
|
|
|
|
| `test_swap_chain.cpp` | 5 | D3D12SwapChain |
|
|
|
|
|
|
|
|
|
|
|
|
#### OpenGL 后端 (`tests/RHI/OpenGL/unit/`)
|
|
|
|
|
|
|
|
|
|
|
|
| 文件 | 测试数 | 测试类/功能 |
|
|
|
|
|
|
|------|--------|-------------|
|
|
|
|
|
|
| `test_device.cpp` | 2 | OpenGLDevice |
|
|
|
|
|
|
| `test_buffer.cpp` | 6 | OpenGLBuffer |
|
|
|
|
|
|
| `test_fence.cpp` | 8 | OpenGLFence |
|
|
|
|
|
|
| `test_texture.cpp` | 5 | OpenGLTexture |
|
|
|
|
|
|
| `test_shader.cpp` | 4 | OpenGLShader |
|
|
|
|
|
|
| `test_pipeline_state.cpp` | 3 | OpenGLPipelineState |
|
|
|
|
|
|
| `test_vertex_array.cpp` | 5 | OpenGLVertexArray |
|
|
|
|
|
|
| `test_command_list.cpp` | 9 | OpenGLCommandList |
|
|
|
|
|
|
| `test_render_target_view.cpp` | 4 | OpenGLRenderTargetView |
|
|
|
|
|
|
| `test_depth_stencil_view.cpp` | 4 | OpenGLDepthStencilView |
|
|
|
|
|
|
| `test_swap_chain.cpp` | 3 | OpenGLSwapChain |
|
|
|
|
|
|
| `test_sampler.cpp` | 4 | OpenGLSampler |
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 2. 严重问题(P0 - 必须修复)
|
|
|
|
|
|
|
2026-03-25 12:28:33 +08:00
|
|
|
|
### 2.1 `tests/RHI/unit/test_shader.cpp` - 9个测试完全相同 ✅ 已修复
|
|
|
|
|
|
|
|
|
|
|
|
**状态**: ✅ 已完成 (2026-03-25)
|
|
|
|
|
|
|
|
|
|
|
|
**修复内容**:
|
|
|
|
|
|
|
|
|
|
|
|
1. **Shader 编译抽象重构** - 扩展 `ShaderCompileDesc` 支持内嵌源码:
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
struct ShaderCompileDesc {
|
|
|
|
|
|
std::wstring fileName; // 文件路径(可选)
|
|
|
|
|
|
std::vector<uint8_t> source; // 内嵌源码(可选)
|
|
|
|
|
|
ShaderLanguage sourceLanguage; // 源码语言:HLSL/GLSL/SPIRV
|
|
|
|
|
|
std::wstring entryPoint; // Entry point 名称
|
|
|
|
|
|
std::wstring profile; // Profile
|
|
|
|
|
|
std::vector<ShaderCompileMacro> macros;
|
|
|
|
|
|
};
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
2. **新增 `ShaderLanguage` 枚举**:
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
enum class ShaderLanguage : uint8_t {
|
|
|
|
|
|
Unknown,
|
|
|
|
|
|
HLSL, // D3D11/D3D12
|
|
|
|
|
|
GLSL, // OpenGL/Vulkan
|
|
|
|
|
|
SPIRV // Vulkan (pre-compiled)
|
|
|
|
|
|
};
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
3. **测试重构** - 9个相同测试 → 7个有效测试:
|
|
|
|
|
|
- `Shader_Compile_EmptyDesc_ReturnsNullptr` - 空描述符测试
|
|
|
|
|
|
- `Shader_Compile_ValidVertexShader` - 顶点着色器编译测试
|
|
|
|
|
|
- `Shader_Compile_ValidFragmentShader` - 片段着色器编译测试
|
|
|
|
|
|
- `Shader_GetType_VertexShader` - 获取顶点着色器类型
|
|
|
|
|
|
- `Shader_GetType_FragmentShader` - 获取片段着色器类型
|
|
|
|
|
|
- `Shader_GetNativeHandle_ValidShader` - 获取原生句柄
|
|
|
|
|
|
- `Shader_Shutdown_Invalidates` - 关闭后验证失效
|
|
|
|
|
|
|
|
|
|
|
|
**测试结果**: 14/14 通过 (D3D12: 7, OpenGL: 7)
|
2026-03-25 01:31:09 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### 2.2 关键 RHI 抽象类完全没有测试
|
|
|
|
|
|
|
|
|
|
|
|
**严重程度**: 🔴 致命
|
|
|
|
|
|
|
|
|
|
|
|
**问题描述**:
|
|
|
|
|
|
|
|
|
|
|
|
以下 RHI 抽象类在 `tests/RHI/unit/` 中完全没有测试:
|
|
|
|
|
|
|
|
|
|
|
|
| 类 | 说明 | 影响 |
|
|
|
|
|
|
|----|------|------|
|
|
|
|
|
|
| `RHIPipelineState` | 管线状态对象 | 无法验证 PSO 创建、配置、绑定 |
|
|
|
|
|
|
| `RHIPipelineLayout` | 管线布局 | 无法验证 descriptor layout |
|
|
|
|
|
|
| `RHIDescriptorPool` | 描述符池 | Descriptor 管理完全未覆盖 |
|
|
|
|
|
|
| `RHIDescriptorSet` | 描述符集 | 无法验证 descriptor 更新 |
|
|
|
|
|
|
| `RHIRenderPass` | 渲染通道 | RenderPass API 完全未覆盖 |
|
|
|
|
|
|
| `RHIFramebuffer` | 帧缓冲 | Framebuffer API 完全未覆盖 |
|
|
|
|
|
|
|
|
|
|
|
|
**修复建议 - 新增 `test_pipeline_state.cpp`**:
|
|
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
// 文件: tests/RHI/unit/test_pipeline_state.cpp
|
|
|
|
|
|
#include "fixtures/RHITestFixture.h"
|
|
|
|
|
|
#include "XCEngine/RHI/RHIPipelineState.h"
|
|
|
|
|
|
#include "XCEngine/RHI/RHIDevice.h"
|
|
|
|
|
|
|
|
|
|
|
|
using namespace XCEngine::RHI;
|
|
|
|
|
|
|
|
|
|
|
|
TEST_P(RHITestFixture, PipelineState_Create) {
|
|
|
|
|
|
GraphicsPipelineDesc desc = {};
|
|
|
|
|
|
// 配置基本描述符
|
|
|
|
|
|
RHIPipelineState* pso = GetDevice()->CreatePipelineState(desc);
|
|
|
|
|
|
ASSERT_NE(pso, nullptr);
|
|
|
|
|
|
pso->Shutdown();
|
|
|
|
|
|
delete pso;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST_P(RHITestFixture, PipelineState_SetGet_RasterizerState) {
|
|
|
|
|
|
GraphicsPipelineDesc desc = {};
|
|
|
|
|
|
RHIPipelineState* pso = GetDevice()->CreatePipelineState(desc);
|
|
|
|
|
|
ASSERT_NE(pso, nullptr);
|
|
|
|
|
|
|
|
|
|
|
|
RasterizerDesc rasterizer = {};
|
|
|
|
|
|
rasterizer.cullMode = CullMode::Back;
|
|
|
|
|
|
pso->SetRasterizerState(rasterizer);
|
|
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(pso->GetRasterizerState().cullMode, CullMode::Back);
|
|
|
|
|
|
pso->Shutdown();
|
|
|
|
|
|
delete pso;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST_P(RHITestFixture, PipelineState_SetGet_BlendState) {
|
|
|
|
|
|
// ...
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST_P(RHITestFixture, PipelineState_SetGet_DepthStencilState) {
|
|
|
|
|
|
// ...
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST_P(RHITestFixture, PipelineState_Finalize) {
|
|
|
|
|
|
GraphicsPipelineDesc desc = {};
|
|
|
|
|
|
RHIPipelineState* pso = GetDevice()->CreatePipelineState(desc);
|
|
|
|
|
|
ASSERT_NE(pso, nullptr);
|
|
|
|
|
|
|
|
|
|
|
|
bool finalized = pso->Finalize();
|
|
|
|
|
|
EXPECT_TRUE(finalized);
|
|
|
|
|
|
EXPECT_TRUE(pso->IsFinalized());
|
|
|
|
|
|
|
|
|
|
|
|
pso->Shutdown();
|
|
|
|
|
|
delete pso;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST_P(RHITestFixture, PipelineState_Bind_Unbind) {
|
|
|
|
|
|
// ...
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**修复建议 - 新增 `test_render_pass.cpp`**:
|
|
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
// 文件: tests/RHI/unit/test_render_pass.cpp
|
|
|
|
|
|
#include "fixtures/RHITestFixture.h"
|
|
|
|
|
|
#include "XCEngine/RHI/RHIRenderPass.h"
|
|
|
|
|
|
|
|
|
|
|
|
using namespace XCEngine::RHI;
|
|
|
|
|
|
|
|
|
|
|
|
TEST_P(RHITestFixture, RenderPass_Create) {
|
|
|
|
|
|
AttachmentDesc colorAttachment = {};
|
|
|
|
|
|
colorAttachment.format = Format::R8G8B8A8_UNorm;
|
|
|
|
|
|
colorAttachment.loadOp = LoadAction::Clear;
|
|
|
|
|
|
colorAttachment.storeOp = StoreAction::Store;
|
|
|
|
|
|
|
|
|
|
|
|
RHIRenderPass* renderPass = GetDevice()->CreateRenderPass(1, &colorAttachment, nullptr);
|
|
|
|
|
|
ASSERT_NE(renderPass, nullptr);
|
|
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(renderPass->GetColorAttachmentCount(), 1);
|
|
|
|
|
|
renderPass->Shutdown();
|
|
|
|
|
|
delete renderPass;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST_P(RHITestFixture, RenderPass_BeginEnd) {
|
|
|
|
|
|
// 需要先创建 framebuffer
|
|
|
|
|
|
// cmdList->BeginRenderPass(renderPass, framebuffer, ...);
|
|
|
|
|
|
// cmdList->EndRenderPass();
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**修复建议 - 新增 `test_framebuffer.cpp`**:
|
|
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
// 文件: tests/RHI/unit/test_framebuffer.cpp
|
|
|
|
|
|
#include "fixtures/RHITestFixture.h"
|
|
|
|
|
|
#include "XCEngine/RHI/RHIFramebuffer.h"
|
|
|
|
|
|
|
|
|
|
|
|
using namespace XCEngine::RHI;
|
|
|
|
|
|
|
|
|
|
|
|
TEST_P(RHITestFixture, Framebuffer_Create) {
|
|
|
|
|
|
// 先创建 renderPass 和 texture
|
|
|
|
|
|
RHIRenderPass* renderPass = ...;
|
|
|
|
|
|
RHITexture* texture = ...;
|
|
|
|
|
|
RHIResourceView* rtv = GetDevice()->CreateRenderTargetView(texture, {});
|
|
|
|
|
|
|
|
|
|
|
|
RHIFramebuffer* fb = GetDevice()->CreateFramebuffer(renderPass, 1, &rtv, nullptr, 256, 256);
|
|
|
|
|
|
ASSERT_NE(fb, nullptr);
|
|
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(fb->GetWidth(), 256);
|
|
|
|
|
|
EXPECT_EQ(fb->GetHeight(), 256);
|
|
|
|
|
|
EXPECT_TRUE(fb->IsValid());
|
|
|
|
|
|
|
|
|
|
|
|
fb->Shutdown();
|
|
|
|
|
|
delete fb;
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**修复建议 - 新增 `test_descriptor.cpp`**:
|
|
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
// 文件: tests/RHI/unit/test_descriptor.cpp
|
|
|
|
|
|
#include "fixtures/RHITestFixture.h"
|
|
|
|
|
|
#include "XCEngine/RHI/RHIDescriptorPool.h"
|
|
|
|
|
|
#include "XCEngine/RHI/RHIDescriptorSet.h"
|
|
|
|
|
|
|
|
|
|
|
|
using namespace XCEngine::RHI;
|
|
|
|
|
|
|
|
|
|
|
|
TEST_P(RHITestFixture, DescriptorPool_Create) {
|
|
|
|
|
|
DescriptorPoolDesc desc = {};
|
|
|
|
|
|
desc.maxSets = 10;
|
|
|
|
|
|
desc.poolSize = 100;
|
|
|
|
|
|
|
|
|
|
|
|
RHIDescriptorPool* pool = GetDevice()->CreateDescriptorPool(desc);
|
|
|
|
|
|
ASSERT_NE(pool, nullptr);
|
|
|
|
|
|
pool->Shutdown();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST_P(RHITestFixture, DescriptorSet_Allocate_Update) {
|
|
|
|
|
|
// 创建 pool
|
|
|
|
|
|
RHIDescriptorPool* pool = GetDevice()->CreateDescriptorPool(desc);
|
|
|
|
|
|
|
|
|
|
|
|
// 创建 layout
|
|
|
|
|
|
DescriptorSetLayoutDesc layoutDesc = {};
|
|
|
|
|
|
DescriptorSetLayoutBinding binding = {};
|
|
|
|
|
|
binding.binding = 0;
|
|
|
|
|
|
binding.type = DescriptorType::CBV;
|
|
|
|
|
|
binding.count = 1;
|
|
|
|
|
|
layoutDesc.bindings = &binding;
|
|
|
|
|
|
layoutDesc.bindingCount = 1;
|
|
|
|
|
|
|
|
|
|
|
|
RHIDescriptorSet* set = GetDevice()->CreateDescriptorSet(pool, layoutDesc);
|
|
|
|
|
|
ASSERT_NE(set, nullptr);
|
|
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(set->GetBindingCount(), 1);
|
|
|
|
|
|
|
|
|
|
|
|
set->Shutdown();
|
|
|
|
|
|
pool->Shutdown();
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 3. 中等问题(P1 - 应该修复)
|
|
|
|
|
|
|
|
|
|
|
|
### 3.1 `tests/RHI/unit/test_command_list.cpp` - 大量测试传递 nullptr
|
|
|
|
|
|
|
|
|
|
|
|
**问题描述**:
|
|
|
|
|
|
|
|
|
|
|
|
很多 CommandList 测试只验证调用不崩溃,不验证实际功能:
|
|
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
// 这些测试传递 nullptr,无法验证真实功能
|
|
|
|
|
|
TEST_P(RHITestFixture, CommandList_ClearRenderTarget) {
|
|
|
|
|
|
// ... 创建了 texture 但实际传递 nullptr
|
|
|
|
|
|
cmdList->ClearRenderTarget(static_cast<RHIResourceView*>(nullptr), color);
|
|
|
|
|
|
// 没有验证任何实际行为
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST_P(RHITestFixture, CommandList_TransitionBarrier) {
|
|
|
|
|
|
// 创建了 texture 但传递 nullptr
|
|
|
|
|
|
cmdList->TransitionBarrier(static_cast<RHIResourceView*>(nullptr), ...);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST_P(RHITestFixture, CommandList_SetVertexBuffer_WithResourceView) {
|
|
|
|
|
|
// 直接传递 nullptr
|
|
|
|
|
|
RHIResourceView* buffer = nullptr;
|
|
|
|
|
|
cmdList->SetVertexBuffers(0, 1, &buffer, nullptr, nullptr);
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**缺少的真实测试**:
|
|
|
|
|
|
|
|
|
|
|
|
| 测试内容 | 状态 | 建议 |
|
|
|
|
|
|
|----------|------|------|
|
|
|
|
|
|
| 有资源的 SetVertexBuffer | ❌ | 添加 |
|
|
|
|
|
|
| 有资源的 SetIndexBuffer | ❌ | 添加 |
|
|
|
|
|
|
| 有资源的 ClearRenderTarget | ❌ | 添加 |
|
|
|
|
|
|
| BeginRenderPass/EndRenderPass | ❌ | 添加 |
|
|
|
|
|
|
| Dispatch (计算着色器) | ❌ | 添加 |
|
|
|
|
|
|
| SetGraphicsDescriptorSets | ❌ | 添加 |
|
|
|
|
|
|
| SetComputeDescriptorSets | ❌ | 添加 |
|
|
|
|
|
|
|
|
|
|
|
|
**修复建议**:
|
|
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
// 新增真实资源测试
|
|
|
|
|
|
TEST_P(RHITestFixture, CommandList_SetVertexBuffer_WithRealBuffer) {
|
|
|
|
|
|
// 1. 创建 buffer
|
|
|
|
|
|
BufferDesc bufDesc = {};
|
|
|
|
|
|
bufDesc.size = 1024;
|
|
|
|
|
|
RHIBuffer* buffer = GetDevice()->CreateBuffer(bufDesc);
|
|
|
|
|
|
ASSERT_NE(buffer, nullptr);
|
|
|
|
|
|
|
|
|
|
|
|
// 2. 创建 cmdList 并设置
|
|
|
|
|
|
RHICommandList* cmdList = GetDevice()->CreateCommandList({});
|
|
|
|
|
|
cmdList->Reset();
|
|
|
|
|
|
|
|
|
|
|
|
RHIResourceView* bufferView = buffer->GetView();
|
|
|
|
|
|
cmdList->SetVertexBuffers(0, 1, &bufferView, nullptr, nullptr);
|
|
|
|
|
|
|
|
|
|
|
|
cmdList->Close();
|
|
|
|
|
|
|
|
|
|
|
|
// 3. 清理
|
|
|
|
|
|
cmdList->Shutdown();
|
|
|
|
|
|
buffer->Shutdown();
|
|
|
|
|
|
delete buffer;
|
|
|
|
|
|
delete cmdList;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST_P(RHITestFixture, CommandList_BeginEndRenderPass) {
|
|
|
|
|
|
// 1. 创建 renderPass
|
|
|
|
|
|
AttachmentDesc colorDesc = {};
|
|
|
|
|
|
colorDesc.format = Format::R8G8B8A8_UNorm;
|
|
|
|
|
|
RHIRenderPass* renderPass = GetDevice()->CreateRenderPass(1, &colorDesc, nullptr);
|
|
|
|
|
|
ASSERT_NE(renderPass, nullptr);
|
|
|
|
|
|
|
|
|
|
|
|
// 2. 创建 framebuffer
|
|
|
|
|
|
TextureDesc texDesc = {};
|
|
|
|
|
|
texDesc.width = 256;
|
|
|
|
|
|
texDesc.height = 256;
|
|
|
|
|
|
RHITexture* texture = GetDevice()->CreateTexture(texDesc);
|
|
|
|
|
|
RHIResourceView* rtv = GetDevice()->CreateRenderTargetView(texture, {});
|
|
|
|
|
|
|
|
|
|
|
|
RHIFramebuffer* fb = GetDevice()->CreateFramebuffer(renderPass, 1, &rtv, nullptr, 256, 256);
|
|
|
|
|
|
|
|
|
|
|
|
// 3. 测试 Begin/End
|
|
|
|
|
|
RHICommandList* cmdList = GetDevice()->CreateCommandList({});
|
|
|
|
|
|
cmdList->Reset();
|
|
|
|
|
|
|
|
|
|
|
|
Rect renderArea = {0, 0, 256, 256};
|
|
|
|
|
|
ClearValue clearValue = {};
|
|
|
|
|
|
cmdList->BeginRenderPass(renderPass, fb, renderArea, 1, &clearValue);
|
|
|
|
|
|
cmdList->EndRenderPass();
|
|
|
|
|
|
|
|
|
|
|
|
cmdList->Close();
|
|
|
|
|
|
|
|
|
|
|
|
// 清理
|
|
|
|
|
|
cmdList->Shutdown();
|
|
|
|
|
|
fb->Shutdown();
|
|
|
|
|
|
delete fb;
|
|
|
|
|
|
delete rtv;
|
|
|
|
|
|
texture->Shutdown();
|
|
|
|
|
|
delete texture;
|
|
|
|
|
|
renderPass->Shutdown();
|
|
|
|
|
|
delete renderPass;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST_P(RHITestFixture, CommandList_Dispatch) {
|
|
|
|
|
|
// 1. 创建 compute shader
|
|
|
|
|
|
ShaderCompileDesc csDesc = {};
|
|
|
|
|
|
RHIShader* computeShader = GetDevice()->CompileShader(csDesc);
|
|
|
|
|
|
// ...
|
|
|
|
|
|
|
|
|
|
|
|
// 2. 创建并设置 compute pipeline
|
|
|
|
|
|
RHIPipelineState* computePSO = GetDevice()->CreatePipelineState(computeDesc);
|
|
|
|
|
|
computePSO->SetComputeShader(computeShader);
|
|
|
|
|
|
computePSO->Finalize();
|
|
|
|
|
|
|
|
|
|
|
|
// 3. 测试 Dispatch
|
|
|
|
|
|
RHICommandList* cmdList = GetDevice()->CreateCommandList({});
|
|
|
|
|
|
cmdList->Reset();
|
|
|
|
|
|
cmdList->SetPipelineState(computePSO);
|
|
|
|
|
|
cmdList->Dispatch(8, 8, 1);
|
|
|
|
|
|
cmdList->Close();
|
|
|
|
|
|
|
|
|
|
|
|
// 清理
|
|
|
|
|
|
cmdList->Shutdown();
|
|
|
|
|
|
computePSO->Shutdown();
|
|
|
|
|
|
delete computePSO;
|
|
|
|
|
|
computeShader->Shutdown();
|
|
|
|
|
|
delete computeShader;
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### 3.2 D3D12 后端测试问题
|
|
|
|
|
|
|
|
|
|
|
|
| 文件 | 问题 | 建议 |
|
|
|
|
|
|
|------|------|------|
|
|
|
|
|
|
| `test_pipeline_state.cpp` | 只测试 struct 默认值 | 添加真实 PSO 创建测试 |
|
|
|
|
|
|
| `test_shader.cpp` | 只做字符串比较 | 添加 shader 编译测试 |
|
|
|
|
|
|
| `test_root_signature.cpp` | 只测试空签名和 CBV | 添加复杂参数测试 |
|
|
|
|
|
|
| `test_command_list.cpp` | 只有 2 个测试 | 补充 Reset/ClearRenderTargetView 等 |
|
|
|
|
|
|
|
|
|
|
|
|
**修复建议 - `test_pipeline_state.cpp`**:
|
|
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
// 当前只有 trivial 测试
|
|
|
|
|
|
TEST_F(D3D12TestFixture, PipelineState_Get_GraphicsPipelineDescDefaults) {
|
|
|
|
|
|
D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
|
|
|
|
|
|
// 只验证 struct 默认值
|
|
|
|
|
|
EXPECT_EQ(psoDesc.PrimitiveTopologyType, ...);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 应该添加
|
|
|
|
|
|
TEST_F(D3D12TestFixture, PipelineState_Create_GraphicsPipeline) {
|
|
|
|
|
|
// 1. 创建 root signature
|
|
|
|
|
|
D3D12_ROOT_SIGNATURE_DESC rootSigDesc = {};
|
|
|
|
|
|
D3D12RootSignature rootSig;
|
|
|
|
|
|
rootSig.Initialize(GetDevice()->GetDevice(), rootSigDesc);
|
|
|
|
|
|
|
|
|
|
|
|
// 2. 创建 shader (需要 HLSL 源码或编译好的 bytecode)
|
|
|
|
|
|
D3D12Shader* vs = new D3D12Shader();
|
|
|
|
|
|
vs->CompileFromFile(L"shaders/vertex.cso");
|
|
|
|
|
|
|
|
|
|
|
|
// 3. 创建 PSO
|
|
|
|
|
|
D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
|
|
|
|
|
|
psoDesc.pRootSignature = rootSig.GetRootSignature();
|
|
|
|
|
|
psoDesc.VS = vs->GetBytecode();
|
|
|
|
|
|
// ... 设置其他字段
|
|
|
|
|
|
|
|
|
|
|
|
ID3D12PipelineState* d3d12PSO = nullptr;
|
|
|
|
|
|
HRESULT hr = GetDevice()->GetDevice()->CreateGraphicsPipelineState(
|
|
|
|
|
|
&psoDesc, IID_PPV_ARGS(&d3d12PSO));
|
|
|
|
|
|
ASSERT_EQ(hr, S_OK);
|
|
|
|
|
|
|
|
|
|
|
|
d3d12PSO->Release();
|
|
|
|
|
|
rootSig.Shutdown();
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### 3.3 OpenGL 后端测试问题
|
|
|
|
|
|
|
|
|
|
|
|
| 文件 | 问题 | 建议 |
|
|
|
|
|
|
|------|------|------|
|
|
|
|
|
|
| `test_command_list.cpp` | 缺少 SetShader/SetUniform 测试 | 添加 |
|
|
|
|
|
|
| `test_shader.cpp` | 无 compute shader 测试 | 添加 GL_COMPUTE_SHADER |
|
|
|
|
|
|
| 无 compute 相关测试 | 缺少 Dispatch 测试 | 添加 |
|
|
|
|
|
|
|
|
|
|
|
|
**修复建议**:
|
|
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
// 新增 test_compute.cpp
|
|
|
|
|
|
TEST_F(OpenGLTestFixture, ComputeShader_Compile) {
|
|
|
|
|
|
const char* computeSrc = R"(
|
|
|
|
|
|
#version 460
|
|
|
|
|
|
layout(local_size_x = 1, local_size_y = 1) in;
|
|
|
|
|
|
void main() {
|
|
|
|
|
|
// compute shader
|
|
|
|
|
|
}
|
|
|
|
|
|
)";
|
|
|
|
|
|
|
|
|
|
|
|
OpenGLShader computeShader;
|
|
|
|
|
|
bool compiled = computeShader.CompileCompute(computeSrc);
|
|
|
|
|
|
EXPECT_TRUE(compiled);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST_F(OpenGLTestFixture, CommandList_Dispatch) {
|
|
|
|
|
|
// 编译 compute shader
|
|
|
|
|
|
OpenGLShader computeShader;
|
|
|
|
|
|
computeShader.CompileCompute(computeSrc);
|
|
|
|
|
|
|
|
|
|
|
|
// 创建 pipeline state
|
|
|
|
|
|
OpenGLPipelineState pipeline;
|
|
|
|
|
|
pipeline.SetComputeShader(&computeShader);
|
|
|
|
|
|
pipeline.Apply();
|
|
|
|
|
|
|
|
|
|
|
|
// 测试 Dispatch
|
|
|
|
|
|
OpenGLCommandList cmdList;
|
|
|
|
|
|
cmdList.Reset();
|
|
|
|
|
|
cmdList.SetPipelineState(&pipeline);
|
|
|
|
|
|
cmdList.Dispatch(8, 8, 1);
|
|
|
|
|
|
cmdList.Close();
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 4. 测试覆盖度矩阵
|
|
|
|
|
|
|
|
|
|
|
|
### 4.1 RHI 抽象层覆盖度
|
|
|
|
|
|
|
|
|
|
|
|
| RHI 抽象接口 | 覆盖状态 | 备注 |
|
|
|
|
|
|
|--------------|----------|------|
|
|
|
|
|
|
| Device 创建/初始化 | ✅ 已覆盖 | |
|
|
|
|
|
|
| Buffer 创建/映射 | ✅ 已覆盖 | |
|
|
|
|
|
|
| Texture 创建 | ✅ 已覆盖 | |
|
|
|
|
|
|
| SwapChain | ✅ 已覆盖 | |
|
|
|
|
|
|
| CommandList 基础 | ⚠️ 太弱 | 大部分传递 nullptr |
|
|
|
|
|
|
| CommandQueue | ✅ 已覆盖 | |
|
|
|
|
|
|
| Fence | ✅ 已覆盖 | |
|
|
|
|
|
|
| Sampler | ✅ 已覆盖 | |
|
2026-03-25 12:30:05 +08:00
|
|
|
|
| Shader 编译 | ✅ 已覆盖 | 7个有效测试,使用内嵌源码 |
|
|
|
|
|
|
| **PipelineState** | ✅ 已覆盖 | 10个测试,已完成 |
|
2026-03-25 01:31:09 +08:00
|
|
|
|
| **PipelineLayout** | ❌ 无测试 | **必须添加** |
|
2026-03-25 13:33:49 +08:00
|
|
|
|
| **DescriptorPool** | ✅ 已覆盖 | 8个测试,已完成 |
|
|
|
|
|
|
| **DescriptorSet** | ⚠️ 部分覆盖 | OpenGL 需要 GL context |
|
2026-03-25 13:05:01 +08:00
|
|
|
|
| **RenderPass** | ✅ 已覆盖 | 10个测试,已完成 |
|
|
|
|
|
|
| **Framebuffer** | ✅ 已覆盖 | 8个测试,已完成 |
|
2026-03-25 15:10:10 +08:00
|
|
|
|
| **Compute/Dispatch** | ✅ 已覆盖 | 8个测试,已完成 |
|
2026-03-25 01:31:09 +08:00
|
|
|
|
|
|
|
|
|
|
### 4.2 D3D12 后端覆盖度
|
|
|
|
|
|
|
|
|
|
|
|
| D3D12 特定功能 | 覆盖状态 | 备注 |
|
|
|
|
|
|
|----------------|----------|------|
|
|
|
|
|
|
| 设备特性检测 | ✅ 已覆盖 | |
|
|
|
|
|
|
| Descriptor Heap | ✅ 已覆盖 | |
|
|
|
|
|
|
| Command Allocator | ✅ 已覆盖 | |
|
|
|
|
|
|
| Fence Timeline | ✅ 已覆盖 | |
|
|
|
|
|
|
| RootSignature | ⚠️ 弱 | 只测试空签名和 CBV |
|
|
|
|
|
|
| PipelineState | ⚠️ 弱 | 只测试 struct 默认值 |
|
|
|
|
|
|
| Shader | ⚠️ 弱 | 只做字符串比较 |
|
|
|
|
|
|
| SwapChain | ✅ 已覆盖 | |
|
|
|
|
|
|
| Views (RTV/DSV) | ✅ 已覆盖 | |
|
|
|
|
|
|
|
|
|
|
|
|
### 4.3 OpenGL 后端覆盖度
|
|
|
|
|
|
|
|
|
|
|
|
| OpenGL 特定功能 | 覆盖状态 | 备注 |
|
|
|
|
|
|
|----------------|----------|------|
|
|
|
|
|
|
| Buffer (VBO/IBO/UBO) | ✅ 已覆盖 | |
|
|
|
|
|
|
| Texture (2D/Cube) | ✅ 已覆盖 | |
|
|
|
|
|
|
| VertexArray | ✅ 已覆盖 | |
|
|
|
|
|
|
| Shader 编译 | ✅ 已覆盖 | |
|
|
|
|
|
|
| PipelineState | ✅ 已覆盖 | |
|
|
|
|
|
|
| Sampler | ✅ 已覆盖 | |
|
|
|
|
|
|
| Fence | ✅ 已覆盖 | |
|
|
|
|
|
|
| SwapChain | ✅ 已覆盖 | |
|
|
|
|
|
|
| **Compute Shader** | ❌ 无测试 | **必须添加** |
|
|
|
|
|
|
| **Dispatch** | ❌ 无测试 | **必须添加** |
|
|
|
|
|
|
| Memory Barrier | ❌ 无测试 | 可选 |
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 5. 重构优先级总结
|
|
|
|
|
|
|
|
|
|
|
|
### P0 - 必须修复(影响功能验证)
|
|
|
|
|
|
|
2026-03-25 12:30:05 +08:00
|
|
|
|
| 优先级 | 问题 | 工作量 | 影响 | 状态 |
|
|
|
|
|
|
|--------|------|--------|------|------|
|
|
|
|
|
|
| 1 | Shader 测试重构 | 中 | 9个测试无效 | ✅ 已完成 |
|
|
|
|
|
|
| 2 | 添加 PipelineState 测试 | 大 | RHI 核心组件无测试 | ✅ 已完成 |
|
2026-03-25 13:05:01 +08:00
|
|
|
|
| 3 | 添加 RenderPass 测试 | 中 | 重要 API 未覆盖 | ✅ 已完成 |
|
|
|
|
|
|
| 4 | 添加 Framebuffer 测试 | 中 | 重要 API 未覆盖 | ✅ 已完成 |
|
2026-03-25 01:31:09 +08:00
|
|
|
|
|
|
|
|
|
|
### P1 - 应该修复(提高覆盖率)
|
|
|
|
|
|
|
2026-03-25 12:30:05 +08:00
|
|
|
|
| 优先级 | 问题 | 工作量 | 影响 | 状态 |
|
|
|
|
|
|
|--------|------|--------|------|------|
|
2026-03-25 13:21:13 +08:00
|
|
|
|
| 5 | 添加 DescriptorPool 测试 | 中 | 已实现未测试 | ✅ 已完成 (DescriptorPool) |
|
|
|
|
|
|
| 5b | DescriptorSet 测试 | 中 | OpenGL 需要 GL context,暂跳过 | ⚠️ 待完成 |
|
2026-03-25 12:30:05 +08:00
|
|
|
|
| 6 | CommandList 测试增强 | 大 | 大部分传递 nullptr | ⏳ 待完成 |
|
2026-03-25 15:10:10 +08:00
|
|
|
|
| 7 | 添加 Compute/Dispatch 测试 | 中 | 重要功能缺失 | ✅ 已完成 |
|
2026-03-25 12:30:05 +08:00
|
|
|
|
| 8 | D3D12 PSO/shader 测试增强 | 小 | 当前测试 trivial | ⏳ 待完成 |
|
2026-03-25 01:31:09 +08:00
|
|
|
|
|
|
|
|
|
|
### P2 - 可以修复(完善细节)
|
|
|
|
|
|
|
|
|
|
|
|
| 优先级 | 问题 | 工作量 | 影响 |
|
|
|
|
|
|
|--------|------|--------|------|
|
|
|
|
|
|
| 9 | OpenGL CommandList SetShader 测试 | 小 | 缺失测试 |
|
|
|
|
|
|
| 10 | 复杂 RootSignature 参数测试 | 小 | 当前只测试 CBV |
|
|
|
|
|
|
| 11 | OpenGL Compute Shader 测试 | 小 | 缺失测试 |
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 6. 新增测试文件清单
|
|
|
|
|
|
|
2026-03-25 13:05:01 +08:00
|
|
|
|
| 文件路径 | 测试内容 | 优先级 | 状态 |
|
|
|
|
|
|
|----------|----------|--------|------|
|
|
|
|
|
|
| `tests/RHI/unit/test_pipeline_state.cpp` | PipelineState 创建/配置/绑定 | P0 | ✅ 已完成 |
|
|
|
|
|
|
| `tests/RHI/unit/test_render_pass.cpp` | RenderPass 创建/Begin/End | P0 | ✅ 已完成 |
|
|
|
|
|
|
| `tests/RHI/unit/test_framebuffer.cpp` | Framebuffer 创建/绑定 | P0 | ✅ 已完成 |
|
2026-03-25 13:33:49 +08:00
|
|
|
|
| `tests/RHI/unit/test_descriptor.cpp` | DescriptorPool 创建/更新 | P1 | ✅ DescriptorPool完成, Set待完成 |
|
2026-03-25 15:10:10 +08:00
|
|
|
|
| `tests/RHI/unit/test_compute.cpp` | Compute shader/Dispatch | P1 | ✅ 已完成 |
|
2026-03-25 13:05:01 +08:00
|
|
|
|
| `tests/RHI/unit/test_pipeline_layout.cpp` | PipelineLayout 创建 | P2 | ⏳ 待完成 |
|
2026-03-25 01:31:09 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 7. 测试质量改进建议
|
|
|
|
|
|
|
|
|
|
|
|
### 7.1 测试命名规范
|
|
|
|
|
|
|
|
|
|
|
|
遵循 `Component_Category_SubBehavior` 格式:
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
Good:
|
|
|
|
|
|
- Buffer_Create_DefaultHeap
|
|
|
|
|
|
- CommandList_SetViewport_ValidRect
|
|
|
|
|
|
- Shader_Compile_ValidSource
|
|
|
|
|
|
|
|
|
|
|
|
Bad:
|
|
|
|
|
|
- Test1
|
|
|
|
|
|
- BufferTest
|
|
|
|
|
|
- test_buffer
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 7.2 测试结构规范
|
|
|
|
|
|
|
|
|
|
|
|
每个测试应包含:
|
|
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
TEST_P(RHITestFixture, CommandList_SetVertexBuffer_WithRealBuffer) {
|
|
|
|
|
|
// 1. Arrange - 准备测试数据
|
|
|
|
|
|
BufferDesc bufDesc = {};
|
|
|
|
|
|
bufDesc.size = 1024;
|
|
|
|
|
|
RHIBuffer* buffer = GetDevice()->CreateBuffer(bufDesc);
|
|
|
|
|
|
ASSERT_NE(buffer, nullptr); // 使用 ASSERT 防止空指针解引用
|
|
|
|
|
|
|
|
|
|
|
|
// 2. Act - 执行被测操作
|
|
|
|
|
|
RHICommandList* cmdList = GetDevice()->CreateCommandList({});
|
|
|
|
|
|
cmdList->Reset();
|
|
|
|
|
|
RHIResourceView* view = buffer->GetView();
|
|
|
|
|
|
cmdList->SetVertexBuffers(0, 1, &view, nullptr, nullptr);
|
|
|
|
|
|
cmdList->Close();
|
|
|
|
|
|
|
|
|
|
|
|
// 3. Assert - 验证结果
|
|
|
|
|
|
// 注意:有些测试难以直接验证结果,可以通过不崩溃来间接验证
|
|
|
|
|
|
|
|
|
|
|
|
// 4. Cleanup - 清理资源
|
|
|
|
|
|
cmdList->Shutdown();
|
|
|
|
|
|
delete cmdList;
|
|
|
|
|
|
buffer->Shutdown();
|
|
|
|
|
|
delete buffer;
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 7.3 避免的问题
|
|
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
// 问题1: 测试逻辑完全相同
|
|
|
|
|
|
TEST_P(RHITestFixture, Shader_Test1) { shader = nullptr; EXPECT_EQ(shader, nullptr); }
|
|
|
|
|
|
TEST_P(RHITestFixture, Shader_Test2) { shader = nullptr; EXPECT_EQ(shader, nullptr); } // 相同!
|
|
|
|
|
|
|
|
|
|
|
|
// 问题2: 传递 nullptr 不验证功能
|
|
|
|
|
|
TEST_P(RHITestFixture, CommandList_Test) {
|
|
|
|
|
|
cmdList->ClearRenderTarget(nullptr, color); // 无意义
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 问题3: 不清理资源
|
|
|
|
|
|
TEST_P(RHITestFixture, Buffer_Test) {
|
|
|
|
|
|
RHIBuffer* buffer = device->CreateBuffer(desc);
|
|
|
|
|
|
// 忘记 buffer->Shutdown() 和 delete buffer
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 问题4: 缺少 ASSERT
|
|
|
|
|
|
TEST_P(RHITestFixture, Buffer_Test) {
|
|
|
|
|
|
RHIBuffer* buffer = device->CreateBuffer(desc);
|
|
|
|
|
|
buffer->SetData(...); // 如果 buffer 是 nullptr 则崩溃
|
|
|
|
|
|
// 应该先 ASSERT_NE(buffer, nullptr);
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 8. 附录:测试执行命令
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# 增量构建 RHI 测试
|
|
|
|
|
|
cmake --build . --target rhi_unit_tests --config Debug
|
|
|
|
|
|
cmake --build . --target rhi_d3d12_tests --config Debug
|
|
|
|
|
|
cmake --build . --target rhi_opengl_tests --config Debug
|
|
|
|
|
|
|
|
|
|
|
|
# 运行 RHI 抽象层测试 (同时验证 D3D12 和 OpenGL)
|
|
|
|
|
|
ctest -R "^D3D12/|^OpenGL/" -C Debug --output-on-failure
|
|
|
|
|
|
|
|
|
|
|
|
# 运行 D3D12 后端专用测试
|
|
|
|
|
|
ctest -R "D3D12TestFixture|SwapChainTestFixture" -C Debug --output-on-failure
|
|
|
|
|
|
|
|
|
|
|
|
# 运行 OpenGL 后端专用测试
|
|
|
|
|
|
ctest -R "OpenGLTestFixture" -C Debug --output-on-failure
|
|
|
|
|
|
|
|
|
|
|
|
# 运行所有 RHI 测试
|
|
|
|
|
|
ctest -R "D3D12|OpenGL|RHITestFixture" -C Debug --output-on-failure
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
2026-03-25 15:10:10 +08:00
|
|
|
|
**文档版本**: 1.4
|
2026-03-25 01:31:09 +08:00
|
|
|
|
**最后更新**: 2026-03-25
|
|
|
|
|
|
**作者**: XCEngine Team
|
2026-03-25 12:30:05 +08:00
|
|
|
|
|
|
|
|
|
|
## 更新日志
|
|
|
|
|
|
|
2026-03-25 15:10:10 +08:00
|
|
|
|
### v1.4 (2026-03-25)
|
|
|
|
|
|
- P1-7: Compute/Dispatch 测试 ✅ 已完成
|
|
|
|
|
|
- 新增 `test_compute.cpp`,8个测试
|
|
|
|
|
|
- 测试通过:D3D12 8 + OpenGL 8 = 16 tests
|
|
|
|
|
|
- 修复 shader type bugs:
|
|
|
|
|
|
- `D3D12Shader::Compile` 不设置 `m_type`
|
|
|
|
|
|
- `OpenGLShader::Compile(const void*,...)` 硬编码 Fragment
|
|
|
|
|
|
- `OpenGLShader::CompileCompute` 不设置 `m_type`
|
|
|
|
|
|
- 修复 `D3D12CommandList::SetPipelineState` 对 Compute PSO 用错 handle
|
|
|
|
|
|
- 测试结果:D3D12 116测试 + OpenGL 116测试 = 232测试全部通过
|
|
|
|
|
|
- 集成测试:8/8 全部通过
|
|
|
|
|
|
|
2026-03-25 13:21:13 +08:00
|
|
|
|
### v1.3 (2026-03-25)
|
|
|
|
|
|
- P1-5: DescriptorPool 测试 ✅ 已完成
|
|
|
|
|
|
- 新增 `test_descriptor.cpp`,8个 DescriptorPool 测试
|
|
|
|
|
|
- 测试通过:D3D12 8 + OpenGL 8 = 16 tests
|
|
|
|
|
|
- DescriptorSet 测试暂跳过(OpenGL 需要 GL context)
|
|
|
|
|
|
- 测试结果:D3D12 108测试 + OpenGL 108测试 = 216测试全部通过
|
|
|
|
|
|
- 集成测试:8/8 全部通过
|
|
|
|
|
|
|
2026-03-25 13:05:01 +08:00
|
|
|
|
### v1.2 (2026-03-25)
|
|
|
|
|
|
- P0-3: RenderPass 测试 ✅ 已完成
|
|
|
|
|
|
- 新增 `test_render_pass.cpp`,10个测试
|
|
|
|
|
|
- 添加 `CreateRenderPass/CreateFramebuffer` 到 `RHIDevice` 接口
|
|
|
|
|
|
- 实现 D3D12 和 OpenGL 后端
|
|
|
|
|
|
- 修复 D3D12 depth stencil 资源创建(自动设置 `D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL`)
|
|
|
|
|
|
- 修复 D3D12 RTV/DSV 空指针检查
|
|
|
|
|
|
- P0-4: Framebuffer 测试 ✅ 已完成
|
|
|
|
|
|
- 新增 `test_framebuffer.cpp`,8个测试
|
|
|
|
|
|
- 修复 `D3D12RenderPass` 的 `StoreAndResolve` 映射问题
|
|
|
|
|
|
- 测试结果:D3D12 100测试 + OpenGL 100测试 = 200测试全部通过
|
|
|
|
|
|
- 集成测试:8/8 全部通过
|
|
|
|
|
|
|
2026-03-25 12:30:05 +08:00
|
|
|
|
### v1.1 (2026-03-25)
|
|
|
|
|
|
- P0-1: Shader 测试重构 ✅ 已完成
|
|
|
|
|
|
- 添加 `ShaderLanguage` 枚举
|
|
|
|
|
|
- 扩展 `ShaderCompileDesc` 支持内嵌源码
|
|
|
|
|
|
- 9个相同测试 → 7个有效测试
|
|
|
|
|
|
- P0-2: PipelineState 测试 ✅ 已完成
|
|
|
|
|
|
- 新增 `test_pipeline_state.cpp`
|
|
|
|
|
|
- 修复 PSO 验证接口:`IsFinalized/Finalize` → `IsValid/EnsureValid`
|
|
|
|
|
|
- 10个测试覆盖创建、配置、状态查询、生命周期
|
|
|
|
|
|
|
|
|
|
|
|
### v1.0 (2026-03-25)
|
|
|
|
|
|
- 初始版本
|