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/OpenGL/OpenGLCommandList.h"
#include "XCEngine/RHI/OpenGL/OpenGLResourceView.h"
#include "XCEngine/RHI/OpenGL/OpenGLPipelineState.h"
#include <glad/glad.h>
namespace XCEngine {
@@ -430,9 +431,6 @@ void OpenGLCommandList::Reset() {
void OpenGLCommandList::Close() {
}
void OpenGLCommandList::TransitionBarrier(void* resource, ResourceStates stateBefore, ResourceStates stateAfter) {
}
void OpenGLCommandList::TransitionBarrier(RHIResourceView* resource, ResourceStates stateBefore, ResourceStates stateAfter) {
(void)resource;
(void)stateBefore;
@@ -473,25 +471,8 @@ void OpenGLCommandList::SetScissorRects(uint32_t count, const Rect* rects) {
glScissorArrayv(0, count, scissorGL.data());
}
void OpenGLCommandList::SetRenderTargets(uint32_t count, void** renderTargets, void* depthStencil) {
}
void OpenGLCommandList::SetRenderTargets(uint32_t count, RHIResourceView** renderTargets, RHIResourceView* depthStencil) {
if (count > 0 && renderTargets != nullptr) {
OpenGLResourceView* view = static_cast<OpenGLResourceView*>(renderTargets[0]);
if (view && view->IsValid()) {
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, view->GetFramebuffer());
}
} else if (depthStencil) {
OpenGLResourceView* dsv = static_cast<OpenGLResourceView*>(depthStencil);
if (dsv && dsv->IsValid()) {
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dsv->GetFramebuffer());
}
} else {
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
}
if (count > 1 && renderTargets != nullptr) {
std::vector<GLuint> fbos(count);
for (uint32_t i = 0; i < count; ++i) {
if (renderTargets[i]) {
@@ -499,13 +480,26 @@ void OpenGLCommandList::SetRenderTargets(uint32_t count, RHIResourceView** rende
fbos[i] = view->GetFramebuffer();
}
}
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[0]);
}
}
void OpenGLCommandList::ClearRenderTarget(void* renderTarget, const float color[4]) {
glClearColor(color[0], color[1], color[2], color[3]);
glClear(GL_COLOR_BUFFER_BIT);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[0]);
std::vector<GLenum> drawBuffers(count);
for (uint32_t i = 0; i < count; ++i) {
drawBuffers[i] = GL_COLOR_ATTACHMENT0 + i;
}
glDrawBuffers(count, drawBuffers.data());
} else if (depthStencil) {
OpenGLResourceView* dsv = static_cast<OpenGLResourceView*>(depthStencil);
if (dsv && dsv->IsValid()) {
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dsv->GetFramebuffer());
}
glDrawBuffers(0, nullptr);
} else {
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
}
(void)depthStencil;
}
void OpenGLCommandList::ClearRenderTarget(RHIResourceView* renderTarget, const float color[4]) {
@@ -523,11 +517,6 @@ void OpenGLCommandList::ClearRenderTarget(RHIResourceView* renderTarget, const f
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, prevFBO);
}
void OpenGLCommandList::ClearDepthStencil(void* depthStencil, float depth, uint8_t stencil) {
glClearDepth(depth);
glClear(GL_DEPTH_BUFFER_BIT);
}
void OpenGLCommandList::ClearDepthStencil(RHIResourceView* depthStencil, float depth, uint8_t stencil) {
if (!depthStencil) return;
OpenGLResourceView* view = static_cast<OpenGLResourceView*>(depthStencil);
@@ -544,33 +533,30 @@ void OpenGLCommandList::ClearDepthStencil(RHIResourceView* depthStencil, float d
(void)stencil;
}
void OpenGLCommandList::SetPipelineState(void* pipelineState) {
void OpenGLCommandList::SetPipelineState(RHIPipelineState* pipelineState) {
if (pipelineState) {
UseShader(reinterpret_cast<uintptr_t>(pipelineState));
UseShader(reinterpret_cast<uintptr_t>(pipelineState->GetNativeHandle()));
}
}
void OpenGLCommandList::SetVertexBuffer(uint32_t slot, void* buffer, uint64_t offset, uint32_t stride) {
GLuint glBuffer = static_cast<GLuint>(reinterpret_cast<uintptr_t>(buffer));
glBindBuffer(GL_ARRAY_BUFFER, glBuffer);
glVertexAttribPointer(slot, stride / sizeof(float), GL_FLOAT, GL_FALSE, stride, reinterpret_cast<void*>(static_cast<uintptr_t>(offset)));
glEnableVertexAttribArray(slot);
}
void OpenGLCommandList::SetVertexBuffer(uint32_t slot, RHIResourceView* buffer, uint64_t offset, uint32_t stride) {
void OpenGLCommandList::SetVertexBuffer(uint32_t slot, RHIResourceView* buffer, uint64_t offset) {
if (!buffer) return;
OpenGLResourceView* view = static_cast<OpenGLResourceView*>(buffer);
if (!view->IsValid()) return;
GLuint glBuffer = view->GetBuffer();
glBindBuffer(GL_ARRAY_BUFFER, glBuffer);
glVertexAttribPointer(slot, stride / sizeof(float), GL_FLOAT, GL_FALSE, stride, reinterpret_cast<void*>(static_cast<uintptr_t>(offset)));
glVertexAttribPointer(slot, 4, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void*>(static_cast<uintptr_t>(offset)));
glEnableVertexAttribArray(slot);
}
void OpenGLCommandList::SetVertexBuffers(uint32_t startSlot, uint32_t count, const uint64_t* buffers, const uint64_t* offsets, const uint32_t* strides) {
void OpenGLCommandList::SetVertexBuffers(uint32_t startSlot, uint32_t count, RHIResourceView** buffers, const uint64_t* offsets, const uint32_t* strides) {
for (uint32_t i = 0; i < count; i++) {
GLuint glBuffer = static_cast<GLuint>(buffers[i]);
if (!buffers[i]) continue;
OpenGLResourceView* view = static_cast<OpenGLResourceView*>(buffers[i]);
if (!view->IsValid()) continue;
GLuint glBuffer = view->GetBuffer();
glBindBuffer(GL_ARRAY_BUFFER, glBuffer);
glEnableVertexAttribArray(startSlot + i);
glVertexAttribPointer(startSlot + i, strides[i] / sizeof(float), GL_FLOAT, GL_FALSE, strides[i], reinterpret_cast<void*>(static_cast<uintptr_t>(offsets[i])));
@@ -578,14 +564,7 @@ void OpenGLCommandList::SetVertexBuffers(uint32_t startSlot, uint32_t count, con
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void OpenGLCommandList::SetIndexBuffer(void* buffer, uint64_t offset, Format format) {
GLuint glBuffer = static_cast<GLuint>(reinterpret_cast<uintptr_t>(buffer));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glBuffer);
(void)offset;
(void)format;
}
void OpenGLCommandList::SetIndexBuffer(RHIResourceView* buffer, uint64_t offset, Format format) {
void OpenGLCommandList::SetIndexBuffer(RHIResourceView* buffer, uint64_t offset) {
if (!buffer) return;
OpenGLResourceView* view = static_cast<OpenGLResourceView*>(buffer);
if (!view->IsValid()) return;
@@ -593,10 +572,6 @@ void OpenGLCommandList::SetIndexBuffer(RHIResourceView* buffer, uint64_t offset,
GLuint glBuffer = view->GetBuffer();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glBuffer);
(void)offset;
(void)format;
}
void OpenGLCommandList::CopyResource(void* dst, void* src) {
}
void OpenGLCommandList::CopyResource(RHIResourceView* dst, RHIResourceView* src) {