refactor(RHI): remove void* from CommandList interfaces and fix OpenGL MRT bug

- Remove void* parameters from RHICommandList abstract interface
- TransitionBarrier, SetVertexBuffer, SetIndexBuffer, SetRenderTargets,
  ClearRenderTarget, ClearDepthStencil, CopyResource now use RHIResourceView*
- SetPipelineState now uses RHIPipelineState* instead of void*
- Simplified SetVertexBuffer to 3 params, SetIndexBuffer to 2 params
- Add internal D3D12 APIs for native type support (low-level escape hatch)
- Fix OpenGL SetRenderTargets to call glDrawBuffers for MRT support
- Update tests to match new interface signatures

All 289 RHI tests pass (158 unit + 64 OpenGL backend + 58 D3D12 backend + 8 integration + 1 disabled)
This commit is contained in:
2026-03-24 17:20:51 +08:00
parent ac5c98584a
commit 0dde7234b7
10 changed files with 132 additions and 173 deletions

View File

@@ -1,5 +1,6 @@
#include "XCEngine/RHI/D3D12/D3D12CommandList.h"
#include "XCEngine/RHI/D3D12/D3D12ResourceView.h"
#include "XCEngine/RHI/D3D12/D3D12PipelineState.h"
namespace XCEngine {
namespace RHI {
@@ -74,26 +75,32 @@ void D3D12CommandList::Close() {
m_commandList->Close();
}
void D3D12CommandList::TransitionBarrier(void* resource, ResourceStates stateBefore, ResourceStates stateAfter) {
TransitionBarrierInternal(static_cast<ID3D12Resource*>(resource), stateBefore, stateAfter);
}
void D3D12CommandList::TransitionBarrier(RHIResourceView* resource, ResourceStates stateBefore, ResourceStates stateAfter) {
if (!resource || !resource->IsValid()) return;
D3D12ResourceView* d3d12View = static_cast<D3D12ResourceView*>(resource);
TransitionBarrierInternal(d3d12View->GetResource(), stateBefore, stateAfter);
}
void D3D12CommandList::UAVBarrier(void* resource) {
UAVBarrierInternal(static_cast<ID3D12Resource*>(resource));
void D3D12CommandList::TransitionBarrier(ID3D12Resource* resource, ResourceStates stateBefore, ResourceStates stateAfter) {
if (!resource) return;
TransitionBarrierInternal(resource, stateBefore, stateAfter);
}
void D3D12CommandList::AliasBarrier(void* beforeResource, void* afterResource) {
AliasBarrierInternal(static_cast<ID3D12Resource*>(beforeResource), static_cast<ID3D12Resource*>(afterResource));
void D3D12CommandList::UAVBarrier(ID3D12Resource* resource) {
UAVBarrierInternal(resource);
}
void D3D12CommandList::SetPipelineState(void* pso) {
SetPipelineStateInternal(static_cast<ID3D12PipelineState*>(pso));
void D3D12CommandList::AliasBarrier(ID3D12Resource* beforeResource, ID3D12Resource* afterResource) {
AliasBarrierInternal(beforeResource, afterResource);
}
void D3D12CommandList::SetPipelineState(RHIPipelineState* pso) {
if (!pso) return;
SetPipelineStateInternal(static_cast<ID3D12PipelineState*>(pso->GetNativeHandle()));
}
void D3D12CommandList::SetPipelineState(ID3D12PipelineState* pso) {
SetPipelineStateInternal(pso);
}
void D3D12CommandList::TransitionBarrierInternal(ID3D12Resource* resource, ResourceStates stateBefore, ResourceStates stateAfter, uint32_t subresource) {
@@ -196,14 +203,6 @@ void D3D12CommandList::SetPrimitiveTopology(PrimitiveTopology topology) {
m_currentTopology = ToD3D12Topology(topology);
}
void D3D12CommandList::SetRenderTargets(uint32_t count, void** renderTargets, void* depthStencil) {
std::vector<ID3D12Resource*> resources(count);
for (uint32_t i = 0; i < count; ++i) {
resources[i] = static_cast<ID3D12Resource*>(renderTargets[i]);
}
SetRenderTargetsInternal(count, resources.data(), static_cast<ID3D12Resource*>(depthStencil));
}
void D3D12CommandList::SetRenderTargets(uint32_t count, RHIResourceView** renderTargets, RHIResourceView* depthStencil) {
std::vector<D3D12_CPU_DESCRIPTOR_HANDLE> rtvHandles(count);
for (uint32_t i = 0; i < count; ++i) {
@@ -258,14 +257,18 @@ void D3D12CommandList::SetRenderTargetsHandle(uint32_t count, const D3D12_CPU_DE
}
}
void D3D12CommandList::SetVertexBuffer(uint32_t slot, void* buffer, uint64_t offset, uint32_t stride) {
SetVertexBufferInternal(slot, static_cast<ID3D12Resource*>(buffer), offset, stride);
}
void D3D12CommandList::SetVertexBuffer(uint32_t slot, RHIResourceView* buffer, uint64_t offset, uint32_t stride) {
void D3D12CommandList::SetVertexBuffer(uint32_t slot, RHIResourceView* buffer, uint64_t offset) {
if (!buffer || !buffer->IsValid()) return;
D3D12ResourceView* view = static_cast<D3D12ResourceView*>(buffer);
SetVertexBufferInternal(slot, view->GetResource(), offset, stride);
D3D12_VERTEX_BUFFER_VIEW vbView = {};
vbView.BufferLocation = view->GetResource()->GetGPUVirtualAddress() + offset;
vbView.SizeInBytes = static_cast<UINT>(view->GetResource()->GetDesc().Width) - static_cast<UINT>(offset);
vbView.StrideInBytes = 0;
m_commandList->IASetVertexBuffers(slot, 1, &vbView);
}
void D3D12CommandList::SetVertexBuffer(uint32_t slot, ID3D12Resource* buffer, uint64_t offset, uint32_t stride) {
SetVertexBufferInternal(slot, buffer, offset, stride);
}
void D3D12CommandList::SetVertexBufferInternal(uint32_t slot, ID3D12Resource* buffer, uint64_t offset, uint32_t stride) {
@@ -277,12 +280,15 @@ void D3D12CommandList::SetVertexBufferInternal(uint32_t slot, ID3D12Resource* bu
m_commandList->IASetVertexBuffers(slot, 1, &view);
}
void D3D12CommandList::SetVertexBuffers(uint32_t startSlot, uint32_t count, const uint64_t* buffers, const uint64_t* offsets, const uint32_t* strides) {
void D3D12CommandList::SetVertexBuffers(uint32_t startSlot, uint32_t count, RHIResourceView** buffers, const uint64_t* offsets, const uint32_t* strides) {
std::vector<D3D12_VERTEX_BUFFER_VIEW> views(count);
for (uint32_t i = 0; i < count; ++i) {
views[i].BufferLocation = buffers[i];
views[i].StrideInBytes = strides[i];
views[i].SizeInBytes = 0;
if (buffers[i] && buffers[i]->IsValid()) {
D3D12ResourceView* view = static_cast<D3D12ResourceView*>(buffers[i]);
views[i].BufferLocation = view->GetResource()->GetGPUVirtualAddress() + offsets[i];
views[i].StrideInBytes = strides[i];
views[i].SizeInBytes = static_cast<UINT>(view->GetResource()->GetDesc().Width) - static_cast<UINT>(offsets[i]);
}
}
SetVertexBuffersInternal(startSlot, count, views.data());
}
@@ -291,14 +297,14 @@ void D3D12CommandList::SetVertexBuffersInternal(uint32_t startSlot, uint32_t cou
m_commandList->IASetVertexBuffers(startSlot, count, views);
}
void D3D12CommandList::SetIndexBuffer(void* buffer, uint64_t offset, Format format) {
SetIndexBufferInternal(static_cast<ID3D12Resource*>(buffer), offset, format);
}
void D3D12CommandList::SetIndexBuffer(RHIResourceView* buffer, uint64_t offset, Format format) {
void D3D12CommandList::SetIndexBuffer(RHIResourceView* buffer, uint64_t offset) {
if (!buffer || !buffer->IsValid()) return;
D3D12ResourceView* view = static_cast<D3D12ResourceView*>(buffer);
SetIndexBufferInternal(view->GetResource(), offset, format);
SetIndexBufferInternal(view->GetResource(), offset, Format::R32_UInt);
}
void D3D12CommandList::SetIndexBuffer(ID3D12Resource* buffer, uint64_t offset, Format format) {
SetIndexBufferInternal(buffer, offset, format);
}
void D3D12CommandList::SetIndexBufferInternal(ID3D12Resource* buffer, uint64_t offset, Format indexFormat) {
@@ -352,7 +358,7 @@ void D3D12CommandList::SetDepthStencilState(const DepthStencilState& state) {
}
void D3D12CommandList::SetBlendState(const BlendState& state) {
// TODO: Implement blend state
m_commandList->OMSetBlendFactor(state.blendFactor);
}
void D3D12CommandList::SetDepthBias(float depthBias, float slopeScaledDepthBias, float depthBiasClamp) {
@@ -366,12 +372,12 @@ void D3D12CommandList::DrawIndexed(uint32_t indexCount, uint32_t instanceCount,
m_commandList->DrawIndexedInstanced(indexCount, instanceCount, startIndex, baseVertex, startInstance);
}
void D3D12CommandList::DrawInstancedIndirect(void* argBuffer, uint64_t alignedByteOffset) {
DrawInstancedIndirectInternal(static_cast<ID3D12Resource*>(argBuffer), alignedByteOffset);
void D3D12CommandList::DrawInstancedIndirect(ID3D12Resource* argBuffer, uint64_t alignedByteOffset) {
DrawInstancedIndirectInternal(argBuffer, alignedByteOffset);
}
void D3D12CommandList::DrawIndexedInstancedIndirect(void* argBuffer, uint64_t alignedByteOffset) {
DrawIndexedInstancedIndirectInternal(static_cast<ID3D12Resource*>(argBuffer), alignedByteOffset);
void D3D12CommandList::DrawIndexedInstancedIndirect(ID3D12Resource* argBuffer, uint64_t alignedByteOffset) {
DrawIndexedInstancedIndirectInternal(argBuffer, alignedByteOffset);
}
void D3D12CommandList::DrawInstancedIndirectInternal(ID3D12Resource* argBuffer, uint64_t alignedByteOffset) {
@@ -393,11 +399,7 @@ void D3D12CommandList::ClearRenderTargetView(D3D12_CPU_DESCRIPTOR_HANDLE renderT
}
void D3D12CommandList::Clear(float r, float g, float b, float a, uint32_t buffers) {
// Not implemented - use ClearRenderTargetView and ClearDepthStencilView directly
}
void D3D12CommandList::ClearRenderTarget(void* renderTarget, const float color[4]) {
ClearRenderTargetView(static_cast<ID3D12Resource*>(renderTarget), color, 0, nullptr);
(void)r; (void)g; (void)b; (void)a; (void)buffers;
}
void D3D12CommandList::ClearRenderTarget(RHIResourceView* renderTarget, const float color[4]) {
@@ -406,10 +408,6 @@ void D3D12CommandList::ClearRenderTarget(RHIResourceView* renderTarget, const fl
ClearRenderTargetView(view->GetCPUHandle(), color, 0, nullptr);
}
void D3D12CommandList::ClearDepthStencil(void* depthStencil, float depth, uint8_t stencil) {
ClearDepthStencilView(static_cast<ID3D12Resource*>(depthStencil), D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, depth, stencil, 0, nullptr);
}
void D3D12CommandList::ClearDepthStencil(RHIResourceView* depthStencil, float depth, uint8_t stencil) {
if (!depthStencil || !depthStencil->IsValid()) return;
D3D12ResourceView* view = static_cast<D3D12ResourceView*>(depthStencil);
@@ -429,10 +427,6 @@ void D3D12CommandList::ClearUnorderedAccessView(D3D12_GPU_DESCRIPTOR_HANDLE view
m_commandList->ClearUnorderedAccessViewFloat(viewHandle, resourceHandle, unorderedAccess, values, rectCount, rects);
}
void D3D12CommandList::CopyResource(void* dst, void* src) {
CopyResourceInternal(static_cast<ID3D12Resource*>(dst), static_cast<ID3D12Resource*>(src));
}
void D3D12CommandList::CopyResource(RHIResourceView* dst, RHIResourceView* src) {
if (!dst || !src || !dst->IsValid() || !src->IsValid()) return;
D3D12ResourceView* dstView = static_cast<D3D12ResourceView*>(dst);
@@ -488,8 +482,8 @@ void D3D12CommandList::Dispatch(uint32_t threadGroupCountX, uint32_t threadGroup
m_commandList->Dispatch(threadGroupCountX, threadGroupCountY, threadGroupCountZ);
}
void D3D12CommandList::DispatchIndirect(void* argBuffer, uint64_t alignedByteOffset) {
DispatchIndirectInternal(static_cast<ID3D12Resource*>(argBuffer), alignedByteOffset);
void D3D12CommandList::DispatchIndirect(ID3D12Resource* argBuffer, uint64_t alignedByteOffset) {
DispatchIndirectInternal(argBuffer, alignedByteOffset);
}
void D3D12CommandList::DispatchIndirectInternal(ID3D12Resource* argBuffer, uint64_t alignedByteOffset) {