feat: 实现D3D12CommandQueue和D3D12CommandAllocator
- 添加D3D12CommandQueue类封装ID3D12CommandQueue - 添加D3D12CommandAllocator类封装ID3D12CommandAllocator - 在D3D12Enum.h中添加CommandQueueType转换函数 - 在CMake中添加Res文件夹自动拷贝到输出目录 - 更新测试项目使用新的封装类
This commit is contained in:
@@ -85,7 +85,11 @@ add_library(XCEngine STATIC
|
|||||||
include/XCEngine/RHI/Enums.h
|
include/XCEngine/RHI/Enums.h
|
||||||
include/XCEngine/RHI/D3D12/D3D12Enum.h
|
include/XCEngine/RHI/D3D12/D3D12Enum.h
|
||||||
include/XCEngine/RHI/D3D12/D3D12Device.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/D3D12Device.cpp
|
||||||
|
src/RHI/D3D12CommandQueue.cpp
|
||||||
|
src/RHI/D3D12CommandAllocator.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
target_include_directories(XCEngine PUBLIC
|
target_include_directories(XCEngine PUBLIC
|
||||||
|
|||||||
32
engine/include/XCEngine/RHI/D3D12/D3D12CommandAllocator.h
Normal file
32
engine/include/XCEngine/RHI/D3D12/D3D12CommandAllocator.h
Normal 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
|
||||||
40
engine/include/XCEngine/RHI/D3D12/D3D12CommandQueue.h
Normal file
40
engine/include/XCEngine/RHI/D3D12/D3D12CommandQueue.h
Normal 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
|
||||||
@@ -273,5 +273,14 @@ inline D3D12_STENCIL_OP ToD3D12(StencilOp op) {
|
|||||||
return D3D12_STENCIL_OP_KEEP;
|
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 RHI
|
||||||
} // namespace XCEngine
|
} // namespace XCEngine
|
||||||
|
|||||||
36
engine/src/RHI/D3D12CommandAllocator.cpp
Normal file
36
engine/src/RHI/D3D12CommandAllocator.cpp
Normal 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
|
||||||
65
engine/src/RHI/D3D12CommandQueue.cpp
Normal file
65
engine/src/RHI/D3D12CommandQueue.cpp
Normal 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
|
||||||
@@ -26,3 +26,10 @@ target_link_libraries(D3D12 PRIVATE
|
|||||||
winmm
|
winmm
|
||||||
XCEngine
|
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
|
||||||
|
$<TARGET_FILE_DIR:D3D12>/Res
|
||||||
|
)
|
||||||
|
|||||||
@@ -14,6 +14,8 @@
|
|||||||
#include "XCEngine/RHI/Enums.h"
|
#include "XCEngine/RHI/Enums.h"
|
||||||
#include "XCEngine/RHI/D3D12/D3D12Enum.h"
|
#include "XCEngine/RHI/D3D12/D3D12Enum.h"
|
||||||
#include "XCEngine/RHI/D3D12/D3D12Device.h"
|
#include "XCEngine/RHI/D3D12/D3D12Device.h"
|
||||||
|
#include "XCEngine/RHI/D3D12/D3D12CommandQueue.h"
|
||||||
|
#include "XCEngine/RHI/D3D12/D3D12CommandAllocator.h"
|
||||||
|
|
||||||
using namespace XCEngine::RHI;
|
using namespace XCEngine::RHI;
|
||||||
|
|
||||||
@@ -26,7 +28,7 @@ using namespace XCEngine::RHI;
|
|||||||
// D3D12 核心全局对象 (最小渲染所需)
|
// D3D12 核心全局对象 (最小渲染所需)
|
||||||
//=================================================================================
|
//=================================================================================
|
||||||
XCEngine::RHI::D3D12Device gDevice;
|
XCEngine::RHI::D3D12Device gDevice;
|
||||||
ID3D12CommandQueue* gCommandQueue = nullptr;
|
XCEngine::RHI::D3D12CommandQueue gCommandQueue;
|
||||||
IDXGISwapChain3* gSwapChain = nullptr;
|
IDXGISwapChain3* gSwapChain = nullptr;
|
||||||
|
|
||||||
// 渲染目标 (SwapChain的后台Buffer)
|
// 渲染目标 (SwapChain的后台Buffer)
|
||||||
@@ -41,7 +43,7 @@ UINT gRTVDescriptorSize = 0;
|
|||||||
UINT gDSVDescriptorSize = 0;
|
UINT gDSVDescriptorSize = 0;
|
||||||
|
|
||||||
// 命令相关
|
// 命令相关
|
||||||
ID3D12CommandAllocator* gCommandAllocator = nullptr;
|
XCEngine::RHI::D3D12CommandAllocator gCommandAllocator;
|
||||||
ID3D12GraphicsCommandList* gCommandList = nullptr;
|
ID3D12GraphicsCommandList* gCommandList = nullptr;
|
||||||
|
|
||||||
// 同步对象
|
// 同步对象
|
||||||
@@ -567,11 +569,10 @@ bool InitD3D12(HWND inHWND, int inWidth, int inHeight) {
|
|||||||
ID3D12Device* device = gDevice.GetDevice();
|
ID3D12Device* device = gDevice.GetDevice();
|
||||||
IDXGIFactory4* dxgiFactory = gDevice.GetFactory();
|
IDXGIFactory4* dxgiFactory = gDevice.GetFactory();
|
||||||
|
|
||||||
D3D12_COMMAND_QUEUE_DESC d3d12CommandQueueDesc = {};
|
if (!gCommandQueue.Initialize(device, XCEngine::RHI::CommandQueueType::Direct)) {
|
||||||
HRESULT hResult = device->CreateCommandQueue(&d3d12CommandQueueDesc, IID_PPV_ARGS(&gCommandQueue));
|
|
||||||
if (FAILED(hResult)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
DXGI_SWAP_CHAIN_DESC swapChainDesc = {};
|
DXGI_SWAP_CHAIN_DESC swapChainDesc = {};
|
||||||
swapChainDesc.BufferCount = 2;
|
swapChainDesc.BufferCount = 2;
|
||||||
swapChainDesc.BufferDesc = {};
|
swapChainDesc.BufferDesc = {};
|
||||||
@@ -585,7 +586,7 @@ bool InitD3D12(HWND inHWND, int inWidth, int inHeight) {
|
|||||||
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
||||||
|
|
||||||
IDXGISwapChain* swapChain = nullptr;
|
IDXGISwapChain* swapChain = nullptr;
|
||||||
dxgiFactory->CreateSwapChain(gCommandQueue, &swapChainDesc, &swapChain);
|
dxgiFactory->CreateSwapChain(gCommandQueue.GetCommandQueue(), &swapChainDesc, &swapChain);
|
||||||
gSwapChain = static_cast<IDXGISwapChain3*>(swapChain);
|
gSwapChain = static_cast<IDXGISwapChain3*>(swapChain);
|
||||||
|
|
||||||
D3D12_HEAP_PROPERTIES d3dHeapProperties = {};
|
D3D12_HEAP_PROPERTIES d3dHeapProperties = {};
|
||||||
@@ -642,8 +643,8 @@ bool InitD3D12(HWND inHWND, int inWidth, int inHeight) {
|
|||||||
|
|
||||||
device->CreateDepthStencilView(gDSRT, &d3dDSViewDesc, gSwapChainDSVHeap->GetCPUDescriptorHandleForHeapStart());
|
device->CreateDepthStencilView(gDSRT, &d3dDSViewDesc, gSwapChainDSVHeap->GetCPUDescriptorHandleForHeapStart());
|
||||||
|
|
||||||
device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&gCommandAllocator));
|
gCommandAllocator.Initialize(device, XCEngine::RHI::CommandQueueType::Direct);
|
||||||
device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, gCommandAllocator, nullptr, IID_PPV_ARGS(&gCommandList));
|
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));
|
device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&gFence));
|
||||||
gFenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
|
gFenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
|
||||||
@@ -655,7 +656,7 @@ bool InitD3D12(HWND inHWND, int inWidth, int inHeight) {
|
|||||||
// 命令相关辅助函数
|
// 命令相关辅助函数
|
||||||
//=================================================================================
|
//=================================================================================
|
||||||
ID3D12CommandAllocator* GetCommandAllocator() {
|
ID3D12CommandAllocator* GetCommandAllocator() {
|
||||||
return gCommandAllocator;
|
return gCommandAllocator.GetCommandAllocator();
|
||||||
}
|
}
|
||||||
|
|
||||||
ID3D12GraphicsCommandList* GetCommandList() {
|
ID3D12GraphicsCommandList* GetCommandList() {
|
||||||
@@ -676,9 +677,9 @@ void WaitForCompletionOfCommandList() {
|
|||||||
void EndCommandList() {
|
void EndCommandList() {
|
||||||
gCommandList->Close();
|
gCommandList->Close();
|
||||||
ID3D12CommandList* ppCommandLists[] = { gCommandList };
|
ID3D12CommandList* ppCommandLists[] = { gCommandList };
|
||||||
gCommandQueue->ExecuteCommandLists(1, ppCommandLists);
|
gCommandQueue.ExecuteCommandLists(1, ppCommandLists);
|
||||||
gFenceValue += 1;
|
gFenceValue += 1;
|
||||||
gCommandQueue->Signal(gFence, gFenceValue);
|
gCommandQueue.Signal(gFence, gFenceValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
//=================================================================================
|
//=================================================================================
|
||||||
|
|||||||
Reference in New Issue
Block a user