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

@@ -19,6 +19,8 @@ class RHIPipelineState;
class D3D12ResourceView;
class D3D12Shader;
class D3D12PipelineLayout;
class D3D12RenderPass;
class D3D12Framebuffer;
class D3D12CommandList : public RHICommandList {
public:
@@ -56,6 +58,10 @@ public:
void AliasBarrier(ID3D12Resource* beforeResource = nullptr, ID3D12Resource* afterResource = nullptr);
void AliasBarrierInternal(ID3D12Resource* beforeResource, ID3D12Resource* afterResource);
void BeginRenderPass(class RHIRenderPass* renderPass, class RHIFramebuffer* framebuffer,
const Rect& renderArea, uint32_t clearValueCount, const ClearValue* clearValues) override;
void EndRenderPass() override;
void SetPipelineState(RHIPipelineState* pso) override;
void SetPipelineState(ID3D12PipelineState* pso);
void SetPipelineStateInternal(ID3D12PipelineState* pso);

View File

@@ -0,0 +1,52 @@
#pragma once
#include <d3d12.h>
#include <wrl/client.h>
#include <vector>
#include "../RHIFramebuffer.h"
#include "../RHIRenderPass.h"
using Microsoft::WRL::ComPtr;
namespace XCEngine {
namespace RHI {
class D3D12ResourceView;
class D3D12DescriptorHeap;
class D3D12RenderPass;
class D3D12Framebuffer : public RHIFramebuffer {
public:
D3D12Framebuffer();
~D3D12Framebuffer() override;
void Shutdown() override;
bool Initialize(D3D12RenderPass* renderPass, uint32_t width, uint32_t height,
uint32_t colorAttachmentCount, RHIResourceView** colorAttachments,
RHIResourceView* depthStencilAttachment);
void* GetNativeHandle() override { return nullptr; }
uint32_t GetWidth() const override { return m_width; }
uint32_t GetHeight() const override { return m_height; }
bool IsValid() const override { return m_renderPass != nullptr; }
D3D12_CPU_DESCRIPTOR_HANDLE GetRenderTargetHandle(uint32_t index) const;
D3D12_CPU_DESCRIPTOR_HANDLE GetDepthStencilHandle() const { return m_depthStencilHandle; }
bool HasDepthStencil() const { return m_depthStencilHandle.ptr != 0; }
uint32_t GetRenderTargetCount() const { return static_cast<uint32_t>(m_renderTargetHandles.size()); }
const D3D12_CPU_DESCRIPTOR_HANDLE* GetRenderTargetHandles() const { return m_renderTargetHandles.data(); }
D3D12RenderPass* GetRenderPass() const { return m_renderPass; }
private:
uint32_t m_width = 0;
uint32_t m_height = 0;
D3D12RenderPass* m_renderPass = nullptr;
std::vector<D3D12_CPU_DESCRIPTOR_HANDLE> m_renderTargetHandles;
D3D12_CPU_DESCRIPTOR_HANDLE m_depthStencilHandle = {};
};
} // namespace RHI
} // namespace XCEngine

View File

@@ -0,0 +1,44 @@
#pragma once
#include <d3d12.h>
#include <wrl/client.h>
#include <vector>
#include "../RHIRenderPass.h"
using Microsoft::WRL::ComPtr;
namespace XCEngine {
namespace RHI {
class D3D12Framebuffer;
class D3D12RenderPass : public RHIRenderPass {
public:
D3D12RenderPass();
~D3D12RenderPass() override;
void Shutdown() override;
bool Initialize(uint32_t colorAttachmentCount, const AttachmentDesc* colorAttachments,
const AttachmentDesc* depthStencilAttachment) override;
uint32_t GetColorAttachmentCount() const override { return m_colorAttachmentCount; }
const AttachmentDesc* GetColorAttachments() const override { return m_colorAttachments.data(); }
const AttachmentDesc* GetDepthStencilAttachment() const override { return m_hasDepthStencil ? &m_depthStencilAttachment : nullptr; }
void* GetNativeHandle() override { return nullptr; }
D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE GetBeginningAccessType(uint32_t index) const;
D3D12_RENDER_PASS_ENDING_ACCESS_TYPE GetEndingAccessType(uint32_t index) const;
D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE GetDepthBeginningAccessType() const;
D3D12_RENDER_PASS_ENDING_ACCESS_TYPE GetDepthEndingAccessType() const;
private:
uint32_t m_colorAttachmentCount = 0;
std::vector<AttachmentDesc> m_colorAttachments;
AttachmentDesc m_depthStencilAttachment;
bool m_hasDepthStencil = false;
};
} // namespace RHI
} // namespace XCEngine

View File

@@ -172,6 +172,9 @@ public:
void PopDebugGroup();
void TransitionBarrier(RHIResourceView* resource, ResourceStates stateBefore, ResourceStates stateAfter) override;
void BeginRenderPass(class RHIRenderPass* renderPass, class RHIFramebuffer* framebuffer,
const Rect& renderArea, uint32_t clearValueCount, const ClearValue* clearValues) override;
void EndRenderPass() override;
void SetPrimitiveTopology(PrimitiveTopology topology) override;
void SetViewport(const Viewport& viewport) override;
void SetViewports(uint32_t count, const Viewport* viewports) override;

View File

@@ -3,6 +3,9 @@
#include <cstdint>
#include <vector>
#include "../RHIFramebuffer.h"
#include "../RHIResourceView.h"
namespace XCEngine {
namespace RHI {
@@ -30,13 +33,21 @@ struct FramebufferDesc {
FramebufferAttachment stencilAttachment;
};
class OpenGLFramebuffer {
class OpenGLFramebuffer : public RHIFramebuffer {
public:
OpenGLFramebuffer();
~OpenGLFramebuffer();
~OpenGLFramebuffer() override;
bool Initialize(const FramebufferDesc& desc);
void Shutdown();
void Shutdown() override;
bool Initialize(class RHIRenderPass* renderPass, uint32_t width, uint32_t height,
uint32_t colorAttachmentCount, RHIResourceView** colorAttachments,
RHIResourceView* depthStencilAttachment) override;
void* GetNativeHandle() override { return reinterpret_cast<void*>(m_framebuffer); }
uint32_t GetWidth() const override { return static_cast<uint32_t>(m_width); }
uint32_t GetHeight() const override { return static_cast<uint32_t>(m_height); }
bool IsValid() const override { return m_framebuffer != 0; }
void Bind();
void Unbind();
@@ -47,9 +58,6 @@ public:
void ClearDepthStencil(float depth, uint8_t stencil);
unsigned int GetFramebuffer() const { return m_framebuffer; }
int GetWidth() const { return m_width; }
int GetHeight() const { return m_height; }
bool IsValid() const { return m_framebuffer != 0; }
static void BindFramebuffer(unsigned int framebuffer);
static void UnbindFramebuffer();

View File

@@ -0,0 +1,35 @@
#pragma once
#include <vector>
#include "../RHIRenderPass.h"
namespace XCEngine {
namespace RHI {
class OpenGLFramebuffer;
class OpenGLRenderPass : public RHIRenderPass {
public:
OpenGLRenderPass();
~OpenGLRenderPass() override;
void Shutdown() override;
bool Initialize(uint32_t colorAttachmentCount, const AttachmentDesc* colorAttachments,
const AttachmentDesc* depthStencilAttachment) override;
uint32_t GetColorAttachmentCount() const override { return m_colorAttachmentCount; }
const AttachmentDesc* GetColorAttachments() const override { return m_colorAttachments.data(); }
const AttachmentDesc* GetDepthStencilAttachment() const override { return m_hasDepthStencil ? &m_depthStencilAttachment : nullptr; }
void* GetNativeHandle() override { return nullptr; }
private:
uint32_t m_colorAttachmentCount = 0;
std::vector<AttachmentDesc> m_colorAttachments;
AttachmentDesc m_depthStencilAttachment;
bool m_hasDepthStencil = false;
};
} // namespace RHI
} // namespace XCEngine

View File

@@ -56,6 +56,10 @@ public:
virtual void TransitionBarrier(RHIResourceView* resource, ResourceStates stateBefore, ResourceStates stateAfter) = 0;
virtual void BeginRenderPass(class RHIRenderPass* renderPass, class RHIFramebuffer* framebuffer,
const Rect& renderArea, uint32_t clearValueCount, const ClearValue* clearValues) = 0;
virtual void EndRenderPass() = 0;
virtual void SetShader(RHIShader* shader) = 0;
virtual void SetUniformInt(const char* name, int value) = 0;

View File

@@ -0,0 +1,28 @@
#pragma once
#include "RHITypes.h"
#include "RHIEnums.h"
#include "RHIResourceView.h"
#include <cstdint>
namespace XCEngine {
namespace RHI {
class RHIFramebuffer {
public:
virtual ~RHIFramebuffer() = default;
virtual void Shutdown() = 0;
virtual bool Initialize(class RHIRenderPass* renderPass, uint32_t width, uint32_t height,
uint32_t colorAttachmentCount, RHIResourceView** colorAttachments,
RHIResourceView* depthStencilAttachment) = 0;
virtual void* GetNativeHandle() = 0;
virtual uint32_t GetWidth() const = 0;
virtual uint32_t GetHeight() const = 0;
virtual bool IsValid() const = 0;
};
} // namespace RHI
} // namespace XCEngine

View File

@@ -0,0 +1,35 @@
#pragma once
#include "RHITypes.h"
#include "RHIEnums.h"
#include <cstdint>
namespace XCEngine {
namespace RHI {
struct AttachmentDesc {
Format format = Format::Unknown;
LoadAction loadOp = LoadAction::Undefined;
StoreAction storeOp = StoreAction::Store;
LoadAction stencilLoadOp = LoadAction::Undefined;
StoreAction stencilStoreOp = StoreAction::Undefined;
ClearValue clearValue;
};
class RHIRenderPass {
public:
virtual ~RHIRenderPass() = default;
virtual void Shutdown() = 0;
virtual bool Initialize(uint32_t colorAttachmentCount, const AttachmentDesc* colorAttachments,
const AttachmentDesc* depthStencilAttachment) = 0;
virtual uint32_t GetColorAttachmentCount() const = 0;
virtual const AttachmentDesc* GetColorAttachments() const = 0;
virtual const AttachmentDesc* GetDepthStencilAttachment() const = 0;
virtual void* GetNativeHandle() = 0;
};
} // namespace RHI
} // namespace XCEngine

View File

@@ -3,6 +3,8 @@
#include "XCEngine/RHI/D3D12/D3D12PipelineState.h"
#include "XCEngine/RHI/D3D12/D3D12Shader.h"
#include "XCEngine/RHI/D3D12/D3D12PipelineLayout.h"
#include "XCEngine/RHI/D3D12/D3D12RenderPass.h"
#include "XCEngine/RHI/D3D12/D3D12Framebuffer.h"
namespace XCEngine {
namespace RHI {
@@ -245,6 +247,52 @@ void D3D12CommandList::AliasBarrierInternal(ID3D12Resource* beforeResource, ID3D
m_commandList->ResourceBarrier(1, &barrier);
}
void D3D12CommandList::BeginRenderPass(RHIRenderPass* renderPass, RHIFramebuffer* framebuffer,
const Rect& renderArea, uint32_t clearValueCount, const ClearValue* clearValues) {
(void)renderArea;
if (!framebuffer || !renderPass) return;
D3D12Framebuffer* d3d12Framebuffer = static_cast<D3D12Framebuffer*>(framebuffer);
uint32_t rtCount = d3d12Framebuffer->GetRenderTargetCount();
const D3D12_CPU_DESCRIPTOR_HANDLE* rtHandles = d3d12Framebuffer->GetRenderTargetHandles();
bool hasDS = d3d12Framebuffer->HasDepthStencil();
D3D12_CPU_DESCRIPTOR_HANDLE dsHandle = d3d12Framebuffer->GetDepthStencilHandle();
D3D12RenderPass* d3d12RenderPass = static_cast<D3D12RenderPass*>(renderPass);
const AttachmentDesc* attachments = d3d12RenderPass->GetColorAttachments();
for (uint32_t i = 0; i < rtCount; ++i) {
if (attachments[i].loadOp == LoadAction::Clear && clearValueCount > i) {
m_commandList->ClearRenderTargetView(rtHandles[i], &clearValues[i].color.r, 0, nullptr);
}
}
if (hasDS) {
const AttachmentDesc* dsAttachment = d3d12RenderPass->GetDepthStencilAttachment();
if (dsAttachment) {
uint32_t clearFlags = 0;
if (dsAttachment->loadOp == LoadAction::Clear) clearFlags |= D3D12_CLEAR_FLAG_DEPTH;
if (dsAttachment->stencilLoadOp == LoadAction::Clear) clearFlags |= D3D12_CLEAR_FLAG_STENCIL;
if (clearFlags && clearValueCount > rtCount) {
m_commandList->ClearDepthStencilView(dsHandle, static_cast<D3D12_CLEAR_FLAGS>(clearFlags), clearValues[rtCount].depth, clearValues[rtCount].stencil, 0, nullptr);
}
}
}
m_commandList->OMSetRenderTargets(rtCount, rtHandles, FALSE, hasDS ? &dsHandle : nullptr);
m_boundRenderTargets.clear();
for (uint32_t i = 0; i < rtCount; ++i) {
m_boundRenderTargets.push_back(rtHandles[i]);
}
m_boundDepthStencil = dsHandle;
m_depthStencilBound = hasDS;
}
void D3D12CommandList::EndRenderPass() {
}
void D3D12CommandList::SetPipelineStateInternal(ID3D12PipelineState* pso) {
m_commandList->SetPipelineState(pso);
m_currentPipelineState = pso;

View File

@@ -0,0 +1,56 @@
#include "XCEngine/RHI/D3D12/D3D12Framebuffer.h"
#include "XCEngine/RHI/D3D12/D3D12RenderPass.h"
#include "XCEngine/RHI/D3D12/D3D12ResourceView.h"
namespace XCEngine {
namespace RHI {
D3D12Framebuffer::D3D12Framebuffer() {
}
D3D12Framebuffer::~D3D12Framebuffer() {
Shutdown();
}
void D3D12Framebuffer::Shutdown() {
m_renderTargetHandles.clear();
m_depthStencilHandle = {};
m_renderPass = nullptr;
m_width = 0;
m_height = 0;
}
bool D3D12Framebuffer::Initialize(D3D12RenderPass* renderPass, uint32_t width, uint32_t height,
uint32_t colorAttachmentCount, RHIResourceView** colorAttachments,
RHIResourceView* depthStencilAttachment) {
m_renderPass = renderPass;
m_width = width;
m_height = height;
m_renderTargetHandles.resize(colorAttachmentCount);
for (uint32_t i = 0; i < colorAttachmentCount; ++i) {
if (colorAttachments[i]) {
D3D12ResourceView* view = static_cast<D3D12ResourceView*>(colorAttachments[i]);
m_renderTargetHandles[i] = view->GetCPUHandle();
}
}
if (depthStencilAttachment) {
D3D12ResourceView* view = static_cast<D3D12ResourceView*>(depthStencilAttachment);
m_depthStencilHandle = view->GetCPUHandle();
} else {
m_depthStencilHandle = {};
}
return true;
}
D3D12_CPU_DESCRIPTOR_HANDLE D3D12Framebuffer::GetRenderTargetHandle(uint32_t index) const {
if (index >= m_renderTargetHandles.size()) {
return {};
}
return m_renderTargetHandles[index];
}
} // namespace RHI
} // namespace XCEngine

View File

@@ -0,0 +1,103 @@
#include "XCEngine/RHI/D3D12/D3D12RenderPass.h"
#include "XCEngine/RHI/D3D12/D3D12Framebuffer.h"
namespace XCEngine {
namespace RHI {
D3D12RenderPass::D3D12RenderPass() {
}
D3D12RenderPass::~D3D12RenderPass() {
Shutdown();
}
void D3D12RenderPass::Shutdown() {
m_colorAttachments.clear();
m_colorAttachmentCount = 0;
m_hasDepthStencil = false;
}
bool D3D12RenderPass::Initialize(uint32_t colorAttachmentCount, const AttachmentDesc* colorAttachments,
const AttachmentDesc* depthStencilAttachment) {
m_colorAttachmentCount = colorAttachmentCount;
m_colorAttachments.resize(colorAttachmentCount);
for (uint32_t i = 0; i < colorAttachmentCount; ++i) {
m_colorAttachments[i] = colorAttachments[i];
}
if (depthStencilAttachment != nullptr) {
m_hasDepthStencil = true;
m_depthStencilAttachment = *depthStencilAttachment;
} else {
m_hasDepthStencil = false;
}
return true;
}
D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE D3D12RenderPass::GetBeginningAccessType(uint32_t index) const {
if (index >= m_colorAttachmentCount) {
return D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE::D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_NO_ACCESS;
}
switch (m_colorAttachments[index].loadOp) {
case LoadAction::Clear:
return D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE::D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_CLEAR;
case LoadAction::Load:
return D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE::D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_PRESERVE;
case LoadAction::Undefined:
default:
return D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE::D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_DISCARD;
}
}
D3D12_RENDER_PASS_ENDING_ACCESS_TYPE D3D12RenderPass::GetEndingAccessType(uint32_t index) const {
if (index >= m_colorAttachmentCount) {
return D3D12_RENDER_PASS_ENDING_ACCESS_TYPE::D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_NO_ACCESS;
}
switch (m_colorAttachments[index].storeOp) {
case StoreAction::Store:
return D3D12_RENDER_PASS_ENDING_ACCESS_TYPE::D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE;
case StoreAction::Discard:
return D3D12_RENDER_PASS_ENDING_ACCESS_TYPE::D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_DISCARD;
case StoreAction::Resolve:
return D3D12_RENDER_PASS_ENDING_ACCESS_TYPE::D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_RESOLVE;
case StoreAction::StoreAndResolve:
return D3D12_RENDER_PASS_ENDING_ACCESS_TYPE::D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_STORE_AND_RESOLVE;
case StoreAction::Undefined:
default:
return D3D12_RENDER_PASS_ENDING_ACCESS_TYPE::D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_NO_ACCESS;
}
}
D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE D3D12RenderPass::GetDepthBeginningAccessType() const {
if (!m_hasDepthStencil) {
return D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE::D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_NO_ACCESS;
}
switch (m_depthStencilAttachment.loadOp) {
case LoadAction::Clear:
return D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE::D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_CLEAR;
case LoadAction::Load:
return D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE::D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_PRESERVE;
case LoadAction::Undefined:
default:
return D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE::D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_DISCARD;
}
}
D3D12_RENDER_PASS_ENDING_ACCESS_TYPE D3D12RenderPass::GetDepthEndingAccessType() const {
if (!m_hasDepthStencil) {
return D3D12_RENDER_PASS_ENDING_ACCESS_TYPE::D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_NO_ACCESS;
}
switch (m_depthStencilAttachment.storeOp) {
case StoreAction::Store:
return D3D12_RENDER_PASS_ENDING_ACCESS_TYPE::D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE;
case StoreAction::Discard:
return D3D12_RENDER_PASS_ENDING_ACCESS_TYPE::D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_DISCARD;
case StoreAction::Undefined:
default:
return D3D12_RENDER_PASS_ENDING_ACCESS_TYPE::D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_NO_ACCESS;
}
}
} // namespace RHI
} // namespace XCEngine

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

View File

@@ -1,4 +1,5 @@
#include "XCEngine/RHI/OpenGL/OpenGLFramebuffer.h"
#include "XCEngine/RHI/OpenGL/OpenGLResourceView.h"
#include <glad/glad.h>
namespace XCEngine {
@@ -97,6 +98,57 @@ void OpenGLFramebuffer::Shutdown() {
m_samples = 1;
}
bool OpenGLFramebuffer::Initialize(class RHIRenderPass* renderPass, uint32_t width, uint32_t height,
uint32_t colorAttachmentCount, RHIResourceView** colorAttachments,
RHIResourceView* depthStencilAttachment) {
(void)renderPass;
m_width = static_cast<int>(width);
m_height = static_cast<int>(height);
m_samples = 1;
glGenFramebuffers(1, &m_framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
GLenum drawBuffers[16] = { GL_NONE };
int drawBufferCount = 0;
for (uint32_t i = 0; i < colorAttachmentCount && i < 16; ++i) {
if (colorAttachments[i]) {
OpenGLResourceView* view = static_cast<OpenGLResourceView*>(colorAttachments[i]);
GLenum glAttachment = GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(i);
unsigned int texture = view->GetTexture();
if (texture) {
glFramebufferTexture2D(GL_FRAMEBUFFER, glAttachment, GL_TEXTURE_2D, texture, 0);
}
drawBuffers[drawBufferCount++] = glAttachment;
}
}
if (depthStencilAttachment) {
OpenGLResourceView* view = static_cast<OpenGLResourceView*>(depthStencilAttachment);
unsigned int texture = view->GetTexture();
if (texture) {
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, texture, 0);
}
}
if (drawBufferCount > 0) {
glDrawBuffers(drawBufferCount, drawBuffers);
} else {
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
}
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
glBindFramebuffer(GL_FRAMEBUFFER, 0);
return false;
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
return true;
}
void OpenGLFramebuffer::Bind() {
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
}

View File

@@ -0,0 +1,38 @@
#include "XCEngine/RHI/OpenGL/OpenGLRenderPass.h"
namespace XCEngine {
namespace RHI {
OpenGLRenderPass::OpenGLRenderPass() {
}
OpenGLRenderPass::~OpenGLRenderPass() {
Shutdown();
}
void OpenGLRenderPass::Shutdown() {
m_colorAttachments.clear();
m_colorAttachmentCount = 0;
m_hasDepthStencil = false;
}
bool OpenGLRenderPass::Initialize(uint32_t colorAttachmentCount, const AttachmentDesc* colorAttachments,
const AttachmentDesc* depthStencilAttachment) {
m_colorAttachmentCount = colorAttachmentCount;
m_colorAttachments.resize(colorAttachmentCount);
for (uint32_t i = 0; i < colorAttachmentCount; ++i) {
m_colorAttachments[i] = colorAttachments[i];
}
if (depthStencilAttachment != nullptr) {
m_hasDepthStencil = true;
m_depthStencilAttachment = *depthStencilAttachment;
} else {
m_hasDepthStencil = false;
}
return true;
}
} // namespace RHI
} // namespace XCEngine