【关键节点】OpenGLCommandList实现RHIResourceView*方法完成统一资源绑定

OpenGL实现:
- TransitionBarrier: 调用glMemoryBarrier(GL_ALL_BARRIER_BITS)
- SetRenderTargets: 通过framebuffer绑定渲染目标
- SetVertexBuffer: 绑定GL_ARRAY_BUFFER并设置顶点属性
- SetIndexBuffer: 绑定GL_ELEMENT_ARRAY_BUFFER
- ClearRenderTarget: 临时切换framebuffer清除颜色缓冲
- ClearDepthStencil: 临时切换framebuffer清除深度 stencil缓冲
- CopyResource: 使用glCopyImageSubData复制纹理数据

新增单元测试:
- CommandList_TransitionBarrier_WithResourceView
- CommandList_SetRenderTargets_WithResourceView
- CommandList_SetVertexBuffer_WithResourceView
- CommandList_SetIndexBuffer_WithResourceView
- CommandList_ClearRenderTarget_WithResourceView
- CommandList_ClearDepthStencil_WithResourceView
- CommandList_CopyResource_WithResourceView

验证: 158个RHI单元测试全部通过, OpenGL集成测试全部通过
This commit is contained in:
2026-03-24 05:23:42 +08:00
parent 1d1eee823d
commit b1829bcfc5
2 changed files with 189 additions and 0 deletions

View File

