RHI: Add DescriptorSet abstraction for D3D12 and OpenGL backends
- Add RHIDescriptorSet base class with Update/UpdateSampler/GetNativeHandle - Add RHIDescriptorPool with AllocateSet/FreeSet methods - Add SetGraphicsDescriptorSets/SetComputeDescriptorSets to RHICommandList - Implement D3D12DescriptorSet using descriptor heap allocation - Implement OpenGLDescriptorSet using TextureUnitAllocator - Add CreateDescriptorPool/CreateDescriptorSet factory methods to RHIDevice - Fix unit test SetVertexBuffer -> SetVertexBuffers API - Add SetVertexBuffer convenience method for D3D12 backward compatibility - Update CMakeLists.txt with new source files
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
#include "XCEngine/RHI/D3D12/D3D12PipelineLayout.h"
|
||||
#include "XCEngine/RHI/D3D12/D3D12RenderPass.h"
|
||||
#include "XCEngine/RHI/D3D12/D3D12Framebuffer.h"
|
||||
#include "XCEngine/RHI/D3D12/D3D12DescriptorSet.h"
|
||||
|
||||
namespace XCEngine {
|
||||
namespace RHI {
|
||||
@@ -214,6 +215,56 @@ void D3D12CommandList::SetPipelineState(ID3D12PipelineState* pso) {
|
||||
SetPipelineStateInternal(pso);
|
||||
}
|
||||
|
||||
void D3D12CommandList::SetGraphicsDescriptorSets(
|
||||
uint32_t firstSet,
|
||||
uint32_t count,
|
||||
RHIDescriptorSet** descriptorSets,
|
||||
RHIPipelineLayout* pipelineLayout) {
|
||||
if (pipelineLayout == nullptr || descriptorSets == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
D3D12PipelineLayout* d3d12Layout = static_cast<D3D12PipelineLayout*>(pipelineLayout);
|
||||
SetPipelineLayout(d3d12Layout);
|
||||
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
if (descriptorSets[i] == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
D3D12DescriptorSet* d3d12Set = static_cast<D3D12DescriptorSet*>(descriptorSets[i]);
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle = d3d12Set->GetGPUHandle();
|
||||
|
||||
uint32_t rootIndex = firstSet + i;
|
||||
SetGraphicsRootDescriptorTable(rootIndex, gpuHandle);
|
||||
}
|
||||
}
|
||||
|
||||
void D3D12CommandList::SetComputeDescriptorSets(
|
||||
uint32_t firstSet,
|
||||
uint32_t count,
|
||||
RHIDescriptorSet** descriptorSets,
|
||||
RHIPipelineLayout* pipelineLayout) {
|
||||
if (pipelineLayout == nullptr || descriptorSets == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
D3D12PipelineLayout* d3d12Layout = static_cast<D3D12PipelineLayout*>(pipelineLayout);
|
||||
SetPipelineLayout(d3d12Layout);
|
||||
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
if (descriptorSets[i] == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
D3D12DescriptorSet* d3d12Set = static_cast<D3D12DescriptorSet*>(descriptorSets[i]);
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle = d3d12Set->GetGPUHandle();
|
||||
|
||||
uint32_t rootIndex = firstSet + i;
|
||||
m_commandList->SetComputeRootDescriptorTable(rootIndex, gpuHandle);
|
||||
}
|
||||
}
|
||||
|
||||
void D3D12CommandList::TransitionBarrierInternal(ID3D12Resource* resource, ResourceStates stateBefore, ResourceStates stateAfter, uint32_t subresource) {
|
||||
D3D12_RESOURCE_BARRIER barrier = {};
|
||||
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
@@ -434,6 +485,14 @@ void D3D12CommandList::SetVertexBuffersInternal(uint32_t startSlot, uint32_t cou
|
||||
m_commandList->IASetVertexBuffers(startSlot, count, views);
|
||||
}
|
||||
|
||||
void D3D12CommandList::SetVertexBuffer(uint32_t slot, ID3D12Resource* resource, uint64_t offset, uint32_t stride) {
|
||||
D3D12_VERTEX_BUFFER_VIEW view = {};
|
||||
view.BufferLocation = resource->GetGPUVirtualAddress() + offset;
|
||||
view.SizeInBytes = static_cast<UINT>(resource->GetDesc().Width) - static_cast<UINT>(offset);
|
||||
view.StrideInBytes = stride;
|
||||
SetVertexBuffersInternal(slot, 1, &view);
|
||||
}
|
||||
|
||||
void D3D12CommandList::SetIndexBuffer(RHIResourceView* buffer, uint64_t offset) {
|
||||
if (!buffer || !buffer->IsValid()) return;
|
||||
D3D12ResourceView* view = static_cast<D3D12ResourceView*>(buffer);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "XCEngine/RHI/D3D12/D3D12DescriptorHeap.h"
|
||||
#include "XCEngine/RHI/D3D12/D3D12DescriptorSet.h"
|
||||
|
||||
namespace XCEngine {
|
||||
namespace RHI {
|
||||
@@ -88,5 +89,41 @@ D3D12_DESCRIPTOR_HEAP_DESC D3D12DescriptorHeap::CreateDesc(DescriptorHeapType ty
|
||||
return desc;
|
||||
}
|
||||
|
||||
RHIDescriptorSet* D3D12DescriptorHeap::AllocateSet(const DescriptorSetLayoutDesc& layout) {
|
||||
uint32_t requiredDescriptors = 0;
|
||||
for (uint32_t i = 0; i < layout.bindingCount; ++i) {
|
||||
requiredDescriptors += layout.bindings[i].count;
|
||||
}
|
||||
|
||||
if (m_allocatedSets.size() >= m_numDescriptors) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
D3D12DescriptorSet* newSet = new D3D12DescriptorSet();
|
||||
uint32_t offset = static_cast<uint32_t>(m_allocatedSets.size());
|
||||
|
||||
if (!newSet->Initialize(this, offset, requiredDescriptors, layout)) {
|
||||
delete newSet;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
m_allocatedSets.push_back(newSet);
|
||||
return newSet;
|
||||
}
|
||||
|
||||
void D3D12DescriptorHeap::FreeSet(RHIDescriptorSet* set) {
|
||||
if (set == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto it = m_allocatedSets.begin(); it != m_allocatedSets.end(); ++it) {
|
||||
if (*it == set) {
|
||||
m_allocatedSets.erase(it);
|
||||
delete set;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace RHI
|
||||
} // namespace XCEngine
|
||||
|
||||
69
engine/src/RHI/D3D12/D3D12DescriptorSet.cpp
Normal file
69
engine/src/RHI/D3D12/D3D12DescriptorSet.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
#include "XCEngine/RHI/D3D12/D3D12DescriptorSet.h"
|
||||
#include "XCEngine/RHI/D3D12/D3D12DescriptorHeap.h"
|
||||
|
||||
namespace XCEngine {
|
||||
namespace RHI {
|
||||
|
||||
D3D12DescriptorSet::D3D12DescriptorSet()
|
||||
: m_heap(nullptr)
|
||||
, m_offset(0)
|
||||
, m_count(0)
|
||||
, m_bindingCount(0)
|
||||
, m_bindings(nullptr) {
|
||||
}
|
||||
|
||||
D3D12DescriptorSet::~D3D12DescriptorSet() {
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
bool D3D12DescriptorSet::Initialize(D3D12DescriptorHeap* heap, uint32_t offset, uint32_t count, const DescriptorSetLayoutDesc& layout) {
|
||||
m_heap = heap;
|
||||
m_offset = offset;
|
||||
m_count = count;
|
||||
m_bindingCount = layout.bindingCount;
|
||||
|
||||
if (layout.bindingCount > 0 && layout.bindings != nullptr) {
|
||||
m_bindings = new DescriptorSetLayoutBinding[layout.bindingCount];
|
||||
for (uint32_t i = 0; i < layout.bindingCount; ++i) {
|
||||
m_bindings[i] = layout.bindings[i];
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void D3D12DescriptorSet::Shutdown() {
|
||||
m_heap = nullptr;
|
||||
m_offset = 0;
|
||||
m_count = 0;
|
||||
m_bindingCount = 0;
|
||||
if (m_bindings != nullptr) {
|
||||
delete[] m_bindings;
|
||||
m_bindings = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void D3D12DescriptorSet::Update(uint32_t offset, RHIResourceView* view) {
|
||||
(void)offset;
|
||||
(void)view;
|
||||
}
|
||||
|
||||
void D3D12DescriptorSet::UpdateSampler(uint32_t offset, RHISampler* sampler) {
|
||||
(void)offset;
|
||||
(void)sampler;
|
||||
}
|
||||
|
||||
void* D3D12DescriptorSet::GetNativeHandle() {
|
||||
return this;
|
||||
}
|
||||
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE D3D12DescriptorSet::GetGPUHandle(uint32_t index) const {
|
||||
if (m_heap == nullptr) {
|
||||
return D3D12_GPU_DESCRIPTOR_HANDLE{0};
|
||||
}
|
||||
GPUDescriptorHandle handle = m_heap->GetGPUDescriptorHandle(m_offset + index);
|
||||
return D3D12_GPU_DESCRIPTOR_HANDLE{ handle.ptr };
|
||||
}
|
||||
|
||||
} // namespace RHI
|
||||
} // namespace XCEngine
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "XCEngine/RHI/D3D12/D3D12CommandAllocator.h"
|
||||
#include "XCEngine/RHI/D3D12/D3D12Fence.h"
|
||||
#include "XCEngine/RHI/D3D12/D3D12DescriptorHeap.h"
|
||||
#include "XCEngine/RHI/D3D12/D3D12DescriptorSet.h"
|
||||
#include "XCEngine/RHI/D3D12/D3D12QueryHeap.h"
|
||||
#include "XCEngine/RHI/D3D12/D3D12RootSignature.h"
|
||||
#include "XCEngine/RHI/D3D12/D3D12PipelineLayout.h"
|
||||
@@ -324,6 +325,24 @@ RHISampler* D3D12Device::CreateSampler(const SamplerDesc& desc) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RHIDescriptorPool* D3D12Device::CreateDescriptorPool(const DescriptorPoolDesc& desc) {
|
||||
auto* pool = new D3D12DescriptorHeap();
|
||||
DescriptorPoolDesc poolDesc = desc;
|
||||
poolDesc.device = m_device.Get();
|
||||
if (pool->Initialize(poolDesc)) {
|
||||
return pool;
|
||||
}
|
||||
delete pool;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RHIDescriptorSet* D3D12Device::CreateDescriptorSet(RHIDescriptorPool* pool, const DescriptorSetLayoutDesc& layout) {
|
||||
if (pool == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
return pool->AllocateSet(layout);
|
||||
}
|
||||
|
||||
RHIFence* D3D12Device::CreateFence(const FenceDesc& desc) {
|
||||
auto* fence = new D3D12Fence();
|
||||
if (fence->Initialize(m_device.Get(), desc.initialValue)) {
|
||||
|
||||
Reference in New Issue
Block a user