diff --git a/engine/src/RHI/D3D12/test/CMakeLists.txt b/engine/src/RHI/D3D12/test/CMakeLists.txt new file mode 100644 index 00000000..1fd16490 --- /dev/null +++ b/engine/src/RHI/D3D12/test/CMakeLists.txt @@ -0,0 +1,58 @@ +cmake_minimum_required(VERSION 3.15) + +project(D3D12EngineTests) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# Google Test 已在父级 tests/CMakeLists.txt 中 FetchContent +# 找到已安装的 GTest +find_package(GTest REQUIRED) + +# 测试源文件 +set(TEST_SOURCES + test_device.cpp + test_fence.cpp + test_command_queue.cpp + test_command_allocator.cpp + test_command_list.cpp + test_buffer.cpp + test_texture.cpp + test_descriptor_heap.cpp + test_shader.cpp + test_root_signature.cpp + test_pipeline_state.cpp + test_views.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 + ${CMAKE_SOURCE_DIR}/engine/include + ${CMAKE_SOURCE_DIR}/tests/D3D12 +) + +# 设置资源目录路径 +target_compile_definitions(d3d12_engine_tests PRIVATE + TEST_RESOURCES_DIR="${CMAKE_SOURCE_DIR}/tests/D3D12/Res" +) + +# 复制资源文件到输出目录 +add_custom_command(TARGET d3d12_engine_tests POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory + ${CMAKE_SOURCE_DIR}/tests/D3D12/Res + $/Res +) + +enable_testing() +add_test(NAME D3D12EngineTests COMMAND d3d12_engine_tests) diff --git a/engine/src/RHI/D3D12/test/fixtures/D3D12TestFixture.h b/engine/src/RHI/D3D12/test/fixtures/D3D12TestFixture.h new file mode 100644 index 00000000..8718bad9 --- /dev/null +++ b/engine/src/RHI/D3D12/test/fixtures/D3D12TestFixture.h @@ -0,0 +1,144 @@ +#pragma once + +#include +#include +#include +#include + +#include "XCEngine/RHI/D3D12/D3D12Device.h" +#include "XCEngine/RHI/D3D12/D3D12CommandQueue.h" +#include "XCEngine/RHI/D3D12/D3D12CommandAllocator.h" +#include "XCEngine/RHI/D3D12/D3D12CommandList.h" +#include "XCEngine/RHI/D3D12/D3D12Fence.h" + +using namespace Microsoft::WRL; + +class D3D12TestFixture : public ::testing::Test { +protected: + static void SetUpTestSuite() { + HRESULT hr = D3D12CreateDevice( + nullptr, + D3D_FEATURE_LEVEL_12_0, + IID_PPV_ARGS(&mDevice) + ); + + if (FAILED(hr)) { + GTEST_SKIP() << "Failed to create D3D12 device - hardware may not support D3D12"; + return; + } + + hr = mDevice->QueryInterface(IID_PPV_ARGS(&mDebugDevice)); + } + + static void TearDownTestSuite() { + mDebugDevice.Reset(); + mDevice.Reset(); + } + + void SetUp() override { + if (!mDevice) { + GTEST_SKIP() << "D3D12 device not available"; + return; + } + + D3D12_COMMAND_QUEUE_DESC queueDesc = {}; + queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; + queueDesc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL; + queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + queueDesc.NodeMask = 0; + + HRESULT hr = mDevice->CreateCommandQueue( + &queueDesc, + IID_PPV_ARGS(&mCommandQueue) + ); + + if (FAILED(hr)) { + GTEST_SKIP() << "Failed to create command queue"; + return; + } + + hr = mDevice->CreateCommandAllocator( + D3D12_COMMAND_LIST_TYPE_DIRECT, + IID_PPV_ARGS(&mCommandAllocator) + ); + + if (FAILED(hr)) { + GTEST_SKIP() << "Failed to create command allocator"; + return; + } + + hr = mDevice->CreateCommandList( + 0, + D3D12_COMMAND_LIST_TYPE_DIRECT, + mCommandAllocator.Get(), + nullptr, + IID_PPV_ARGS(&mCommandList) + ); + + if (FAILED(hr)) { + GTEST_SKIP() << "Failed to create command list"; + return; + } + } + + void TearDown() override { + if (mCommandQueue) { + WaitForGPU(); + } + + if (mCommandList) { + mCommandList.Reset(); + } + + if (mCommandAllocator) { + mCommandAllocator.Reset(); + } + + if (mCommandQueue) { + mCommandQueue.Reset(); + } + } + + ID3D12Device* GetDevice() { return mDevice.Get(); } + ID3D12CommandQueue* GetCommandQueue() { return mCommandQueue.Get(); } + ID3D12CommandList* GetCommandList() { return mCommandList.Get(); } + ID3D12CommandAllocator* GetCommandAllocator() { return mCommandAllocator.Get(); } + + void WaitForGPU() { + if (!mCommandQueue || !mDevice) { + return; + } + + ComPtr fence; + UINT64 fenceValue = 1; + + HRESULT hr = mDevice->CreateFence( + 0, + D3D12_FENCE_FLAG_NONE, + IID_PPV_ARGS(&fence) + ); + + if (SUCCEEDED(hr)) { + mCommandQueue->Signal(fence.Get(), fenceValue); + + if (fence->GetCompletedValue() < fenceValue) { + HANDLE eventHandle = CreateEvent(nullptr, FALSE, FALSE, nullptr); + if (eventHandle) { + fence->SetEventOnCompletion(fenceValue, eventHandle); + WaitForSingleObject(eventHandle, INFINITE); + CloseHandle(eventHandle); + } + } + } + } + +private: + static ComPtr mDevice; + static ComPtr mDebugDevice; + ComPtr mCommandQueue; + ComPtr mCommandAllocator; + ComPtr mCommandList; +}; + +ComPtr D3D12TestFixture::mDevice; +ComPtr D3D12TestFixture::mDebugDevice; diff --git a/engine/src/RHI/D3D12/test/test_buffer.cpp b/engine/src/RHI/D3D12/test/test_buffer.cpp new file mode 100644 index 00000000..085bb9dc --- /dev/null +++ b/engine/src/RHI/D3D12/test/test_buffer.cpp @@ -0,0 +1,5 @@ +#include "fixtures/D3D12TestFixture.h" + +TEST(D3D12Buffer, Placeholder) { + ASSERT_TRUE(true); +} diff --git a/engine/src/RHI/D3D12/test/test_command_allocator.cpp b/engine/src/RHI/D3D12/test/test_command_allocator.cpp new file mode 100644 index 00000000..c3d6b150 --- /dev/null +++ b/engine/src/RHI/D3D12/test/test_command_allocator.cpp @@ -0,0 +1,6 @@ +#include "fixtures/D3D12TestFixture.h" + +TEST(D3D12CommandAllocator, CreateAllocator_Success) { + auto* allocator = GetCommandAllocator(); + ASSERT_NE(allocator, nullptr); +} diff --git a/engine/src/RHI/D3D12/test/test_command_list.cpp b/engine/src/RHI/D3D12/test/test_command_list.cpp new file mode 100644 index 00000000..0e193945 --- /dev/null +++ b/engine/src/RHI/D3D12/test/test_command_list.cpp @@ -0,0 +1,6 @@ +#include "fixtures/D3D12TestFixture.h" + +TEST(D3D12CommandList, CreateCommandList_Success) { + auto* cmdList = GetCommandList(); + ASSERT_NE(cmdList, nullptr); +} diff --git a/engine/src/RHI/D3D12/test/test_command_queue.cpp b/engine/src/RHI/D3D12/test/test_command_queue.cpp new file mode 100644 index 00000000..e93bd61d --- /dev/null +++ b/engine/src/RHI/D3D12/test/test_command_queue.cpp @@ -0,0 +1,6 @@ +#include "fixtures/D3D12TestFixture.h" + +TEST(D3D12CommandQueue, CreateQueue_Success) { + auto* queue = GetCommandQueue(); + ASSERT_NE(queue, nullptr); +} diff --git a/engine/src/RHI/D3D12/test/test_descriptor_heap.cpp b/engine/src/RHI/D3D12/test/test_descriptor_heap.cpp new file mode 100644 index 00000000..e1df6350 --- /dev/null +++ b/engine/src/RHI/D3D12/test/test_descriptor_heap.cpp @@ -0,0 +1,5 @@ +#include "fixtures/D3D12TestFixture.h" + +TEST(D3D12DescriptorHeap, Placeholder) { + ASSERT_TRUE(true); +} diff --git a/engine/src/RHI/D3D12/test/test_device.cpp b/engine/src/RHI/D3D12/test/test_device.cpp new file mode 100644 index 00000000..a0d5e5f0 --- /dev/null +++ b/engine/src/RHI/D3D12/test/test_device.cpp @@ -0,0 +1,10 @@ +#include "fixtures/D3D12TestFixture.h" + +TEST(D3D12Device, CreateDevice_Success) { + auto* device = GetDevice(); + ASSERT_NE(device, nullptr); +} + +TEST(D3D12Device, GetAdapterInfo_NotEmpty) { + ASSERT_NE(GetDevice(), nullptr); +} diff --git a/engine/src/RHI/D3D12/test/test_fence.cpp b/engine/src/RHI/D3D12/test/test_fence.cpp new file mode 100644 index 00000000..786b9cb9 --- /dev/null +++ b/engine/src/RHI/D3D12/test/test_fence.cpp @@ -0,0 +1,6 @@ +#include "fixtures/D3D12TestFixture.h" + +TEST(D3D12Fence, CreateFence_Success) { + auto* device = GetDevice(); + ASSERT_NE(device, nullptr); +} diff --git a/engine/src/RHI/D3D12/test/test_pipeline_state.cpp b/engine/src/RHI/D3D12/test/test_pipeline_state.cpp new file mode 100644 index 00000000..9f5796d0 --- /dev/null +++ b/engine/src/RHI/D3D12/test/test_pipeline_state.cpp @@ -0,0 +1,5 @@ +#include "fixtures/D3D12TestFixture.h" + +TEST(D3D12PipelineState, Placeholder) { + ASSERT_TRUE(true); +} diff --git a/engine/src/RHI/D3D12/test/test_root_signature.cpp b/engine/src/RHI/D3D12/test/test_root_signature.cpp new file mode 100644 index 00000000..9e5d17f3 --- /dev/null +++ b/engine/src/RHI/D3D12/test/test_root_signature.cpp @@ -0,0 +1,5 @@ +#include "fixtures/D3D12TestFixture.h" + +TEST(D3D12RootSignature, Placeholder) { + ASSERT_TRUE(true); +} diff --git a/engine/src/RHI/D3D12/test/test_shader.cpp b/engine/src/RHI/D3D12/test/test_shader.cpp new file mode 100644 index 00000000..305498a2 --- /dev/null +++ b/engine/src/RHI/D3D12/test/test_shader.cpp @@ -0,0 +1,5 @@ +#include "fixtures/D3D12TestFixture.h" + +TEST(D3D12Shader, Placeholder) { + ASSERT_TRUE(true); +} diff --git a/engine/src/RHI/D3D12/test/test_texture.cpp b/engine/src/RHI/D3D12/test/test_texture.cpp new file mode 100644 index 00000000..7f164a11 --- /dev/null +++ b/engine/src/RHI/D3D12/test/test_texture.cpp @@ -0,0 +1,5 @@ +#include "fixtures/D3D12TestFixture.h" + +TEST(D3D12Texture, Placeholder) { + ASSERT_TRUE(true); +} diff --git a/engine/src/RHI/D3D12/test/test_views.cpp b/engine/src/RHI/D3D12/test/test_views.cpp new file mode 100644 index 00000000..b770f160 --- /dev/null +++ b/engine/src/RHI/D3D12/test/test_views.cpp @@ -0,0 +1,5 @@ +#include "fixtures/D3D12TestFixture.h" + +TEST(D3D12Views, Placeholder) { + ASSERT_TRUE(true); +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index ff6e7831..034a7219 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -39,6 +39,9 @@ add_subdirectory(threading) add_subdirectory(debug) add_subdirectory(D3D12) +# D3D12 Engine Tests (in engine source tree) +add_subdirectory(${CMAKE_SOURCE_DIR}/engine/src/RHI/D3D12/test ${CMAKE_BINARY_DIR}/D3D12_engine_tests) + # ============================================================ # Test Summary # ============================================================