@@ -1,4 +1,5 @@
#include "XCEngine/RHI/OpenGL/OpenGLCommandList.h"
#include "XCEngine/RHI/OpenGL/OpenGLResourceView.h"
#include <glad/glad.h>
namespace XCEngine {
@@ -433,6 +434,10 @@ void OpenGLCommandList::TransitionBarrier(void* resource, ResourceStates stateBe
}
void OpenGLCommandList::TransitionBarrier(RHIResourceView* resource, ResourceStates stateBefore, ResourceStates stateAfter) {
(void)resource;
(void)stateBefore;
(void)stateAfter;
glMemoryBarrier(GL_ALL_BARRIER_BITS);
}
void OpenGLCommandList::SetViewport(const Viewport& viewport) {
@@ -472,6 +477,30 @@ void OpenGLCommandList::SetRenderTargets(uint32_t count, void** renderTargets, v
}
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]) {
OpenGLResourceView* view = static_cast<OpenGLResourceView*>(renderTargets[i]);
fbos[i] = view->GetFramebuffer();
}
}
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[0]);
}
}
void OpenGLCommandList::ClearRenderTarget(void* renderTarget, const float color[4]) {
@@ -480,6 +509,18 @@ void OpenGLCommandList::ClearRenderTarget(void* renderTarget, const float color[
}
void OpenGLCommandList::ClearRenderTarget(RHIResourceView* renderTarget, const float color[4]) {
if (!renderTarget) return;
OpenGLResourceView* view = static_cast<OpenGLResourceView*>(renderTarget);
if (!view->IsValid()) return;
GLuint prevFBO = 0;
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, reinterpret_cast<GLint*>(&prevFBO));
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, view->GetFramebuffer());
glClearColor(color[0], color[1], color[2], color[3]);
glClear(GL_COLOR_BUFFER_BIT);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, prevFBO);
}
void OpenGLCommandList::ClearDepthStencil(void* depthStencil, float depth, uint8_t stencil) {
@@ -488,6 +529,19 @@ void OpenGLCommandList::ClearDepthStencil(void* depthStencil, float depth, uint8
}
void OpenGLCommandList::ClearDepthStencil(RHIResourceView* depthStencil, float depth, uint8_t stencil) {
if (!depthStencil) return;
OpenGLResourceView* view = static_cast<OpenGLResourceView*>(depthStencil);
if (!view->IsValid()) return;
GLuint prevFBO = 0;
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, reinterpret_cast<GLint*>(&prevFBO));
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, view->GetFramebuffer());
glClearDepth(depth);
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, prevFBO);
(void)stencil;
}
void OpenGLCommandList::SetPipelineState(void* pipelineState) {
@@ -504,6 +558,14 @@ void OpenGLCommandList::SetVertexBuffer(uint32_t slot, void* buffer, uint64_t of
}
void OpenGLCommandList::SetVertexBuffer(uint32_t slot, RHIResourceView* buffer, uint64_t offset, uint32_t stride) {
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)));
glEnableVertexAttribArray(slot);
}
void OpenGLCommandList::SetVertexBuffers(uint32_t startSlot, uint32_t count, const uint64_t* buffers, const uint64_t* offsets, const uint32_t* strides) {
@@ -524,12 +586,32 @@ void OpenGLCommandList::SetIndexBuffer(void* buffer, uint64_t offset, Format for
}
void OpenGLCommandList::SetIndexBuffer(RHIResourceView* buffer, uint64_t offset, Format format) {
if (!buffer) return;
OpenGLResourceView* view = static_cast<OpenGLResourceView*>(buffer);
if (!view->IsValid()) return;
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) {
if (!dst || !src) return;
OpenGLResourceView* dstView = static_cast<OpenGLResourceView*>(dst);
OpenGLResourceView* srcView = static_cast<OpenGLResourceView*>(src);
if (!dstView->IsValid() || !srcView->IsValid()) return;
GLuint dstTex = dstView->GetTexture();
GLuint srcTex = srcView->GetTexture();
if (dstTex && srcTex) {
glCopyImageSubData(srcTex, GL_TEXTURE_2D, 0, 0, 0, 0,
dstTex, GL_TEXTURE_2D, 0, 0, 0, 0,
256, 256, 1);
}
}
void OpenGLCommandList::Draw(uint32_t vertexCount, uint32_t instanceCount, uint32_t startVertex, uint32_t startInstance) {

View File

@@ -226,3 +226,110 @@ TEST_P(RHITestFixture, CommandList_TransitionBarrier) {
cmdList->Shutdown();
delete cmdList;
}
TEST_P(RHITestFixture, CommandList_TransitionBarrier_WithResourceView) {
CommandListDesc cmdDesc = {};
cmdDesc.commandListType = static_cast<uint32_t>(CommandQueueType::Direct);
RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc);
ASSERT_NE(cmdList, nullptr);
cmdList->Reset();
cmdList->TransitionBarrier(static_cast<RHIResourceView*>(nullptr), ResourceStates::Common, ResourceStates::RenderTarget);
cmdList->Close();
cmdList->Shutdown();
delete cmdList;
}
TEST_P(RHITestFixture, CommandList_SetRenderTargets_WithResourceView) {
CommandListDesc cmdDesc = {};
cmdDesc.commandListType = static_cast<uint32_t>(CommandQueueType::Direct);
RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc);
ASSERT_NE(cmdList, nullptr);
cmdList->Reset();
cmdList->SetRenderTargets(0, static_cast<RHIResourceView**>(nullptr), static_cast<RHIResourceView*>(nullptr));
cmdList->Close();
cmdList->Shutdown();
delete cmdList;
}
TEST_P(RHITestFixture, CommandList_SetVertexBuffer_WithResourceView) {
CommandListDesc cmdDesc = {};
cmdDesc.commandListType = static_cast<uint32_t>(CommandQueueType::Direct);
RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc);
ASSERT_NE(cmdList, nullptr);
cmdList->Reset();
cmdList->SetVertexBuffer(0, static_cast<RHIResourceView*>(nullptr), 0, 16);
cmdList->Close();
cmdList->Shutdown();
delete cmdList;
}
TEST_P(RHITestFixture, CommandList_SetIndexBuffer_WithResourceView) {
CommandListDesc cmdDesc = {};
cmdDesc.commandListType = static_cast<uint32_t>(CommandQueueType::Direct);
RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc);
ASSERT_NE(cmdList, nullptr);
cmdList->Reset();
cmdList->SetIndexBuffer(static_cast<RHIResourceView*>(nullptr), 0, Format::R32_UInt);
cmdList->Close();
cmdList->Shutdown();
delete cmdList;
}
TEST_P(RHITestFixture, CommandList_ClearRenderTarget_WithResourceView) {
CommandListDesc cmdDesc = {};
cmdDesc.commandListType = static_cast<uint32_t>(CommandQueueType::Direct);
RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc);
ASSERT_NE(cmdList, nullptr);
float color[4] = { 1.0f, 0.0f, 0.0f, 1.0f };
cmdList->Reset();
cmdList->ClearRenderTarget(static_cast<RHIResourceView*>(nullptr), color);
cmdList->Close();
cmdList->Shutdown();
delete cmdList;
}
TEST_P(RHITestFixture, CommandList_ClearDepthStencil_WithResourceView) {
CommandListDesc cmdDesc = {};
cmdDesc.commandListType = static_cast<uint32_t>(CommandQueueType::Direct);
RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc);
ASSERT_NE(cmdList, nullptr);
cmdList->Reset();
cmdList->ClearDepthStencil(static_cast<RHIResourceView*>(nullptr), 1.0f, 0);
cmdList->Close();
cmdList->Shutdown();
delete cmdList;
}
TEST_P(RHITestFixture, CommandList_CopyResource_WithResourceView) {
CommandListDesc cmdDesc = {};
cmdDesc.commandListType = static_cast<uint32_t>(CommandQueueType::Direct);
RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc);
ASSERT_NE(cmdList, nullptr);
cmdList->Reset();
cmdList->CopyResource(static_cast<RHIResourceView*>(nullptr), static_cast<RHIResourceView*>(nullptr));
cmdList->Close();
cmdList->Shutdown();
delete cmdList;
}