feat: 实现D3D12CommandQueue和D3D12CommandAllocator

- 添加D3D12CommandQueue类封装ID3D12CommandQueue
- 添加D3D12CommandAllocator类封装ID3D12CommandAllocator
- 在D3D12Enum.h中添加CommandQueueType转换函数
- 在CMake中添加Res文件夹自动拷贝到输出目录
- 更新测试项目使用新的封装类
This commit is contained in:
2026-03-15 03:15:12 +08:00
parent cba4f9c838
commit 8fb11dc650
8 changed files with 205 additions and 11 deletions

View File

@@ -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

View File

@@ -0,0 +1,32 @@
#pragma once
#include <d3d12.h>
#include <wrl/client.h>
#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<ID3D12CommandAllocator> m_commandAllocator;
CommandQueueType m_type;
};
} // namespace RHI
} // namespace XCEngine

View File

@@ -0,0 +1,40 @@
#pragma once
#include <d3d12.h>
#include <wrl/client.h>
#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<ID3D12CommandQueue> m_commandQueue;
CommandQueueType m_type;
uint64_t m_timestampFrequency;
};
} // namespace RHI
} // namespace XCEngine

View File

@@ -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

View File

@@ -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

View File

@@ -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