From 8fb11dc65013f2c3f1afd8879524995c4eacfe44 Mon Sep 17 00:00:00 2001 From: ssdfasd <2156608475@qq.com> Date: Sun, 15 Mar 2026 03:15:12 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=9E=E7=8E=B0D3D12CommandQueue?= =?UTF-8?q?=E5=92=8CD3D12CommandAllocator?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加D3D12CommandQueue类封装ID3D12CommandQueue - 添加D3D12CommandAllocator类封装ID3D12CommandAllocator - 在D3D12Enum.h中添加CommandQueueType转换函数 - 在CMake中添加Res文件夹自动拷贝到输出目录 - 更新测试项目使用新的封装类 --- engine/CMakeLists.txt | 4 ++ .../RHI/D3D12/D3D12CommandAllocator.h | 32 +++++++++ .../XCEngine/RHI/D3D12/D3D12CommandQueue.h | 40 ++++++++++++ engine/include/XCEngine/RHI/D3D12/D3D12Enum.h | 9 +++ engine/src/RHI/D3D12CommandAllocator.cpp | 36 ++++++++++ engine/src/RHI/D3D12CommandQueue.cpp | 65 +++++++++++++++++++ tests/D3D12/CMakeLists.txt | 7 ++ tests/D3D12/main.cpp | 23 +++---- 8 files changed, 205 insertions(+), 11 deletions(-) create mode 100644 engine/include/XCEngine/RHI/D3D12/D3D12CommandAllocator.h create mode 100644 engine/include/XCEngine/RHI/D3D12/D3D12CommandQueue.h create mode 100644 engine/src/RHI/D3D12CommandAllocator.cpp create mode 100644 engine/src/RHI/D3D12CommandQueue.cpp diff --git a/engine/CMakeLists.txt b/engine/CMakeLists.txt index 5a98ee0b..d8f9ec3e 100644 --- a/engine/CMakeLists.txt +++ b/engine/CMakeLists.txt @@ -85,7 +85,11 @@ add_library(XCEngine STATIC include/XCEngine/RHI/Enums.h include/XCEngine/RHI/D3D12/D3D12Enum.h include/XCEngine/RHI/D3D12/D3D12Device.h + include/XCEngine/RHI/D3D12/D3D12CommandQueue.h + include/XCEngine/RHI/D3D12/D3D12CommandAllocator.h src/RHI/D3D12Device.cpp + src/RHI/D3D12CommandQueue.cpp + src/RHI/D3D12CommandAllocator.cpp ) target_include_directories(XCEngine PUBLIC diff --git a/engine/include/XCEngine/RHI/D3D12/D3D12CommandAllocator.h b/engine/include/XCEngine/RHI/D3D12/D3D12CommandAllocator.h new file mode 100644 index 00000000..c5dc4d17 --- /dev/null +++ b/engine/include/XCEngine/RHI/D3D12/D3D12CommandAllocator.h @@ -0,0 +1,32 @@ +#pragma once + +#include +#include + +#include "../Enums.h" + +using Microsoft::WRL::ComPtr; + +namespace XCEngine { +namespace RHI { + +class D3D12CommandAllocator { +public: + D3D12CommandAllocator(); + ~D3D12CommandAllocator(); + + bool Initialize(ID3D12Device* device, CommandQueueType type = CommandQueueType::Direct); + void Shutdown(); + + void Reset(); + bool IsReady() const; + + ID3D12CommandAllocator* GetCommandAllocator() const { return m_commandAllocator.Get(); } + +private: + ComPtr m_commandAllocator; + CommandQueueType m_type; +}; + +} // namespace RHI +} // namespace XCEngine diff --git a/engine/include/XCEngine/RHI/D3D12/D3D12CommandQueue.h b/engine/include/XCEngine/RHI/D3D12/D3D12CommandQueue.h new file mode 100644 index 00000000..1390eecd --- /dev/null +++ b/engine/include/XCEngine/RHI/D3D12/D3D12CommandQueue.h @@ -0,0 +1,40 @@ +#pragma once + +#include +#include + +#include "../Enums.h" +#include "D3D12Enum.h" + +using Microsoft::WRL::ComPtr; + +namespace XCEngine { +namespace RHI { + +class D3D12CommandQueue { +public: + D3D12CommandQueue(); + ~D3D12CommandQueue(); + + bool Initialize(ID3D12Device* device, CommandQueueType type = CommandQueueType::Direct); + void Shutdown(); + + void ExecuteCommandLists(uint32_t count, ID3D12CommandList** lists); + void Signal(ID3D12Fence* fence, uint64_t value); + void Wait(ID3D12Fence* fence, uint64_t value); + uint64_t GetCompletedValue(ID3D12Fence* fence); + void WaitForIdle(); + + CommandQueueType GetType() const { return m_type; } + uint64_t GetTimestampFrequency() const { return m_timestampFrequency; } + + ID3D12CommandQueue* GetCommandQueue() const { return m_commandQueue.Get(); } + +private: + ComPtr m_commandQueue; + CommandQueueType m_type; + uint64_t m_timestampFrequency; +}; + +} // namespace RHI +} // namespace XCEngine diff --git a/engine/include/XCEngine/RHI/D3D12/D3D12Enum.h b/engine/include/XCEngine/RHI/D3D12/D3D12Enum.h index 4deee15d..f0dd8b03 100644 --- a/engine/include/XCEngine/RHI/D3D12/D3D12Enum.h +++ b/engine/include/XCEngine/RHI/D3D12/D3D12Enum.h @@ -273,5 +273,14 @@ inline D3D12_STENCIL_OP ToD3D12(StencilOp op) { return D3D12_STENCIL_OP_KEEP; } +inline D3D12_COMMAND_LIST_TYPE ToD3D12(CommandQueueType type) { + switch (type) { + case CommandQueueType::Direct: return D3D12_COMMAND_LIST_TYPE_DIRECT; + case CommandQueueType::Compute: return D3D12_COMMAND_LIST_TYPE_COMPUTE; + case CommandQueueType::Copy: return D3D12_COMMAND_LIST_TYPE_COPY; + } + return D3D12_COMMAND_LIST_TYPE_DIRECT; +} + } // namespace RHI } // namespace XCEngine diff --git a/engine/src/RHI/D3D12CommandAllocator.cpp b/engine/src/RHI/D3D12CommandAllocator.cpp new file mode 100644 index 00000000..3de91348 --- /dev/null +++ b/engine/src/RHI/D3D12CommandAllocator.cpp @@ -0,0 +1,36 @@ +#include "XCEngine/RHI/D3D12/D3D12CommandAllocator.h" +#include "XCEngine/RHI/D3D12/D3D12Enum.h" + +namespace XCEngine { +namespace RHI { + +D3D12CommandAllocator::D3D12CommandAllocator() + : m_type(CommandQueueType::Direct) { +} + +D3D12CommandAllocator::~D3D12CommandAllocator() { + Shutdown(); +} + +bool D3D12CommandAllocator::Initialize(ID3D12Device* device, CommandQueueType type) { + m_type = type; + HRESULT hResult = device->CreateCommandAllocator( + ToD3D12(type), + IID_PPV_ARGS(&m_commandAllocator)); + return SUCCEEDED(hResult); +} + +void D3D12CommandAllocator::Shutdown() { + m_commandAllocator.Reset(); +} + +void D3D12CommandAllocator::Reset() { + m_commandAllocator->Reset(); +} + +bool D3D12CommandAllocator::IsReady() const { + return m_commandAllocator != nullptr; +} + +} // namespace RHI +} // namespace XCEngine diff --git a/engine/src/RHI/D3D12CommandQueue.cpp b/engine/src/RHI/D3D12CommandQueue.cpp new file mode 100644 index 00000000..3521a4e5 --- /dev/null +++ b/engine/src/RHI/D3D12CommandQueue.cpp @@ -0,0 +1,65 @@ +#include "XCEngine/RHI/D3D12/D3D12CommandQueue.h" + +namespace XCEngine { +namespace RHI { + +D3D12CommandQueue::D3D12CommandQueue() + : m_timestampFrequency(0) + , m_type(CommandQueueType::Direct) { +} + +D3D12CommandQueue::~D3D12CommandQueue() { + Shutdown(); +} + +bool D3D12CommandQueue::Initialize(ID3D12Device* device, CommandQueueType type) { + D3D12_COMMAND_QUEUE_DESC queueDesc = {}; + queueDesc.Type = ToD3D12(type); + queueDesc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL; + queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + queueDesc.NodeMask = 0; + + HRESULT hResult = device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&m_commandQueue)); + if (FAILED(hResult)) { + return false; + } + + m_type = type; + m_commandQueue->GetTimestampFrequency(&m_timestampFrequency); + return true; +} + +void D3D12CommandQueue::Shutdown() { + m_commandQueue.Reset(); +} + +void D3D12CommandQueue::ExecuteCommandLists(uint32_t count, ID3D12CommandList** lists) { + m_commandQueue->ExecuteCommandLists(count, lists); +} + +void D3D12CommandQueue::Signal(ID3D12Fence* fence, uint64_t value) { + m_commandQueue->Signal(fence, value); +} + +void D3D12CommandQueue::Wait(ID3D12Fence* fence, uint64_t value) { + m_commandQueue->Wait(fence, value); +} + +uint64_t D3D12CommandQueue::GetCompletedValue(ID3D12Fence* fence) { + if (fence) { + return fence->GetCompletedValue(); + } + return 0; +} + +void D3D12CommandQueue::WaitForIdle() { + ID3D12Fence* fence = nullptr; + HRESULT hResult = m_commandQueue->GetDevice(IID_PPV_ARGS(&fence)); + if (SUCCEEDED(hResult)) { + m_commandQueue->Wait(fence, UINT64_MAX); + fence->Release(); + } +} + +} // namespace RHI +} // namespace XCEngine diff --git a/tests/D3D12/CMakeLists.txt b/tests/D3D12/CMakeLists.txt index 7734da27..4685d300 100644 --- a/tests/D3D12/CMakeLists.txt +++ b/tests/D3D12/CMakeLists.txt @@ -26,3 +26,10 @@ target_link_libraries(D3D12 PRIVATE winmm XCEngine ) + +# Copy Res folder to output directory after build +add_custom_command(TARGET D3D12 POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory + ${CMAKE_SOURCE_DIR}/tests/D3D12/Res + $/Res +) diff --git a/tests/D3D12/main.cpp b/tests/D3D12/main.cpp index dbef2313..248c08a0 100644 --- a/tests/D3D12/main.cpp +++ b/tests/D3D12/main.cpp @@ -14,6 +14,8 @@ #include "XCEngine/RHI/Enums.h" #include "XCEngine/RHI/D3D12/D3D12Enum.h" #include "XCEngine/RHI/D3D12/D3D12Device.h" +#include "XCEngine/RHI/D3D12/D3D12CommandQueue.h" +#include "XCEngine/RHI/D3D12/D3D12CommandAllocator.h" using namespace XCEngine::RHI; @@ -26,7 +28,7 @@ using namespace XCEngine::RHI; // D3D12 核心全局对象 (最小渲染所需) //================================================================================= XCEngine::RHI::D3D12Device gDevice; -ID3D12CommandQueue* gCommandQueue = nullptr; +XCEngine::RHI::D3D12CommandQueue gCommandQueue; IDXGISwapChain3* gSwapChain = nullptr; // 渲染目标 (SwapChain的后台Buffer) @@ -41,7 +43,7 @@ UINT gRTVDescriptorSize = 0; UINT gDSVDescriptorSize = 0; // 命令相关 -ID3D12CommandAllocator* gCommandAllocator = nullptr; +XCEngine::RHI::D3D12CommandAllocator gCommandAllocator; ID3D12GraphicsCommandList* gCommandList = nullptr; // 同步对象 @@ -567,11 +569,10 @@ bool InitD3D12(HWND inHWND, int inWidth, int inHeight) { ID3D12Device* device = gDevice.GetDevice(); IDXGIFactory4* dxgiFactory = gDevice.GetFactory(); - D3D12_COMMAND_QUEUE_DESC d3d12CommandQueueDesc = {}; - HRESULT hResult = device->CreateCommandQueue(&d3d12CommandQueueDesc, IID_PPV_ARGS(&gCommandQueue)); - if (FAILED(hResult)) { + if (!gCommandQueue.Initialize(device, XCEngine::RHI::CommandQueueType::Direct)) { return false; } + DXGI_SWAP_CHAIN_DESC swapChainDesc = {}; swapChainDesc.BufferCount = 2; swapChainDesc.BufferDesc = {}; @@ -585,7 +586,7 @@ bool InitD3D12(HWND inHWND, int inWidth, int inHeight) { swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; IDXGISwapChain* swapChain = nullptr; - dxgiFactory->CreateSwapChain(gCommandQueue, &swapChainDesc, &swapChain); + dxgiFactory->CreateSwapChain(gCommandQueue.GetCommandQueue(), &swapChainDesc, &swapChain); gSwapChain = static_cast(swapChain); D3D12_HEAP_PROPERTIES d3dHeapProperties = {}; @@ -642,8 +643,8 @@ bool InitD3D12(HWND inHWND, int inWidth, int inHeight) { device->CreateDepthStencilView(gDSRT, &d3dDSViewDesc, gSwapChainDSVHeap->GetCPUDescriptorHandleForHeapStart()); - device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&gCommandAllocator)); - device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, gCommandAllocator, nullptr, IID_PPV_ARGS(&gCommandList)); + gCommandAllocator.Initialize(device, XCEngine::RHI::CommandQueueType::Direct); + device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, gCommandAllocator.GetCommandAllocator(), nullptr, IID_PPV_ARGS(&gCommandList)); device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&gFence)); gFenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr); @@ -655,7 +656,7 @@ bool InitD3D12(HWND inHWND, int inWidth, int inHeight) { // 命令相关辅助函数 //================================================================================= ID3D12CommandAllocator* GetCommandAllocator() { - return gCommandAllocator; + return gCommandAllocator.GetCommandAllocator(); } ID3D12GraphicsCommandList* GetCommandList() { @@ -676,9 +677,9 @@ void WaitForCompletionOfCommandList() { void EndCommandList() { gCommandList->Close(); ID3D12CommandList* ppCommandLists[] = { gCommandList }; - gCommandQueue->ExecuteCommandLists(1, ppCommandLists); + gCommandQueue.ExecuteCommandLists(1, ppCommandLists); gFenceValue += 1; - gCommandQueue->Signal(gFence, gFenceValue); + gCommandQueue.Signal(gFence, gFenceValue); } //=================================================================================