RHI: Add explicit RenderPass abstraction (BeginRenderPass/EndRenderPass)

New abstractions:
- RHIFramebuffer: Framebuffer interface with Initialize/Bind/GetHandle
- RHIRenderPass: RenderPass interface with AttachmentDesc for load/store actions
- D3D12Framebuffer/D3D12RenderPass: D3D12 implementation
- OpenGLFramebuffer/OpenGLRenderPass: OpenGL implementation (adapted from existing)

RHICommandList changes:
- Added BeginRenderPass(RHIRenderPass*, RHIFramebuffer*, Rect, clearValues...)
- Added EndRenderPass()

Implementation notes:
- D3D12: Uses OMSetRenderTargets + ClearRenderTargetView (fallback from native RenderPass API)
- OpenGL: Uses glBindFramebuffer + glClearBufferfv for LoadOp handling
- Old SetRenderTargets/ClearRenderTarget retained for backward compatibility

All 845 tests pass.
This commit is contained in:
2026-03-24 23:59:44 +08:00
parent 1e88beacb8
commit 5eb731bc2d
15 changed files with 559 additions and 6 deletions

View File

@@ -2,6 +2,8 @@
#include "XCEngine/RHI/OpenGL/OpenGLResourceView.h"
#include "XCEngine/RHI/OpenGL/OpenGLPipelineState.h"
#include "XCEngine/RHI/OpenGL/OpenGLShader.h"
#include "XCEngine/RHI/OpenGL/OpenGLFramebuffer.h"
#include "XCEngine/RHI/OpenGL/OpenGLRenderPass.h"
#include <glad/glad.h>
namespace XCEngine {
@@ -508,6 +510,45 @@ void OpenGLCommandList::TransitionBarrier(RHIResourceView* resource, ResourceSta
glMemoryBarrier(GL_ALL_BARRIER_BITS);
}
void OpenGLCommandList::BeginRenderPass(RHIRenderPass* renderPass, RHIFramebuffer* framebuffer,
const Rect& renderArea, uint32_t clearValueCount, const ClearValue* clearValues) {
(void)renderArea;
(void)clearValueCount;
(void)clearValues;
if (!framebuffer) return;
OpenGLFramebuffer* glFramebuffer = static_cast<OpenGLFramebuffer*>(framebuffer);
glFramebuffer->Bind();
OpenGLRenderPass* glRenderPass = static_cast<OpenGLRenderPass*>(renderPass);
if (glRenderPass) {
const AttachmentDesc* colorAttachments = glRenderPass->GetColorAttachments();
uint32_t colorCount = glRenderPass->GetColorAttachmentCount();
for (uint32_t i = 0; i < colorCount && i < clearValueCount; ++i) {
if (colorAttachments[i].loadOp == LoadAction::Clear) {
glClearBufferfv(GL_COLOR, i, &clearValues[i].color.r);
}
}
const AttachmentDesc* dsAttachment = glRenderPass->GetDepthStencilAttachment();
if (dsAttachment && clearValueCount > colorCount) {
if (dsAttachment->loadOp == LoadAction::Clear) {
glClearBufferfv(GL_DEPTH, 0, &clearValues[colorCount].depth);
}
if (dsAttachment->stencilLoadOp == LoadAction::Clear) {
float stencilValue = static_cast<float>(clearValues[colorCount].stencil);
glClearBufferfv(GL_STENCIL, 0, &stencilValue);
}
}
}
}
void OpenGLCommandList::EndRenderPass() {
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
void OpenGLCommandList::SetViewport(const Viewport& viewport) {
glViewport(static_cast<int>(viewport.topLeftX), static_cast<int>(viewport.topLeftY),
static_cast<int>(viewport.width), static_cast<int>(viewport.height));