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:
2026-03-25 00:26:16 +08:00
parent c5c43ae7aa
commit c6fe9547aa
22 changed files with 688 additions and 1 deletions

View File

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