From 295459067f034959ce28b50e6df8b9f30a8f7fa1 Mon Sep 17 00:00:00 2001 From: ssdfasd <2156608475@qq.com> Date: Wed, 25 Mar 2026 17:30:16 +0800 Subject: [PATCH] Fix RHI format conversion and add debug logging for D3D12 tests --- .../XCEngine/RHI/D3D12/D3D12Screenshot.h | 6 ++- engine/include/XCEngine/RHI/RHIScreenshot.h | 25 +++++++++++ .../src/RHI/D3D12/D3D12CommandAllocator.cpp | 4 ++ engine/src/RHI/D3D12/D3D12Device.cpp | 24 +++++++++-- engine/src/RHI/D3D12/D3D12Screenshot.cpp | 16 +++++++ engine/src/RHI/D3D12/D3D12Texture.cpp | 5 +++ engine/src/RHI/RHIScreenshot.cpp | 25 +++++++++++ tests/RHI/CMakeLists.txt | 1 + tests/RHI/unit/fixtures/RHITestFixture.cpp | 43 +++++++++++++++++++ tests/RHI/unit/fixtures/RHITestFixture.h | 2 + 10 files changed, 146 insertions(+), 5 deletions(-) create mode 100644 engine/include/XCEngine/RHI/RHIScreenshot.h create mode 100644 engine/src/RHI/RHIScreenshot.cpp diff --git a/engine/include/XCEngine/RHI/D3D12/D3D12Screenshot.h b/engine/include/XCEngine/RHI/D3D12/D3D12Screenshot.h index 0f8fb103..333f3d06 100644 --- a/engine/include/XCEngine/RHI/D3D12/D3D12Screenshot.h +++ b/engine/include/XCEngine/RHI/D3D12/D3D12Screenshot.h @@ -2,6 +2,7 @@ #include #include +#include "../RHIScreenshot.h" namespace XCEngine { namespace RHI { @@ -10,8 +11,11 @@ class D3D12Device; class D3D12CommandQueue; class D3D12Texture; -class D3D12Screenshot { +class D3D12Screenshot : public RHIScreenshot { public: + bool Capture(RHIDevice* device, RHISwapChain* swapChain, const char* filename) override; + void Shutdown() override {} + static bool Capture(ID3D12Device* device, ID3D12CommandQueue* commandQueue, ID3D12Resource* renderTarget, diff --git a/engine/include/XCEngine/RHI/RHIScreenshot.h b/engine/include/XCEngine/RHI/RHIScreenshot.h new file mode 100644 index 00000000..7eabf5ed --- /dev/null +++ b/engine/include/XCEngine/RHI/RHIScreenshot.h @@ -0,0 +1,25 @@ +#pragma once + +#include +#include + +namespace XCEngine { +namespace RHI { + +enum class RHIType : uint8_t; + +class RHIDevice; +class RHISwapChain; + +class RHIScreenshot { +public: + virtual ~RHIScreenshot() = default; + + virtual bool Capture(RHIDevice* device, RHISwapChain* swapChain, const char* filename) = 0; + virtual void Shutdown() = 0; + + static RHIScreenshot* Create(RHIType type); +}; + +} // namespace RHI +} // namespace XCEngine \ No newline at end of file diff --git a/engine/src/RHI/D3D12/D3D12CommandAllocator.cpp b/engine/src/RHI/D3D12/D3D12CommandAllocator.cpp index d8a1fcea..f1e21fec 100644 --- a/engine/src/RHI/D3D12/D3D12CommandAllocator.cpp +++ b/engine/src/RHI/D3D12/D3D12CommandAllocator.cpp @@ -21,6 +21,10 @@ bool D3D12CommandAllocator::Initialize(ID3D12Device* device, CommandQueueType ty if (FAILED(hResult)) { FILE* f = fopen("D:\\Xuanchi\\Main\\XCEngine\\debug_rhi.log", "a"); if (f) { fprintf(f, "[D3D12CommandAllocator] CreateCommandAllocator failed: hr=0x%08X\n", hResult); fclose(f); } + if (hResult == DXGI_ERROR_DEVICE_REMOVED) { + FILE* f2 = fopen("D:\\Xuanchi\\Main\\XCEngine\\debug_rhi.log", "a"); + if (f2) { fprintf(f2, "[D3D12CommandAllocator] Device removed reason: %d\n", device->GetDeviceRemovedReason()); fclose(f2); } + } } return SUCCEEDED(hResult); } diff --git a/engine/src/RHI/D3D12/D3D12Device.cpp b/engine/src/RHI/D3D12/D3D12Device.cpp index 000b1d43..a6a90e14 100644 --- a/engine/src/RHI/D3D12/D3D12Device.cpp +++ b/engine/src/RHI/D3D12/D3D12Device.cpp @@ -273,6 +273,12 @@ RHIBuffer* D3D12Device::CreateBuffer(const BufferDesc& desc) { } RHITexture* D3D12Device::CreateTexture(const TextureDesc& desc) { + OutputDebugStringA("[CreateTexture] Start\n"); + { + FILE* f = fopen("D:\\Xuanchi\\Main\\XCEngine\\debug_rhi.log", "a"); + if (f) { fprintf(f, "[CreateTexture] Start, m_device=%p\n", m_device.Get()); fclose(f); } + } + auto* texture = new D3D12Texture(); D3D12_RESOURCE_DESC d3d12Desc = {}; @@ -282,7 +288,7 @@ RHITexture* D3D12Device::CreateTexture(const TextureDesc& desc) { d3d12Desc.Height = desc.height; d3d12Desc.DepthOrArraySize = desc.depth > 0 ? desc.depth : 1; d3d12Desc.MipLevels = desc.mipLevels > 0 ? desc.mipLevels : 1; - d3d12Desc.Format = static_cast(desc.format); + d3d12Desc.Format = ToD3D12(static_cast(desc.format)); d3d12Desc.SampleDesc.Count = desc.sampleCount > 0 ? desc.sampleCount : 1; d3d12Desc.SampleDesc.Quality = desc.sampleQuality; d3d12Desc.Flags = static_cast(desc.flags); @@ -294,9 +300,19 @@ RHITexture* D3D12Device::CreateTexture(const TextureDesc& desc) { } d3d12Desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; + { + FILE* f = fopen("D:\\Xuanchi\\Main\\XCEngine\\debug_rhi.log", "a"); + if (f) { fprintf(f, "[CreateTexture] Calling Initialize, device=%p, format=%d\n", m_device.Get(), (int)d3d12Desc.Format); fclose(f); } + } if (texture->Initialize(m_device.Get(), d3d12Desc)) { + FILE* f = fopen("D:\\Xuanchi\\Main\\XCEngine\\debug_rhi.log", "a"); + if (f) { fprintf(f, "[CreateTexture] Initialize succeeded\n"); fclose(f); } return texture; } + { + FILE* f = fopen("D:\\Xuanchi\\Main\\XCEngine\\debug_rhi.log", "a"); + if (f) { fprintf(f, "[CreateTexture] Initialize FAILED\n"); fclose(f); } + } delete texture; return nullptr; } @@ -489,7 +505,7 @@ RHIResourceView* D3D12Device::CreateRenderTargetView(RHITexture* texture, const } D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {}; - rtvDesc.Format = static_cast(desc.format); + rtvDesc.Format = ToD3D12(static_cast(desc.format)); rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; { @@ -526,7 +542,7 @@ RHIResourceView* D3D12Device::CreateDepthStencilView(RHITexture* texture, const ID3D12Resource* resource = d3d12Texture->GetResource(); D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = {}; - dsvDesc.Format = static_cast(desc.format); + dsvDesc.Format = ToD3D12(static_cast(desc.format)); dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D; auto heap = std::make_unique(); @@ -549,7 +565,7 @@ RHIResourceView* D3D12Device::CreateShaderResourceView(RHITexture* texture, cons ID3D12Resource* resource = d3d12Texture->GetResource(); D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; - srvDesc.Format = static_cast(desc.format); + srvDesc.Format = ToD3D12(static_cast(desc.format)); srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; srvDesc.Texture2D.MipLevels = desc.mipLevel > 0 ? desc.mipLevel : 1; srvDesc.Texture2D.MostDetailedMip = 0; diff --git a/engine/src/RHI/D3D12/D3D12Screenshot.cpp b/engine/src/RHI/D3D12/D3D12Screenshot.cpp index 6adfae68..a94fd15e 100644 --- a/engine/src/RHI/D3D12/D3D12Screenshot.cpp +++ b/engine/src/RHI/D3D12/D3D12Screenshot.cpp @@ -2,6 +2,7 @@ #include "RHI/D3D12/D3D12Device.h" #include "RHI/D3D12/D3D12CommandQueue.h" #include "RHI/D3D12/D3D12Texture.h" +#include "RHI/D3D12/D3D12SwapChain.h" #include "Debug/Logger.h" #include #include @@ -219,5 +220,20 @@ bool D3D12Screenshot::CopyToReadbackAndSave(ID3D12Device* device, return true; } +bool D3D12Screenshot::Capture(RHIDevice* device, RHISwapChain* swapChain, const char* filename) { + auto* d3d12Device = static_cast(device); + auto* d3d12SwapChain = static_cast(swapChain); + RHITexture* tex = swapChain->GetCurrentBackBuffer(); + D3D12Texture* backBuffer = static_cast(tex); + return CopyToReadbackAndSave( + d3d12Device->GetDevice(), + d3d12SwapChain->GetNativeCommandQueue(), + backBuffer->GetResource(), + filename, + backBuffer->GetWidth(), + backBuffer->GetHeight() + ); +} + } // namespace RHI } // namespace XCEngine \ No newline at end of file diff --git a/engine/src/RHI/D3D12/D3D12Texture.cpp b/engine/src/RHI/D3D12/D3D12Texture.cpp index 7c5a7695..672ae274 100644 --- a/engine/src/RHI/D3D12/D3D12Texture.cpp +++ b/engine/src/RHI/D3D12/D3D12Texture.cpp @@ -11,6 +11,9 @@ D3D12Texture::~D3D12Texture() { } bool D3D12Texture::Initialize(ID3D12Device* device, const D3D12_RESOURCE_DESC& desc, D3D12_RESOURCE_STATES initialState) { + FILE* f = fopen("D:\\Xuanchi\\Main\\XCEngine\\debug_rhi.log", "a"); + if (f) { fprintf(f, "[D3D12Texture::Initialize] Start, device=%p\n", device); fclose(f); } + D3D12_HEAP_PROPERTIES heapProperties = {}; heapProperties.Type = D3D12_HEAP_TYPE_DEFAULT; heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; @@ -30,6 +33,8 @@ bool D3D12Texture::Initialize(ID3D12Device* device, const D3D12_RESOURCE_DESC& d ); if (FAILED(hResult)) { + FILE* f2 = fopen("D:\\Xuanchi\\Main\\XCEngine\\debug_rhi.log", "a"); + if (f2) { fprintf(f2, "[D3D12Texture::Initialize] CreateCommittedResource failed: hr=0x%08X\n", hResult); fclose(f2); } return false; } diff --git a/engine/src/RHI/RHIScreenshot.cpp b/engine/src/RHI/RHIScreenshot.cpp new file mode 100644 index 00000000..459a3cb5 --- /dev/null +++ b/engine/src/RHI/RHIScreenshot.cpp @@ -0,0 +1,25 @@ +#include "XCEngine/RHI/RHIScreenshot.h" +#include "XCEngine/RHI/RHIEnums.h" +#include "XCEngine/RHI/D3D12/D3D12Screenshot.h" +#ifdef XCENGINE_SUPPORT_OPENGL +#include "XCEngine/RHI/OpenGL/OpenGLScreenshot.h" +#endif + +namespace XCEngine { +namespace RHI { + +RHIScreenshot* RHIScreenshot::Create(RHIType type) { + switch (type) { + case RHIType::D3D12: + return new D3D12Screenshot(); +#ifdef XCENGINE_SUPPORT_OPENGL + case RHIType::OpenGL: + return new OpenGLScreenshot(); +#endif + default: + return nullptr; + } +} + +} // namespace RHI +} // namespace XCEngine \ No newline at end of file diff --git a/tests/RHI/CMakeLists.txt b/tests/RHI/CMakeLists.txt index f54eb676..9851fef2 100644 --- a/tests/RHI/CMakeLists.txt +++ b/tests/RHI/CMakeLists.txt @@ -8,3 +8,4 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) add_subdirectory(D3D12) add_subdirectory(OpenGL) add_subdirectory(unit) +add_subdirectory(integration) diff --git a/tests/RHI/unit/fixtures/RHITestFixture.cpp b/tests/RHI/unit/fixtures/RHITestFixture.cpp index a6b3982b..c1f1aeef 100644 --- a/tests/RHI/unit/fixtures/RHITestFixture.cpp +++ b/tests/RHI/unit/fixtures/RHITestFixture.cpp @@ -44,7 +44,50 @@ void RHITestFixture::SetUp() { ASSERT_TRUE(initResult); } +void RHITestFixture::WaitForGPU() { + if (mDevice == nullptr) { + return; + } + + if (GetParam() == RHIType::D3D12) { + auto* device = static_cast(mDevice); + + CommandQueueDesc queueDesc = {}; + queueDesc.queueType = static_cast(CommandQueueType::Direct); + queueDesc.priority = 0; + queueDesc.nodeMask = 0; + queueDesc.flags = 0; + auto* commandQueue = device->CreateCommandQueue(queueDesc); + if (commandQueue) { + FenceDesc fenceDesc = {}; + fenceDesc.initialValue = 0; + fenceDesc.flags = 0; + auto* fence = mDevice->CreateFence(fenceDesc); + if (fence) { + commandQueue->Signal(fence, 1); + fence->Wait(1); + + for (int i = 0; i < 100; i++) { + if (fence->GetCompletedValue() >= 1) { + break; + } + Sleep(10); + } + + fence->Shutdown(); + delete fence; + } + commandQueue->Shutdown(); + delete commandQueue; + } + + Sleep(100); + } +} + void RHITestFixture::TearDown() { + WaitForGPU(); + if (mDevice != nullptr) { mDevice->Shutdown(); delete mDevice; diff --git a/tests/RHI/unit/fixtures/RHITestFixture.h b/tests/RHI/unit/fixtures/RHITestFixture.h index 69f93885..ce42bb99 100644 --- a/tests/RHI/unit/fixtures/RHITestFixture.h +++ b/tests/RHI/unit/fixtures/RHITestFixture.h @@ -16,6 +16,7 @@ #include "XCEngine/RHI/RHISampler.h" #include "XCEngine/RHI/RHIDescriptorPool.h" #include "XCEngine/RHI/RHIPipelineLayout.h" +#include "XCEngine/RHI/RHIEnums.h" namespace XCEngine { namespace RHI { @@ -27,6 +28,7 @@ protected: static void SetUpTestSuite(); static void TearDownTestSuite(); + void WaitForGPU(); RHIDevice* GetDevice() { return mDevice; } RHIType GetBackendType() const { return GetParam(); }