From bc6b47ffcf9ef09bfda2c48317d481d2792a31f9 Mon Sep 17 00:00:00 2001 From: ssdfasd <2156608475@qq.com> Date: Mon, 23 Mar 2026 20:32:33 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20RHI=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=B8=8E=E5=91=BD=E5=90=8D=E8=A7=84=E8=8C=83?= =?UTF-8?q?=E7=BB=9F=E4=B8=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RHI抽象层测试修复: - OpenGL Shader: 空描述符正确返回nullptr - OpenGL Texture: 修复TextureType映射(case 2/3) - OpenGL Buffer: 设置stride和state支持 - OpenGL Texture: 添加Format和State支持 - OpenGL SwapChain: 修复IsFullscreen硬编码false问题 命名规范统一( snake_case + _test后缀): - D3D12_Minimal -> d3d12_minimal_test - D3D12_Triangle -> d3d12_triangle_test - D3D12_Quad -> d3d12_quad_test - D3D12_Sphere -> d3d12_sphere_test - OpenGL_Minimal -> opengl_minimal_test - OpenGL_Triangle -> opengl_triangle_test - OpenGL_Quad -> opengl_quad_test - OpenGL_Sphere -> opengl_sphere_test - CTest名称去掉_Integration后缀 测试结果: 138个测试中从21个失败减少到16个失败 --- .../XCEngine/RHI/OpenGL/OpenGLBuffer.h | 5 +- .../XCEngine/RHI/OpenGL/OpenGLSwapChain.h | 1 + .../XCEngine/RHI/OpenGL/OpenGLTexture.h | 5 +- engine/src/RHI/OpenGL/OpenGLDevice.cpp | 28 ++- engine/src/RHI/OpenGL/OpenGLSwapChain.cpp | 4 +- .../D3D12/integration/minimal/CMakeLists.txt | 28 +-- .../RHI/D3D12/integration/quad/CMakeLists.txt | 32 ++-- .../D3D12/integration/sphere/CMakeLists.txt | 30 +-- .../D3D12/integration/triangle/CMakeLists.txt | 30 +-- .../OpenGL/integration/minimal/CMakeLists.txt | 28 +-- .../OpenGL/integration/quad/CMakeLists.txt | 30 +-- .../OpenGL/integration/sphere/CMakeLists.txt | 30 +-- .../integration/triangle/CMakeLists.txt | 30 +-- tests/RHI/unit/CMakeLists.txt | 10 +- tests/TEST_SPEC.md | 175 +++++++++++++++--- 15 files changed, 302 insertions(+), 164 deletions(-) diff --git a/engine/include/XCEngine/RHI/OpenGL/OpenGLBuffer.h b/engine/include/XCEngine/RHI/OpenGL/OpenGLBuffer.h index bcd22f18..b17b4618 100644 --- a/engine/include/XCEngine/RHI/OpenGL/OpenGLBuffer.h +++ b/engine/include/XCEngine/RHI/OpenGL/OpenGLBuffer.h @@ -50,8 +50,8 @@ public: void* GetNativeHandle() override { return reinterpret_cast(static_cast(m_buffer)); } - ResourceStates GetState() const override { return ResourceStates::Common; } - void SetState(ResourceStates state) override { } + ResourceStates GetState() const override { return m_state; } + void SetState(ResourceStates state) override { m_state = state; } const std::string& GetName() const override { return m_name; } void SetName(const std::string& name) override { m_name = name; } @@ -65,6 +65,7 @@ private: BufferType m_bufferType = BufferType::Vertex; uint32_t m_stride = 0; std::string m_name; + ResourceStates m_state = ResourceStates::Common; }; } // namespace RHI diff --git a/engine/include/XCEngine/RHI/OpenGL/OpenGLSwapChain.h b/engine/include/XCEngine/RHI/OpenGL/OpenGLSwapChain.h index d28ab8ef..7cb8942c 100644 --- a/engine/include/XCEngine/RHI/OpenGL/OpenGLSwapChain.h +++ b/engine/include/XCEngine/RHI/OpenGL/OpenGLSwapChain.h @@ -70,6 +70,7 @@ private: int m_framebufferHeight; bool m_vsync; bool m_shouldClose; + bool m_fullscreen; PresentMode m_presentMode; }; diff --git a/engine/include/XCEngine/RHI/OpenGL/OpenGLTexture.h b/engine/include/XCEngine/RHI/OpenGL/OpenGLTexture.h index 7d8ddf08..dff8c430 100644 --- a/engine/include/XCEngine/RHI/OpenGL/OpenGLTexture.h +++ b/engine/include/XCEngine/RHI/OpenGL/OpenGLTexture.h @@ -82,8 +82,8 @@ public: void* GetNativeHandle() override { return reinterpret_cast(static_cast(m_texture)); } - ResourceStates GetState() const override { return ResourceStates::Common; } - void SetState(ResourceStates state) override { } + ResourceStates GetState() const override { return m_state; } + void SetState(ResourceStates state) override { m_state = state; } const std::string& GetName() const override { return m_name; } void SetName(const std::string& name) override { m_name = name; } @@ -101,6 +101,7 @@ private: int m_channels; Format m_format = Format::Unknown; std::string m_name; + ResourceStates m_state = ResourceStates::Common; }; } // namespace RHI diff --git a/engine/src/RHI/OpenGL/OpenGLDevice.cpp b/engine/src/RHI/OpenGL/OpenGLDevice.cpp index 2f51ee62..040e7337 100644 --- a/engine/src/RHI/OpenGL/OpenGLDevice.cpp +++ b/engine/src/RHI/OpenGL/OpenGLDevice.cpp @@ -349,6 +349,7 @@ RHIBuffer* OpenGLDevice::CreateBuffer(const BufferDesc& desc) { } buffer->Initialize(bufferType, desc.size, nullptr, false); + buffer->SetStride(desc.stride); return buffer; } @@ -361,9 +362,12 @@ RHITexture* OpenGLDevice::CreateTexture(const TextureDesc& desc) { type = OpenGLTextureType::Texture1D; break; case 2: - type = OpenGLTextureType::Texture3D; + type = OpenGLTextureType::Texture2DArray; break; case 3: + type = OpenGLTextureType::Texture3D; + break; + case 4: type = OpenGLTextureType::TextureCube; break; default: @@ -372,7 +376,20 @@ RHITexture* OpenGLDevice::CreateTexture(const TextureDesc& desc) { } OpenGLFormat format = OpenGLFormat::RGBA8; + switch (desc.format) { + case 1: format = OpenGLFormat::R8; break; + case 2: format = OpenGLFormat::RG8; break; + case 3: format = OpenGLFormat::RGBA8; break; + case 4: format = OpenGLFormat::RGBA16F; break; + case 5: format = OpenGLFormat::RGBA32F; break; + case 6: format = OpenGLFormat::RGBA16F; break; + case 7: format = OpenGLFormat::RGBA32F; break; + case 8: format = OpenGLFormat::Depth24Stencil8; break; + case 9: format = OpenGLFormat::Depth32F; break; + default: format = OpenGLFormat::RGBA8; break; + } texture->Initialize(type, desc.width, desc.height, desc.depth, desc.mipLevels, format, nullptr); + texture->SetFormat(static_cast(desc.format)); return texture; } @@ -395,13 +412,14 @@ RHICommandQueue* OpenGLDevice::CreateCommandQueue(const CommandQueueDesc& desc) } RHIShader* OpenGLDevice::CompileShader(const ShaderCompileDesc& desc) { - auto* shader = new OpenGLShader(); std::wstring filePath = desc.fileName; + if (filePath.empty()) { + return nullptr; + } + auto* shader = new OpenGLShader(); std::string entryPoint(desc.entryPoint.begin(), desc.entryPoint.end()); std::string profile(desc.profile.begin(), desc.profile.end()); - if (!filePath.empty()) { - shader->CompileFromFile(filePath.c_str(), entryPoint.c_str(), profile.c_str()); - } + shader->CompileFromFile(filePath.c_str(), entryPoint.c_str(), profile.c_str()); return shader; } diff --git a/engine/src/RHI/OpenGL/OpenGLSwapChain.cpp b/engine/src/RHI/OpenGL/OpenGLSwapChain.cpp index b7bf5355..929e9452 100644 --- a/engine/src/RHI/OpenGL/OpenGLSwapChain.cpp +++ b/engine/src/RHI/OpenGL/OpenGLSwapChain.cpp @@ -21,6 +21,7 @@ OpenGLSwapChain::OpenGLSwapChain() , m_framebufferHeight(0) , m_vsync(true) , m_shouldClose(false) + , m_fullscreen(false) , m_presentMode(PresentMode::VSync) { } @@ -146,10 +147,11 @@ void OpenGLSwapChain::Resize(uint32_t width, uint32_t height) { } void OpenGLSwapChain::SetFullscreen(bool fullscreen) { + m_fullscreen = fullscreen; } bool OpenGLSwapChain::IsFullscreen() const { - return false; + return m_fullscreen; } uint32_t OpenGLSwapChain::GetCurrentBackBufferIndex() const { diff --git a/tests/RHI/D3D12/integration/minimal/CMakeLists.txt b/tests/RHI/D3D12/integration/minimal/CMakeLists.txt index 0dd7bc93..ea77b489 100644 --- a/tests/RHI/D3D12/integration/minimal/CMakeLists.txt +++ b/tests/RHI/D3D12/integration/minimal/CMakeLists.txt @@ -2,26 +2,26 @@ cmake_minimum_required(VERSION 3.15) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) -project(D3D12_Minimal) +project(d3d12_minimal_test) set(ENGINE_ROOT_DIR ${CMAKE_SOURCE_DIR}/engine) -add_executable(D3D12_Minimal +add_executable(d3d12_minimal_test WIN32 main.cpp ) -target_include_directories(D3D12_Minimal PRIVATE +target_include_directories(d3d12_minimal_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${ENGINE_ROOT_DIR}/include ) -target_compile_definitions(D3D12_Minimal PRIVATE +target_compile_definitions(d3d12_minimal_test PRIVATE UNICODE _UNICODE ) -target_link_libraries(D3D12_Minimal PRIVATE +target_link_libraries(d3d12_minimal_test PRIVATE d3d12 dxgi d3dcompiler @@ -29,26 +29,26 @@ target_link_libraries(D3D12_Minimal PRIVATE XCEngine ) -add_custom_command(TARGET D3D12_Minimal POST_BUILD +add_custom_command(TARGET d3d12_minimal_test POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/tests/rhi/d3d12/integration/compare_ppm.py - $/ + $/ COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/tests/rhi/d3d12/integration/run_integration_test.py - $/ + $/ COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/GT.ppm - $/ + $/ COMMAND ${CMAKE_COMMAND} -E copy_if_different ${ENGINE_ROOT_DIR}/third_party/renderdoc/renderdoc.dll - $/ + $/ ) -add_test(NAME D3D12_Minimal_Integration - COMMAND ${Python3_EXECUTABLE} $/run_integration_test.py - $ +add_test(NAME d3d12_minimal_test + COMMAND ${Python3_EXECUTABLE} $/run_integration_test.py + $ minimal.ppm ${CMAKE_CURRENT_SOURCE_DIR}/GT.ppm 0 - WORKING_DIRECTORY $ + WORKING_DIRECTORY $ ) diff --git a/tests/RHI/D3D12/integration/quad/CMakeLists.txt b/tests/RHI/D3D12/integration/quad/CMakeLists.txt index 53e48e26..a619a592 100644 --- a/tests/RHI/D3D12/integration/quad/CMakeLists.txt +++ b/tests/RHI/D3D12/integration/quad/CMakeLists.txt @@ -2,29 +2,29 @@ cmake_minimum_required(VERSION 3.15) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) -project(D3D12_Quad) +project(d3d12_quad_test) set(ENGINE_ROOT_DIR ${CMAKE_SOURCE_DIR}/engine) -add_executable(D3D12_Quad +add_executable(d3d12_quad_test WIN32 main.cpp ) -set_target_properties(D3D12_Quad PROPERTIES LINK_FLAGS "/INCREMENTAL:NO") +set_target_properties(d3d12_quad_test PROPERTIES LINK_FLAGS "/INCREMENTAL:NO") -target_include_directories(D3D12_Quad PRIVATE +target_include_directories(d3d12_quad_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${ENGINE_ROOT_DIR}/include ${ENGINE_ROOT_DIR} ) -target_compile_definitions(D3D12_Quad PRIVATE +target_compile_definitions(d3d12_quad_test PRIVATE UNICODE _UNICODE ) -target_link_libraries(D3D12_Quad PRIVATE +target_link_libraries(d3d12_quad_test PRIVATE d3d12 dxgi d3dcompiler @@ -32,29 +32,29 @@ target_link_libraries(D3D12_Quad PRIVATE XCEngine ) -add_custom_command(TARGET D3D12_Quad POST_BUILD +add_custom_command(TARGET d3d12_quad_test POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/Res - $/Res + $/Res ) -add_custom_command(TARGET D3D12_Quad POST_BUILD +add_custom_command(TARGET d3d12_quad_test POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/tests/rhi/d3d12/integration/compare_ppm.py - $/ + $/ COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/tests/rhi/d3d12/integration/run_integration_test.py - $/ + $/ COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/GT.ppm - $/ + $/ ) -add_test(NAME D3D12_Quad_Integration - COMMAND ${Python3_EXECUTABLE} $/run_integration_test.py - $ +add_test(NAME d3d12_quad_test + COMMAND ${Python3_EXECUTABLE} $/run_integration_test.py + $ quad.ppm ${CMAKE_CURRENT_SOURCE_DIR}/GT.ppm 0 - WORKING_DIRECTORY $ + WORKING_DIRECTORY $ ) \ No newline at end of file diff --git a/tests/RHI/D3D12/integration/sphere/CMakeLists.txt b/tests/RHI/D3D12/integration/sphere/CMakeLists.txt index b41aa60b..7185247f 100644 --- a/tests/RHI/D3D12/integration/sphere/CMakeLists.txt +++ b/tests/RHI/D3D12/integration/sphere/CMakeLists.txt @@ -2,27 +2,27 @@ cmake_minimum_required(VERSION 3.15) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) -project(D3D12_Sphere) +project(d3d12_sphere_test) set(ENGINE_ROOT_DIR ${CMAKE_SOURCE_DIR}/engine) -add_executable(D3D12_Sphere +add_executable(d3d12_sphere_test WIN32 main.cpp ) -target_include_directories(D3D12_Sphere PRIVATE +target_include_directories(d3d12_sphere_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${ENGINE_ROOT_DIR}/include ${ENGINE_ROOT_DIR} ) -target_compile_definitions(D3D12_Sphere PRIVATE +target_compile_definitions(d3d12_sphere_test PRIVATE UNICODE _UNICODE ) -target_link_libraries(D3D12_Sphere PRIVATE +target_link_libraries(d3d12_sphere_test PRIVATE d3d12 dxgi d3dcompiler @@ -30,29 +30,29 @@ target_link_libraries(D3D12_Sphere PRIVATE XCEngine ) -add_custom_command(TARGET D3D12_Sphere POST_BUILD +add_custom_command(TARGET d3d12_sphere_test POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/Res - $/Res + $/Res ) -add_custom_command(TARGET D3D12_Sphere POST_BUILD +add_custom_command(TARGET d3d12_sphere_test POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/tests/rhi/d3d12/integration/compare_ppm.py - $/ + $/ COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/tests/rhi/d3d12/integration/run_integration_test.py - $/ + $/ COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/GT.ppm - $/ + $/ ) -add_test(NAME D3D12_Sphere_Integration - COMMAND ${Python3_EXECUTABLE} $/run_integration_test.py - $ +add_test(NAME d3d12_sphere_test + COMMAND ${Python3_EXECUTABLE} $/run_integration_test.py + $ sphere.ppm ${CMAKE_CURRENT_SOURCE_DIR}/GT.ppm 0 - WORKING_DIRECTORY $ + WORKING_DIRECTORY $ ) diff --git a/tests/RHI/D3D12/integration/triangle/CMakeLists.txt b/tests/RHI/D3D12/integration/triangle/CMakeLists.txt index 7078e717..ee1e9df9 100644 --- a/tests/RHI/D3D12/integration/triangle/CMakeLists.txt +++ b/tests/RHI/D3D12/integration/triangle/CMakeLists.txt @@ -2,26 +2,26 @@ cmake_minimum_required(VERSION 3.15) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) -project(D3D12_Triangle) +project(d3d12_triangle_test) set(ENGINE_ROOT_DIR ${CMAKE_SOURCE_DIR}/engine) -add_executable(D3D12_Triangle +add_executable(d3d12_triangle_test WIN32 main.cpp ) -target_include_directories(D3D12_Triangle PRIVATE +target_include_directories(d3d12_triangle_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${ENGINE_ROOT_DIR}/include ) -target_compile_definitions(D3D12_Triangle PRIVATE +target_compile_definitions(d3d12_triangle_test PRIVATE UNICODE _UNICODE ) -target_link_libraries(D3D12_Triangle PRIVATE +target_link_libraries(d3d12_triangle_test PRIVATE d3d12 dxgi d3dcompiler @@ -29,29 +29,29 @@ target_link_libraries(D3D12_Triangle PRIVATE XCEngine ) -add_custom_command(TARGET D3D12_Triangle POST_BUILD +add_custom_command(TARGET d3d12_triangle_test POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/Res - $/Res + $/Res ) -add_custom_command(TARGET D3D12_Triangle POST_BUILD +add_custom_command(TARGET d3d12_triangle_test POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/tests/rhi/d3d12/integration/compare_ppm.py - $/ + $/ COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/tests/rhi/d3d12/integration/run_integration_test.py - $/ + $/ COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/GT.ppm - $/ + $/ ) -add_test(NAME D3D12_Triangle_Integration - COMMAND ${Python3_EXECUTABLE} $/run_integration_test.py - $ +add_test(NAME d3d12_triangle_test + COMMAND ${Python3_EXECUTABLE} $/run_integration_test.py + $ triangle.ppm ${CMAKE_CURRENT_SOURCE_DIR}/GT.ppm 0 - WORKING_DIRECTORY $ + WORKING_DIRECTORY $ ) diff --git a/tests/RHI/OpenGL/integration/minimal/CMakeLists.txt b/tests/RHI/OpenGL/integration/minimal/CMakeLists.txt index 19d94fec..f1b7c752 100644 --- a/tests/RHI/OpenGL/integration/minimal/CMakeLists.txt +++ b/tests/RHI/OpenGL/integration/minimal/CMakeLists.txt @@ -2,53 +2,53 @@ cmake_minimum_required(VERSION 3.15) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) -project(OpenGL_Minimal) +project(opengl_minimal_test) set(ENGINE_ROOT_DIR ${CMAKE_SOURCE_DIR}/engine) set(PACKAGE_DIR ${CMAKE_SOURCE_DIR}/tests/opengl/package) -add_executable(OpenGL_Minimal +add_executable(opengl_minimal_test WIN32 main.cpp ${PACKAGE_DIR}/src/glad.c ) -target_include_directories(OpenGL_Minimal PRIVATE +target_include_directories(opengl_minimal_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${ENGINE_ROOT_DIR}/include ${PACKAGE_DIR}/include ) -target_link_libraries(OpenGL_Minimal PRIVATE +target_link_libraries(opengl_minimal_test PRIVATE opengl32 XCEngine ) -target_compile_definitions(OpenGL_Minimal PRIVATE +target_compile_definitions(opengl_minimal_test PRIVATE UNICODE _UNICODE ) -add_custom_command(TARGET OpenGL_Minimal POST_BUILD +add_custom_command(TARGET opengl_minimal_test POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/tests/rhi/opengl/integration/run_integration_test.py - $/ + $/ COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/tests/rhi/opengl/integration/compare_ppm.py - $/ + $/ COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/GT.ppm - $/ + $/ COMMAND ${CMAKE_COMMAND} -E copy_if_different ${ENGINE_ROOT_DIR}/third_party/renderdoc/renderdoc.dll - $/ + $/ ) -add_test(NAME OpenGL_Minimal_Integration - COMMAND ${Python3_EXECUTABLE} $/run_integration_test.py - $ +add_test(NAME opengl_minimal_test + COMMAND ${Python3_EXECUTABLE} $/run_integration_test.py + $ minimal.ppm ${CMAKE_CURRENT_SOURCE_DIR}/GT.ppm 5 - WORKING_DIRECTORY $ + WORKING_DIRECTORY $ ) diff --git a/tests/RHI/OpenGL/integration/quad/CMakeLists.txt b/tests/RHI/OpenGL/integration/quad/CMakeLists.txt index a0aa0fa2..e605a212 100644 --- a/tests/RHI/OpenGL/integration/quad/CMakeLists.txt +++ b/tests/RHI/OpenGL/integration/quad/CMakeLists.txt @@ -2,56 +2,56 @@ cmake_minimum_required(VERSION 3.15) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) -project(OpenGL_Quad) +project(opengl_quad_test) set(ENGINE_ROOT_DIR ${CMAKE_SOURCE_DIR}/engine) set(PACKAGE_DIR ${CMAKE_SOURCE_DIR}/tests/opengl/package) -add_executable(OpenGL_Quad +add_executable(opengl_quad_test WIN32 main.cpp ${PACKAGE_DIR}/src/glad.c ) -target_include_directories(OpenGL_Quad PRIVATE +target_include_directories(opengl_quad_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${ENGINE_ROOT_DIR}/include ${PACKAGE_DIR}/include ) -target_link_libraries(OpenGL_Quad PRIVATE +target_link_libraries(opengl_quad_test PRIVATE opengl32 XCEngine ) -target_compile_definitions(OpenGL_Quad PRIVATE +target_compile_definitions(opengl_quad_test PRIVATE UNICODE _UNICODE ) -add_custom_command(TARGET OpenGL_Quad POST_BUILD +add_custom_command(TARGET opengl_quad_test POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/Res - $/Res + $/Res ) -add_custom_command(TARGET OpenGL_Quad POST_BUILD +add_custom_command(TARGET opengl_quad_test POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/tests/rhi/opengl/integration/run_integration_test.py - $/ + $/ COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/tests/rhi/opengl/integration/compare_ppm.py - $/ + $/ COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/GT.ppm - $/ + $/ ) -add_test(NAME OpenGL_Quad_Integration - COMMAND ${Python3_EXECUTABLE} $/run_integration_test.py - $ +add_test(NAME opengl_quad_test + COMMAND ${Python3_EXECUTABLE} $/run_integration_test.py + $ quad.ppm ${CMAKE_CURRENT_SOURCE_DIR}/GT.ppm 5 - WORKING_DIRECTORY $ + WORKING_DIRECTORY $ ) \ No newline at end of file diff --git a/tests/RHI/OpenGL/integration/sphere/CMakeLists.txt b/tests/RHI/OpenGL/integration/sphere/CMakeLists.txt index ac23e3ba..596ac57b 100644 --- a/tests/RHI/OpenGL/integration/sphere/CMakeLists.txt +++ b/tests/RHI/OpenGL/integration/sphere/CMakeLists.txt @@ -2,56 +2,56 @@ cmake_minimum_required(VERSION 3.15) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) -project(OpenGL_Sphere) +project(opengl_sphere_test) set(ENGINE_ROOT_DIR ${CMAKE_SOURCE_DIR}/engine) set(PACKAGE_DIR ${CMAKE_SOURCE_DIR}/tests/opengl/package) -add_executable(OpenGL_Sphere +add_executable(opengl_sphere_test WIN32 main.cpp ${PACKAGE_DIR}/src/glad.c ) -target_include_directories(OpenGL_Sphere PRIVATE +target_include_directories(opengl_sphere_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${ENGINE_ROOT_DIR}/include ${PACKAGE_DIR}/include ) -target_link_libraries(OpenGL_Sphere PRIVATE +target_link_libraries(opengl_sphere_test PRIVATE opengl32 XCEngine ) -target_compile_definitions(OpenGL_Sphere PRIVATE +target_compile_definitions(opengl_sphere_test PRIVATE UNICODE _UNICODE ) -add_custom_command(TARGET OpenGL_Sphere POST_BUILD +add_custom_command(TARGET opengl_sphere_test POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/Res - $/Res + $/Res ) -add_custom_command(TARGET OpenGL_Sphere POST_BUILD +add_custom_command(TARGET opengl_sphere_test POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/tests/rhi/opengl/integration/run_integration_test.py - $/ + $/ COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/tests/rhi/opengl/integration/compare_ppm.py - $/ + $/ COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/GT.ppm - $/ + $/ ) -add_test(NAME OpenGL_Sphere_Integration - COMMAND ${Python3_EXECUTABLE} $/run_integration_test.py - $ +add_test(NAME opengl_sphere_test + COMMAND ${Python3_EXECUTABLE} $/run_integration_test.py + $ sphere.ppm ${CMAKE_CURRENT_SOURCE_DIR}/GT.ppm 5 - WORKING_DIRECTORY $ + WORKING_DIRECTORY $ ) \ No newline at end of file diff --git a/tests/RHI/OpenGL/integration/triangle/CMakeLists.txt b/tests/RHI/OpenGL/integration/triangle/CMakeLists.txt index b38f774e..27c95541 100644 --- a/tests/RHI/OpenGL/integration/triangle/CMakeLists.txt +++ b/tests/RHI/OpenGL/integration/triangle/CMakeLists.txt @@ -2,56 +2,56 @@ cmake_minimum_required(VERSION 3.15) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) -project(OpenGL_Triangle) +project(opengl_triangle_test) set(ENGINE_ROOT_DIR ${CMAKE_SOURCE_DIR}/engine) set(PACKAGE_DIR ${CMAKE_SOURCE_DIR}/tests/opengl/package) -add_executable(OpenGL_Triangle +add_executable(opengl_triangle_test WIN32 main.cpp ${PACKAGE_DIR}/src/glad.c ) -target_include_directories(OpenGL_Triangle PRIVATE +target_include_directories(opengl_triangle_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${ENGINE_ROOT_DIR}/include ${PACKAGE_DIR}/include ) -target_link_libraries(OpenGL_Triangle PRIVATE +target_link_libraries(opengl_triangle_test PRIVATE opengl32 XCEngine ) -target_compile_definitions(OpenGL_Triangle PRIVATE +target_compile_definitions(opengl_triangle_test PRIVATE UNICODE _UNICODE ) -add_custom_command(TARGET OpenGL_Triangle POST_BUILD +add_custom_command(TARGET opengl_triangle_test POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/Res - $/Res + $/Res ) -add_custom_command(TARGET OpenGL_Triangle POST_BUILD +add_custom_command(TARGET opengl_triangle_test POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/tests/rhi/opengl/integration/run_integration_test.py - $/ + $/ COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/tests/rhi/opengl/integration/compare_ppm.py - $/ + $/ COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/GT.ppm - $/ + $/ ) -add_test(NAME OpenGL_Triangle_Integration - COMMAND ${Python3_EXECUTABLE} $/run_integration_test.py - $ +add_test(NAME opengl_triangle_test + COMMAND ${Python3_EXECUTABLE} $/run_integration_test.py + $ triangle.ppm ${CMAKE_CURRENT_SOURCE_DIR}/GT.ppm 5 - WORKING_DIRECTORY $ + WORKING_DIRECTORY $ ) \ No newline at end of file diff --git a/tests/RHI/unit/CMakeLists.txt b/tests/RHI/unit/CMakeLists.txt index b5fa699f..7d15eaaa 100644 --- a/tests/RHI/unit/CMakeLists.txt +++ b/tests/RHI/unit/CMakeLists.txt @@ -18,11 +18,11 @@ set(TEST_SOURCES ${CMAKE_SOURCE_DIR}/tests/opengl/package/src/glad.c ) -add_executable(rhi_tests ${TEST_SOURCES}) +add_executable(rhi_unit_tests ${TEST_SOURCES}) -target_compile_definitions(rhi_tests PRIVATE XCENGINE_SUPPORT_OPENGL) +target_compile_definitions(rhi_unit_tests PRIVATE XCENGINE_SUPPORT_OPENGL) -target_link_libraries(rhi_tests PRIVATE +target_link_libraries(rhi_unit_tests PRIVATE d3d12 dxgi d3dcompiler @@ -32,7 +32,7 @@ target_link_libraries(rhi_tests PRIVATE GTest::gtest_main ) -target_include_directories(rhi_tests PRIVATE +target_include_directories(rhi_unit_tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/fixtures ${PROJECT_ROOT_DIR}/engine/include ${PROJECT_ROOT_DIR}/engine/src @@ -40,4 +40,4 @@ target_include_directories(rhi_tests PRIVATE ) include(GoogleTest) -gtest_discover_tests(rhi_tests) +gtest_discover_tests(rhi_unit_tests) diff --git a/tests/TEST_SPEC.md b/tests/TEST_SPEC.md index b03b96c9..13b62d0e 100644 --- a/tests/TEST_SPEC.md +++ b/tests/TEST_SPEC.md @@ -20,22 +20,45 @@ tests/ ├── containers/ # 容器测试 ├── memory/ # 内存管理测试 ├── threading/ # 线程测试 -├── debug/ # 调试系统测试 -├── resources/ # 资源系统测试 -├── input/ # 输入模块测试 -├── scene/ # 场景测试 -├── components/ # 组件测试 +├── debug/ # 调试系统测试 +├── resources/ # 资源系统测试 +├── input/ # 输入模块测试 +├── scene/ # 场景测试 +├── components/ # 组件测试 └── rhi/ - ├── d3d12/ # D3D12 RHI 测试 - │ ├── unit/ # 单元测试 - │ ├── integration/ # 集成测试 - │ └── CMakeLists.txt - └── opengl/ # OpenGL RHI 测试 - ├── unit/ # 单元测试 - ├── integration/ # 集成测试 - └── CMakeLists.txt + ├── CMakeLists.txt # RHI 测试主 CMake (包含 D3D12/OpenGL/unit) + ├── unit/ # RHI 抽象层单元测试 (参数化, 同时测 D3D12/OpenGL) + │ ├── CMakeLists.txt + │ ├── fixtures/ + │ └── test_*.cpp + ├── d3d12/ # D3D12 后端封装测试 + │ ├── CMakeLists.txt + │ ├── unit/ # D3D12 单元测试 + │ │ ├── fixtures/ + │ │ └── test_*.cpp + │ └── integration/ # D3D12 集成测试 (minimal/triangle/quad/sphere) + └── opengl/ # OpenGL 后端封装测试 + ├── CMakeLists.txt + ├── unit/ # OpenGL 单元测试 + │ ├── fixtures/ + │ └── test_*.cpp + └── integration/ # OpenGL 集成测试 ``` +### 2.1 RHI 测试分层架构 + +RHI 测试分为三个层次,各层测试目标不同: + +| 层次 | 位置 | 测试目标 | 测试方式 | +|------|------|----------|----------| +| **RHI抽象层** | `tests/RHI/unit/` | RHI接口定义、跨平台抽象、后端选择 | 参数化测试 (TEST_P),一份代码同时测试 D3D12/OpenGL | +| **D3D12后端封装** | `tests/RHI/D3D12/unit/` | D3D12 API封装实现 | 非参数化测试 (TEST_F),直接测试D3D12封装 | +| **OpenGL后端封装** | `tests/RHI/OpenGL/unit/` | OpenGL API封装实现 | 非参数化测试 (TEST_F),直接测试OpenGL封装 | + +**注意**:三层测试不是冗余,而是测试不同层次的封装。各层测试可以验证: +- RHI抽象层测试验证接口兼容性和跨平台一致性 +- 后端专用测试验证各后端实现的正确性 + --- ## 3. 模块命名 @@ -52,8 +75,27 @@ tests/ | input | input_tests | Input*/WindowsInput* | | scene | scene_tests | Scene*/SceneManager_* | | components | components_tests | Component_*|TransformComponent_* | -| RHI/D3D12 | rhi_d3d12_tests | D3D12*Fixture/SwapChain*Fixture | -| RHI/OpenGL | opengl_engine_tests | OpenGLTestFixture.* | +| RHI/unit (抽象层) | rhi_unit_tests | D3D12/RHITestFixture.*
OpenGL/RHITestFixture.* | +| RHI/D3D12 (后端) | rhi_d3d12_tests | D3D12TestFixture.*
SwapChainTestFixture.* | +| RHI/OpenGL (后端) | rhi_opengl_tests | OpenGLTestFixture.* | + +### 3.1 RHI 参数化测试说明 + +`tests/RHI/unit/` 使用 Google Test 参数化测试 (TEST_P): + +```cpp +// 使用 INSTANTIATE_TEST_SUITE_P 创建两个测试变体 +INSTANTIATE_TEST_SUITE_P(D3D12, RHITestFixture, ::testing::Values(RHIType::D3D12)); +INSTANTIATE_TEST_SUITE_P(OpenGL, RHITestFixture, ::testing::Values(RHIType::OpenGL)); + +// 测试名称格式: Suite/TestName/Instance +// 例如: D3D12/RHITestFixture.Buffer_Create/0 +// OpenGL/RHITestFixture.Buffer_Create/0 +``` + +**CTest 前缀说明**: +- `D3D12/` - D3D12 后端实例 +- `OpenGL/` - OpenGL 后端实例 --- @@ -177,7 +219,9 @@ cmake .. cmake --build . --target math_tests --config Debug # 3. 只构建特定模块 -cmake --build . --target rhi_d3d12_tests --config Debug +cmake --build . --target rhi_unit_tests --config Debug # RHI抽象层测试 +cmake --build . --target rhi_d3d12_tests --config Debug # D3D12后端测试 +cmake --build . --target rhi_opengl_tests --config Debug # OpenGL后端测试 ``` ### 6.2 完整构建 @@ -197,10 +241,22 @@ ctest -N ctest -C Debug --output-on-failure # 运行特定模块测试 -ctest -R "Math_" -C Debug --output-on-failure +ctest -R "^Math_" -C Debug --output-on-failure -# 运行 D3D12 所有测试 -ctest -R "D3D12" -C Debug --output-on-failure +# 运行 RHI 抽象层测试 (D3D12 + OpenGL 同时测试) +ctest -R "^D3D12/|^OpenGL/" -C Debug --output-on-failure + +# 只运行 RHI 抽象层的 D3D12 后端测试 +ctest -R "^D3D12/" -C Debug --output-on-failure + +# 只运行 RHI 抽象层的 OpenGL 后端测试 +ctest -R "^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 # 运行特定测试用例 ctest -R "Buffer_Create" -C Debug --output-on-failure @@ -263,7 +319,7 @@ jobs: ### 9.1 模块构建和运行时间 | 模块 | 构建时间 | 运行时间 | 测试数量 | -|------|---------|---------|----------| +|------|---------|---------|---------| | math | ~6s | ~26s | 140 | | core | ~6s | ~4s | 18 | | containers | ~3s | ~10s | 51 | @@ -274,9 +330,12 @@ jobs: | scene | ~4s | ~2s | 14 | | resources | ~4s | ~31s | 131 | | input | ~4s | ~9s | 40 | -| D3D12 unit | ~3s | ~55s | 49 | +| RHI/unit (抽象层) | ~20s | ~60s | 138 (69×2后端) | +| D3D12 unit | ~3s | ~55s | 54 | | OpenGL unit | ~46s | ~11s | 61 | -| **总计** | - | - | **~622** | +| **总计** | - | - | **~760** | + +**注意**:RHI/unit 抽象层测试数量为 69 个用例,每个用例同时在 D3D12 和 OpenGL 两个后端上执行,共 138 次测试运行。 ### 9.2 分模块构建命令(推荐) @@ -294,8 +353,9 @@ cmake --build . --target components_tests --config Debug cmake --build . --target scene_tests --config Debug cmake --build . --target resources_tests --config Debug cmake --build . --target input_tests --config Debug +cmake --build . --target rhi_unit_tests --config Debug # RHI抽象层测试 cmake --build . --target rhi_d3d12_tests --config Debug -cmake --build . --target opengl_engine_tests --config Debug +cmake --build . --target rhi_opengl_tests --config Debug # 2. 只运行该模块测试 ctest -R "^Math_" -C Debug --output-on-failure @@ -308,8 +368,9 @@ ctest -R "Component_Test|TransformComponent_" -C Debug --output-on-failure ctest -R "^Scene_" -C Debug --output-on-failure ctest -R "Resource[A-Z]|Texture[A-Z]|Mesh[A-Z]|Shader[A-Z]|Audio[A-Z]|Material[A-Z]" -C Debug --output-on-failure ctest -R "Input|WindowsInput" -C Debug --output-on-failure -ctest -R "D3D12.*Fixture|SwapChain.*Fixture" -C Debug --output-on-failure -build/tests/RHI/OpenGL/unit/Debug/opengl_engine_tests.exe --gtest_filter=* +ctest -R "^D3D12/|^OpenGL/" -C Debug --output-on-failure # RHI抽象层测试 +ctest -R "D3D12TestFixture|SwapChainTestFixture" -C Debug --output-on-failure # D3D12后端测试 +ctest -R "OpenGLTestFixture" -C Debug --output-on-failure # OpenGL后端测试 ``` ### 9.3 按功能组构建和运行 @@ -335,19 +396,73 @@ cmake --build . --target input_tests --config Debug ctest -R "Component_Test|TransformComponent_|^Scene_|Resource[A-Z]|Texture[A-Z]|Mesh[A-Z]|Input|WindowsInput" -C Debug --output-on-failure # ==================== RHI 模块 ==================== +# RHI抽象层测试 (推荐优先测试,同时验证D3D12和OpenGL) +cmake --build . --target rhi_unit_tests --config Debug +ctest -R "^D3D12/|^OpenGL/" -C Debug --output-on-failure + +# RHI后端专用测试 (验证特定后端实现) cmake --build . --target rhi_d3d12_tests --config Debug -cmake --build . --target opengl_engine_tests --config Debug -ctest -R "D3D12.*Fixture|SwapChain.*Fixture" -C Debug --output-on-failure -build/tests/RHI/OpenGL/unit/Debug/opengl_engine_tests.exe --gtest_filter=* +cmake --build . --target rhi_opengl_tests --config Debug +ctest -R "D3D12TestFixture|SwapChainTestFixture" -C Debug --output-on-failure +ctest -R "OpenGLTestFixture" -C Debug --output-on-failure ``` ### 9.4 注意事项 -- **OpenGL 单元测试**:构建时间较长(~46s),因为需要编译 glad.c。建议单独构建 -- **D3D12 单元测试**:运行时间较长(~55s),适合 CI 自动化 +- **RHI/unit 抽象层测试**:运行时间~60s,138次测试(69用例×2后端)。推荐优先测试,可快速验证接口兼容性和跨平台一致性 +- **OpenGL 后端测试**:构建时间较长(~46s),因为需要编译 glad.c。建议单独构建 +- **D3D12 后端测试**:运行时间较长(~55s),适合 CI 自动化 - **Resources 模块**:运行时间~31s,包含大量资源加载测试 - **Math 模块**:运行时间~26s,包含140个数学运算测试 --- **最后更新**: 2026-03-23 + +--- + +## 附录 A. RHI 测试分层详解 + +### A.1 为什么需要三层测试? + +RHI(Render Hardware Interface)抽象层测试的目的是确保: +1. **接口兼容性** - RHI定义的抽象接口在不同后端都能正常工作 +2. **跨平台一致性** - 同样的代码逻辑在D3D12和OpenGL上行为一致 +3. **后端实现正确性** - 各后端的封装实现符合RHI接口约定 + +### A.2 三层测试的关系 + +``` +┌─────────────────────────────────────────────────────────────┐ +│ RHI 抽象层测试 (unit/) │ +│ TEST_P: 一份代码,验证 D3D12/OpenGL 接口兼容 │ +│ 实例: D3D12/RHITestFixture.* / OpenGL/RHITestFixture.* │ +└─────────────────────────────────────────────────────────────┘ + │ + ┌───────────────────┴───────────────────┐ + ▼ ▼ +┌─────────────────────────┐ ┌─────────────────────────┐ +│ D3D12 后端测试 │ │ OpenGL 后端测试 │ +│ (D3D12/unit/) │ │ (OpenGL/unit/) │ +│ TEST_F: D3D12 专用 │ │ TEST_F: OpenGL 专用 │ +│ 验证 D3D12 封装实现 │ │ 验证 OpenGL 封装实现 │ +└─────────────────────────┘ └─────────────────────────┘ +``` + +### A.3 测试执行建议 + +| 场景 | 推荐测试 | +|------|---------| +| 日常开发 (RHI 接口验证) | `rhi_unit_tests` | +| 开发 D3D12 后端 | `rhi_unit_tests` + `rhi_d3d12_tests` | +| 开发 OpenGL 后端 | `rhi_unit_tests` + `rhi_opengl_tests` | +| CI 自动化 | `rhi_unit_tests` + `rhi_d3d12_tests` + `rhi_opengl_tests` | + +### A.4 可执行文件命名规范 + +``` +rhi_<层级>_tests +├── rhi_unit_tests # RHI抽象层测试 +├── rhi_d3d12_tests # D3D12后端封装测试 +└── rhi_opengl_tests # OpenGL后端封装测试 +```