Fix OpenGL render target binding composition
This commit is contained in:
@@ -14,6 +14,7 @@ class OpenGLVertexArray;
|
|||||||
class OpenGLShader;
|
class OpenGLShader;
|
||||||
class OpenGLTexture;
|
class OpenGLTexture;
|
||||||
class OpenGLPipelineState;
|
class OpenGLPipelineState;
|
||||||
|
class OpenGLFramebuffer;
|
||||||
|
|
||||||
enum class PrimitiveType {
|
enum class PrimitiveType {
|
||||||
Points,
|
Points,
|
||||||
@@ -193,6 +194,7 @@ public:
|
|||||||
void DrawIndexed(uint32_t indexCount, uint32_t instanceCount, uint32_t startIndex, int32_t baseVertex, uint32_t startInstance) override;
|
void DrawIndexed(uint32_t indexCount, uint32_t instanceCount, uint32_t startIndex, int32_t baseVertex, uint32_t startInstance) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void ReleaseComposedFramebuffer();
|
||||||
void EnsureInternalVertexArrayBound();
|
void EnsureInternalVertexArrayBound();
|
||||||
void DisableConfiguredVertexAttributes();
|
void DisableConfiguredVertexAttributes();
|
||||||
|
|
||||||
@@ -203,6 +205,7 @@ private:
|
|||||||
OpenGLPipelineState* m_currentPipelineState;
|
OpenGLPipelineState* m_currentPipelineState;
|
||||||
std::vector<unsigned int> m_enabledVertexAttributes;
|
std::vector<unsigned int> m_enabledVertexAttributes;
|
||||||
OpenGLShader* m_currentShader;
|
OpenGLShader* m_currentShader;
|
||||||
|
OpenGLFramebuffer* m_composedFramebuffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace RHI
|
} // namespace RHI
|
||||||
|
|||||||
@@ -18,8 +18,9 @@ enum class FramebufferAttachmentType {
|
|||||||
|
|
||||||
struct FramebufferAttachment {
|
struct FramebufferAttachment {
|
||||||
unsigned int texture = 0;
|
unsigned int texture = 0;
|
||||||
|
unsigned int target = 0;
|
||||||
int mipLevel = 0;
|
int mipLevel = 0;
|
||||||
int layer = 0;
|
int layer = -1;
|
||||||
FramebufferAttachmentType type = FramebufferAttachmentType::Color;
|
FramebufferAttachmentType type = FramebufferAttachmentType::Color;
|
||||||
uint32_t format = 0;
|
uint32_t format = 0;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "XCEngine/RHI/OpenGL/OpenGLFramebuffer.h"
|
||||||
#include "XCEngine/RHI/RHIResourceView.h"
|
#include "XCEngine/RHI/RHIResourceView.h"
|
||||||
#include "XCEngine/RHI/RHITypes.h"
|
#include "XCEngine/RHI/RHITypes.h"
|
||||||
|
|
||||||
@@ -63,6 +64,8 @@ public:
|
|||||||
uint64_t GetBufferOffset() const { return m_bufferOffset; }
|
uint64_t GetBufferOffset() const { return m_bufferOffset; }
|
||||||
uint32_t GetBufferSize() const { return m_bufferSize; }
|
uint32_t GetBufferSize() const { return m_bufferSize; }
|
||||||
uint32_t GetBufferStride() const { return m_bufferStride; }
|
uint32_t GetBufferStride() const { return m_bufferStride; }
|
||||||
|
const FramebufferAttachment& GetFramebufferAttachment() const { return m_framebufferAttachment; }
|
||||||
|
const OpenGLTexture* GetTextureResource() const { return m_texture; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ResourceViewType m_viewType;
|
ResourceViewType m_viewType;
|
||||||
@@ -76,6 +79,7 @@ private:
|
|||||||
OpenGLFramebuffer* m_framebuffer;
|
OpenGLFramebuffer* m_framebuffer;
|
||||||
OpenGLTextureUnitAllocator* m_textureUnitAllocator;
|
OpenGLTextureUnitAllocator* m_textureUnitAllocator;
|
||||||
OpenGLUniformBufferManager* m_uniformBufferManager;
|
OpenGLUniformBufferManager* m_uniformBufferManager;
|
||||||
|
FramebufferAttachment m_framebufferAttachment;
|
||||||
uint64_t m_bufferOffset;
|
uint64_t m_bufferOffset;
|
||||||
uint32_t m_bufferSize;
|
uint32_t m_bufferSize;
|
||||||
uint32_t m_bufferStride;
|
uint32_t m_bufferStride;
|
||||||
|
|||||||
@@ -65,7 +65,8 @@ OpenGLCommandList::OpenGLCommandList()
|
|||||||
, m_currentProgram(0)
|
, m_currentProgram(0)
|
||||||
, m_internalVAO(0)
|
, m_internalVAO(0)
|
||||||
, m_currentPipelineState(nullptr)
|
, m_currentPipelineState(nullptr)
|
||||||
, m_currentShader(nullptr) {
|
, m_currentShader(nullptr)
|
||||||
|
, m_composedFramebuffer(nullptr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
OpenGLCommandList::~OpenGLCommandList() {
|
OpenGLCommandList::~OpenGLCommandList() {
|
||||||
@@ -457,6 +458,7 @@ void OpenGLCommandList::PopDebugGroup() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLCommandList::Shutdown() {
|
void OpenGLCommandList::Shutdown() {
|
||||||
|
ReleaseComposedFramebuffer();
|
||||||
DisableConfiguredVertexAttributes();
|
DisableConfiguredVertexAttributes();
|
||||||
if (m_internalVAO != 0) {
|
if (m_internalVAO != 0) {
|
||||||
glDeleteVertexArrays(1, &m_internalVAO);
|
glDeleteVertexArrays(1, &m_internalVAO);
|
||||||
@@ -467,12 +469,21 @@ void OpenGLCommandList::Shutdown() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLCommandList::Reset() {
|
void OpenGLCommandList::Reset() {
|
||||||
|
ReleaseComposedFramebuffer();
|
||||||
m_currentPipelineState = nullptr;
|
m_currentPipelineState = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLCommandList::Close() {
|
void OpenGLCommandList::Close() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OpenGLCommandList::ReleaseComposedFramebuffer() {
|
||||||
|
if (m_composedFramebuffer != nullptr) {
|
||||||
|
m_composedFramebuffer->Shutdown();
|
||||||
|
delete m_composedFramebuffer;
|
||||||
|
m_composedFramebuffer = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void OpenGLCommandList::SetShader(RHIShader* shader) {
|
void OpenGLCommandList::SetShader(RHIShader* shader) {
|
||||||
m_currentShader = static_cast<OpenGLShader*>(shader);
|
m_currentShader = static_cast<OpenGLShader*>(shader);
|
||||||
if (m_currentShader) {
|
if (m_currentShader) {
|
||||||
@@ -593,29 +604,63 @@ void OpenGLCommandList::SetScissorRects(uint32_t count, const Rect* rects) {
|
|||||||
|
|
||||||
void OpenGLCommandList::SetRenderTargets(uint32_t count, RHIResourceView** renderTargets, RHIResourceView* depthStencil) {
|
void OpenGLCommandList::SetRenderTargets(uint32_t count, RHIResourceView** renderTargets, RHIResourceView* depthStencil) {
|
||||||
if (count > 0 && renderTargets != nullptr) {
|
if (count > 0 && renderTargets != nullptr) {
|
||||||
std::vector<GLuint> fbos(count);
|
const bool requiresComposedFramebuffer = count > 1 || depthStencil != nullptr;
|
||||||
for (uint32_t i = 0; i < count; ++i) {
|
std::vector<GLenum> drawBuffers(count, GL_NONE);
|
||||||
if (renderTargets[i]) {
|
|
||||||
OpenGLResourceView* view = static_cast<OpenGLResourceView*>(renderTargets[i]);
|
|
||||||
fbos[i] = view->GetFramebuffer();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[0]);
|
|
||||||
|
|
||||||
std::vector<GLenum> drawBuffers(count);
|
|
||||||
for (uint32_t i = 0; i < count; ++i) {
|
for (uint32_t i = 0; i < count; ++i) {
|
||||||
|
if (renderTargets[i] != nullptr) {
|
||||||
drawBuffers[i] = ToOpenGLColorAttachment(i);
|
drawBuffers[i] = ToOpenGLColorAttachment(i);
|
||||||
}
|
}
|
||||||
glDrawBuffers(count, drawBuffers.data());
|
}
|
||||||
|
|
||||||
|
if (requiresComposedFramebuffer) {
|
||||||
|
uint32_t width = 0;
|
||||||
|
uint32_t height = 0;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < count; ++i) {
|
||||||
|
auto* view = static_cast<OpenGLResourceView*>(renderTargets[i]);
|
||||||
|
const OpenGLTexture* texture = view != nullptr ? view->GetTextureResource() : nullptr;
|
||||||
|
if (texture != nullptr) {
|
||||||
|
width = texture->GetWidth();
|
||||||
|
height = texture->GetHeight();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((width == 0 || height == 0) && depthStencil != nullptr) {
|
||||||
|
auto* dsv = static_cast<OpenGLResourceView*>(depthStencil);
|
||||||
|
const OpenGLTexture* depthTexture = dsv != nullptr ? dsv->GetTextureResource() : nullptr;
|
||||||
|
if (depthTexture != nullptr) {
|
||||||
|
width = depthTexture->GetWidth();
|
||||||
|
height = depthTexture->GetHeight();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReleaseComposedFramebuffer();
|
||||||
|
m_composedFramebuffer = new OpenGLFramebuffer();
|
||||||
|
if (!m_composedFramebuffer->Initialize(nullptr, width, height, count, renderTargets, depthStencil)) {
|
||||||
|
ReleaseComposedFramebuffer();
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||||
|
glDrawBuffers(0, nullptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_composedFramebuffer->GetFramebuffer());
|
||||||
|
} else {
|
||||||
|
ReleaseComposedFramebuffer();
|
||||||
|
OpenGLResourceView* view = static_cast<OpenGLResourceView*>(renderTargets[0]);
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, view != nullptr ? view->GetFramebuffer() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
glDrawBuffers(count, drawBuffers.data());
|
||||||
} else if (depthStencil) {
|
} else if (depthStencil) {
|
||||||
|
ReleaseComposedFramebuffer();
|
||||||
OpenGLResourceView* dsv = static_cast<OpenGLResourceView*>(depthStencil);
|
OpenGLResourceView* dsv = static_cast<OpenGLResourceView*>(depthStencil);
|
||||||
if (dsv && dsv->IsValid()) {
|
if (dsv && dsv->IsValid()) {
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dsv->GetFramebuffer());
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dsv->GetFramebuffer());
|
||||||
}
|
}
|
||||||
glDrawBuffers(0, nullptr);
|
glDrawBuffers(0, nullptr);
|
||||||
} else {
|
} else {
|
||||||
|
ReleaseComposedFramebuffer();
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -84,6 +84,42 @@ OpenGLFormat ToOpenGLTextureFormat(Format format) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLenum ResolveFramebufferTextureTarget(OpenGLTextureType textureType, const ResourceViewDesc& desc) {
|
||||||
|
switch (textureType) {
|
||||||
|
case OpenGLTextureType::Texture1D:
|
||||||
|
return GL_TEXTURE_1D;
|
||||||
|
case OpenGLTextureType::Texture2D:
|
||||||
|
return GL_TEXTURE_2D;
|
||||||
|
case OpenGLTextureType::TextureCube: {
|
||||||
|
const uint32_t face = desc.firstArraySlice < 6 ? desc.firstArraySlice : 0;
|
||||||
|
return GL_TEXTURE_CUBE_MAP_POSITIVE_X + face;
|
||||||
|
}
|
||||||
|
case OpenGLTextureType::Texture2DArray:
|
||||||
|
case OpenGLTextureType::Texture3D:
|
||||||
|
case OpenGLTextureType::TextureCubeArray:
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
return GL_TEXTURE_2D;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int ResolveFramebufferAttachmentLayer(OpenGLTextureType textureType, const ResourceViewDesc& desc) {
|
||||||
|
switch (textureType) {
|
||||||
|
case OpenGLTextureType::Texture2DArray:
|
||||||
|
case OpenGLTextureType::Texture3D:
|
||||||
|
case OpenGLTextureType::TextureCubeArray:
|
||||||
|
return static_cast<int>(desc.firstArraySlice);
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FramebufferAttachmentType ResolveDepthAttachmentType(Format format) {
|
||||||
|
return format == Format::D24_UNorm_S8_UInt
|
||||||
|
? FramebufferAttachmentType::DepthStencil
|
||||||
|
: FramebufferAttachmentType::Depth;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
OpenGLDevice::OpenGLDevice()
|
OpenGLDevice::OpenGLDevice()
|
||||||
@@ -634,9 +670,11 @@ RHIResourceView* OpenGLDevice::CreateRenderTargetView(RHITexture* texture, const
|
|||||||
|
|
||||||
FramebufferAttachment colorAttachment = {};
|
FramebufferAttachment colorAttachment = {};
|
||||||
colorAttachment.texture = glTexture->GetID();
|
colorAttachment.texture = glTexture->GetID();
|
||||||
|
colorAttachment.target = ResolveFramebufferTextureTarget(glTexture->GetOpenGLType(), desc);
|
||||||
colorAttachment.mipLevel = static_cast<int>(desc.mipLevel);
|
colorAttachment.mipLevel = static_cast<int>(desc.mipLevel);
|
||||||
|
colorAttachment.layer = ResolveFramebufferAttachmentLayer(glTexture->GetOpenGLType(), desc);
|
||||||
colorAttachment.type = FramebufferAttachmentType::Color;
|
colorAttachment.type = FramebufferAttachmentType::Color;
|
||||||
colorAttachment.format = desc.format;
|
colorAttachment.format = desc.format != 0 ? desc.format : static_cast<uint32_t>(texture->GetFormat());
|
||||||
fbDesc.colorAttachments.push_back(colorAttachment);
|
fbDesc.colorAttachments.push_back(colorAttachment);
|
||||||
|
|
||||||
auto* framebuffer = new OpenGLFramebuffer();
|
auto* framebuffer = new OpenGLFramebuffer();
|
||||||
@@ -668,9 +706,11 @@ RHIResourceView* OpenGLDevice::CreateDepthStencilView(RHITexture* texture, const
|
|||||||
|
|
||||||
FramebufferAttachment depthAttachment = {};
|
FramebufferAttachment depthAttachment = {};
|
||||||
depthAttachment.texture = glTexture->GetID();
|
depthAttachment.texture = glTexture->GetID();
|
||||||
|
depthAttachment.target = ResolveFramebufferTextureTarget(glTexture->GetOpenGLType(), desc);
|
||||||
depthAttachment.mipLevel = static_cast<int>(desc.mipLevel);
|
depthAttachment.mipLevel = static_cast<int>(desc.mipLevel);
|
||||||
depthAttachment.type = FramebufferAttachmentType::DepthStencil;
|
depthAttachment.layer = ResolveFramebufferAttachmentLayer(glTexture->GetOpenGLType(), desc);
|
||||||
depthAttachment.format = desc.format;
|
depthAttachment.format = desc.format != 0 ? desc.format : static_cast<uint32_t>(texture->GetFormat());
|
||||||
|
depthAttachment.type = ResolveDepthAttachmentType(static_cast<Format>(depthAttachment.format));
|
||||||
fbDesc.depthAttachment = depthAttachment;
|
fbDesc.depthAttachment = depthAttachment;
|
||||||
|
|
||||||
auto* framebuffer = new OpenGLFramebuffer();
|
auto* framebuffer = new OpenGLFramebuffer();
|
||||||
|
|||||||
@@ -6,6 +6,38 @@
|
|||||||
namespace XCEngine {
|
namespace XCEngine {
|
||||||
namespace RHI {
|
namespace RHI {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
bool IsTexture2DAttachmentTarget(GLenum target) {
|
||||||
|
return target == GL_TEXTURE_2D ||
|
||||||
|
(target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AttachFramebufferTexture(GLenum attachmentPoint, const FramebufferAttachment& attachment) {
|
||||||
|
if (attachment.texture == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attachment.layer >= 0) {
|
||||||
|
glFramebufferTextureLayer(GL_FRAMEBUFFER, attachmentPoint, attachment.texture, attachment.mipLevel, attachment.layer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attachment.target == GL_TEXTURE_1D) {
|
||||||
|
glFramebufferTexture1D(GL_FRAMEBUFFER, attachmentPoint, GL_TEXTURE_1D, attachment.texture, attachment.mipLevel);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsTexture2DAttachmentTarget(attachment.target)) {
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint, attachment.target, attachment.texture, attachment.mipLevel);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
glFramebufferTexture(GL_FRAMEBUFFER, attachmentPoint, attachment.texture, attachment.mipLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
OpenGLFramebuffer::OpenGLFramebuffer()
|
OpenGLFramebuffer::OpenGLFramebuffer()
|
||||||
: m_framebuffer(0)
|
: m_framebuffer(0)
|
||||||
, m_width(0)
|
, m_width(0)
|
||||||
@@ -32,45 +64,23 @@ bool OpenGLFramebuffer::Initialize(const FramebufferDesc& desc) {
|
|||||||
for (size_t i = 0; i < desc.colorAttachments.size() && i < 16; ++i) {
|
for (size_t i = 0; i < desc.colorAttachments.size() && i < 16; ++i) {
|
||||||
const auto& attachment = desc.colorAttachments[i];
|
const auto& attachment = desc.colorAttachments[i];
|
||||||
GLenum glAttachment = ToOpenGLColorAttachment(static_cast<uint32_t>(i));
|
GLenum glAttachment = ToOpenGLColorAttachment(static_cast<uint32_t>(i));
|
||||||
|
AttachFramebufferTexture(glAttachment, attachment);
|
||||||
switch (attachment.type) {
|
|
||||||
case FramebufferAttachmentType::Color:
|
|
||||||
if (attachment.layer == 0 && attachment.mipLevel == 0) {
|
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, glAttachment, GL_TEXTURE_2D, attachment.texture, 0);
|
|
||||||
} else if (attachment.layer > 0) {
|
|
||||||
glFramebufferTextureLayer(GL_FRAMEBUFFER, glAttachment, attachment.texture, attachment.mipLevel, attachment.layer);
|
|
||||||
} else {
|
|
||||||
glFramebufferTexture(GL_FRAMEBUFFER, glAttachment, attachment.texture, attachment.mipLevel);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
drawBuffers[drawBufferCount++] = glAttachment;
|
drawBuffers[drawBufferCount++] = glAttachment;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (desc.depthAttachment.texture != 0) {
|
if (desc.depthAttachment.texture != 0) {
|
||||||
GLenum depthAttachment = ToOpenGLDepthAttachment();
|
GLenum depthAttachment = ToOpenGLDepthAttachment();
|
||||||
if (desc.stencilAttachment.texture != 0) {
|
if (desc.depthAttachment.type == FramebufferAttachmentType::DepthStencil || desc.stencilAttachment.texture != 0) {
|
||||||
depthAttachment = ToOpenGLDepthStencilAttachment();
|
depthAttachment = ToOpenGLDepthStencilAttachment();
|
||||||
}
|
}
|
||||||
|
AttachFramebufferTexture(depthAttachment, desc.depthAttachment);
|
||||||
if (desc.depthAttachment.layer == 0 && desc.depthAttachment.mipLevel == 0) {
|
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, depthAttachment, GL_TEXTURE_2D, desc.depthAttachment.texture, 0);
|
|
||||||
} else if (desc.depthAttachment.layer > 0) {
|
|
||||||
glFramebufferTextureLayer(GL_FRAMEBUFFER, depthAttachment, desc.depthAttachment.texture, desc.depthAttachment.mipLevel, desc.depthAttachment.layer);
|
|
||||||
} else {
|
|
||||||
glFramebufferTexture(GL_FRAMEBUFFER, depthAttachment, desc.depthAttachment.texture, desc.depthAttachment.mipLevel);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (desc.stencilAttachment.texture != 0 && desc.stencilAttachment.texture != desc.depthAttachment.texture) {
|
if (desc.stencilAttachment.texture != 0 &&
|
||||||
|
(desc.stencilAttachment.texture != desc.depthAttachment.texture ||
|
||||||
|
desc.depthAttachment.type != FramebufferAttachmentType::DepthStencil)) {
|
||||||
GLenum stencilAttachment = ToOpenGLStencilAttachment();
|
GLenum stencilAttachment = ToOpenGLStencilAttachment();
|
||||||
if (desc.stencilAttachment.layer == 0 && desc.stencilAttachment.mipLevel == 0) {
|
AttachFramebufferTexture(stencilAttachment, desc.stencilAttachment);
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, stencilAttachment, GL_TEXTURE_2D, desc.stencilAttachment.texture, 0);
|
|
||||||
} else if (desc.stencilAttachment.layer > 0) {
|
|
||||||
glFramebufferTextureLayer(GL_FRAMEBUFFER, stencilAttachment, desc.stencilAttachment.texture, desc.stencilAttachment.mipLevel, desc.stencilAttachment.layer);
|
|
||||||
} else {
|
|
||||||
glFramebufferTexture(GL_FRAMEBUFFER, stencilAttachment, desc.stencilAttachment.texture, desc.stencilAttachment.mipLevel);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (drawBufferCount > 0) {
|
if (drawBufferCount > 0) {
|
||||||
@@ -118,9 +128,9 @@ bool OpenGLFramebuffer::Initialize(class RHIRenderPass* renderPass, uint32_t wid
|
|||||||
if (colorAttachments[i]) {
|
if (colorAttachments[i]) {
|
||||||
OpenGLResourceView* view = static_cast<OpenGLResourceView*>(colorAttachments[i]);
|
OpenGLResourceView* view = static_cast<OpenGLResourceView*>(colorAttachments[i]);
|
||||||
GLenum glAttachment = ToOpenGLColorAttachment(i);
|
GLenum glAttachment = ToOpenGLColorAttachment(i);
|
||||||
unsigned int texture = view->GetTexture();
|
const auto& attachment = view->GetFramebufferAttachment();
|
||||||
if (texture) {
|
if (attachment.texture != 0) {
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, glAttachment, GL_TEXTURE_2D, texture, 0);
|
AttachFramebufferTexture(glAttachment, attachment);
|
||||||
}
|
}
|
||||||
drawBuffers[drawBufferCount++] = glAttachment;
|
drawBuffers[drawBufferCount++] = glAttachment;
|
||||||
}
|
}
|
||||||
@@ -128,9 +138,13 @@ bool OpenGLFramebuffer::Initialize(class RHIRenderPass* renderPass, uint32_t wid
|
|||||||
|
|
||||||
if (depthStencilAttachment) {
|
if (depthStencilAttachment) {
|
||||||
OpenGLResourceView* view = static_cast<OpenGLResourceView*>(depthStencilAttachment);
|
OpenGLResourceView* view = static_cast<OpenGLResourceView*>(depthStencilAttachment);
|
||||||
unsigned int texture = view->GetTexture();
|
const auto& attachment = view->GetFramebufferAttachment();
|
||||||
if (texture) {
|
if (attachment.texture != 0) {
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, ToOpenGLDepthStencilAttachment(), GL_TEXTURE_2D, texture, 0);
|
const GLenum depthAttachment =
|
||||||
|
attachment.type == FramebufferAttachmentType::DepthStencil
|
||||||
|
? ToOpenGLDepthStencilAttachment()
|
||||||
|
: ToOpenGLDepthAttachment();
|
||||||
|
AttachFramebufferTexture(depthAttachment, attachment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,53 @@
|
|||||||
namespace XCEngine {
|
namespace XCEngine {
|
||||||
namespace RHI {
|
namespace RHI {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
GLenum ResolveFramebufferTextureTarget(OpenGLTextureType textureType, const ResourceViewDesc& desc) {
|
||||||
|
switch (textureType) {
|
||||||
|
case OpenGLTextureType::Texture1D:
|
||||||
|
return GL_TEXTURE_1D;
|
||||||
|
case OpenGLTextureType::Texture2D:
|
||||||
|
return GL_TEXTURE_2D;
|
||||||
|
case OpenGLTextureType::TextureCube: {
|
||||||
|
const uint32_t face = desc.firstArraySlice < 6 ? desc.firstArraySlice : 0;
|
||||||
|
return GL_TEXTURE_CUBE_MAP_POSITIVE_X + face;
|
||||||
|
}
|
||||||
|
case OpenGLTextureType::Texture2DArray:
|
||||||
|
case OpenGLTextureType::Texture3D:
|
||||||
|
case OpenGLTextureType::TextureCubeArray:
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
return GL_TEXTURE_2D;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int ResolveFramebufferAttachmentLayer(OpenGLTextureType textureType, const ResourceViewDesc& desc) {
|
||||||
|
switch (textureType) {
|
||||||
|
case OpenGLTextureType::Texture2DArray:
|
||||||
|
case OpenGLTextureType::Texture3D:
|
||||||
|
case OpenGLTextureType::TextureCubeArray:
|
||||||
|
return static_cast<int>(desc.firstArraySlice);
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Format ResolveViewFormat(OpenGLTexture* texture, const ResourceViewDesc& desc) {
|
||||||
|
if (desc.format != 0) {
|
||||||
|
return static_cast<Format>(desc.format);
|
||||||
|
}
|
||||||
|
return texture ? texture->GetFormat() : Format::Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
FramebufferAttachmentType ResolveDepthAttachmentType(Format format) {
|
||||||
|
return format == Format::D24_UNorm_S8_UInt
|
||||||
|
? FramebufferAttachmentType::DepthStencil
|
||||||
|
: FramebufferAttachmentType::Depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
OpenGLResourceView::OpenGLResourceView()
|
OpenGLResourceView::OpenGLResourceView()
|
||||||
: m_viewType(ResourceViewType::RenderTarget)
|
: m_viewType(ResourceViewType::RenderTarget)
|
||||||
, m_format(Format::Unknown)
|
, m_format(Format::Unknown)
|
||||||
@@ -47,6 +94,7 @@ void OpenGLResourceView::Shutdown() {
|
|||||||
m_framebuffer = nullptr;
|
m_framebuffer = nullptr;
|
||||||
m_textureUnitAllocator = nullptr;
|
m_textureUnitAllocator = nullptr;
|
||||||
m_uniformBufferManager = nullptr;
|
m_uniformBufferManager = nullptr;
|
||||||
|
m_framebufferAttachment = {};
|
||||||
m_framebufferID = 0;
|
m_framebufferID = 0;
|
||||||
m_texture = nullptr;
|
m_texture = nullptr;
|
||||||
m_buffer = nullptr;
|
m_buffer = nullptr;
|
||||||
@@ -101,11 +149,17 @@ bool OpenGLResourceView::InitializeAsRenderTarget(
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_viewType = ResourceViewType::RenderTarget;
|
m_viewType = ResourceViewType::RenderTarget;
|
||||||
m_format = static_cast<Format>(desc.format);
|
m_format = ResolveViewFormat(texture, desc);
|
||||||
m_dimension = desc.dimension;
|
m_dimension = desc.dimension;
|
||||||
m_texture = texture;
|
m_texture = texture;
|
||||||
m_framebuffer = framebuffer;
|
m_framebuffer = framebuffer;
|
||||||
m_framebufferID = framebuffer->GetFramebuffer();
|
m_framebufferID = framebuffer->GetFramebuffer();
|
||||||
|
m_framebufferAttachment.texture = texture->GetID();
|
||||||
|
m_framebufferAttachment.target = ResolveFramebufferTextureTarget(texture->GetOpenGLType(), desc);
|
||||||
|
m_framebufferAttachment.mipLevel = static_cast<int>(desc.mipLevel);
|
||||||
|
m_framebufferAttachment.layer = ResolveFramebufferAttachmentLayer(texture->GetOpenGLType(), desc);
|
||||||
|
m_framebufferAttachment.type = FramebufferAttachmentType::Color;
|
||||||
|
m_framebufferAttachment.format = static_cast<uint32_t>(m_format);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,11 +172,17 @@ bool OpenGLResourceView::InitializeAsDepthStencil(
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_viewType = ResourceViewType::DepthStencil;
|
m_viewType = ResourceViewType::DepthStencil;
|
||||||
m_format = static_cast<Format>(desc.format);
|
m_format = ResolveViewFormat(texture, desc);
|
||||||
m_dimension = desc.dimension;
|
m_dimension = desc.dimension;
|
||||||
m_texture = texture;
|
m_texture = texture;
|
||||||
m_framebuffer = framebuffer;
|
m_framebuffer = framebuffer;
|
||||||
m_framebufferID = framebuffer->GetFramebuffer();
|
m_framebufferID = framebuffer->GetFramebuffer();
|
||||||
|
m_framebufferAttachment.texture = texture->GetID();
|
||||||
|
m_framebufferAttachment.target = ResolveFramebufferTextureTarget(texture->GetOpenGLType(), desc);
|
||||||
|
m_framebufferAttachment.mipLevel = static_cast<int>(desc.mipLevel);
|
||||||
|
m_framebufferAttachment.layer = ResolveFramebufferAttachmentLayer(texture->GetOpenGLType(), desc);
|
||||||
|
m_framebufferAttachment.type = ResolveDepthAttachmentType(m_format);
|
||||||
|
m_framebufferAttachment.format = static_cast<uint32_t>(m_format);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,7 +195,7 @@ bool OpenGLResourceView::InitializeAsShaderResource(
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_viewType = ResourceViewType::ShaderResource;
|
m_viewType = ResourceViewType::ShaderResource;
|
||||||
m_format = static_cast<Format>(desc.format);
|
m_format = ResolveViewFormat(texture, desc);
|
||||||
m_dimension = desc.dimension;
|
m_dimension = desc.dimension;
|
||||||
m_texture = texture;
|
m_texture = texture;
|
||||||
m_textureUnit = -1;
|
m_textureUnit = -1;
|
||||||
@@ -157,7 +217,7 @@ bool OpenGLResourceView::InitializeAsUnorderedAccess(
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_viewType = ResourceViewType::UnorderedAccess;
|
m_viewType = ResourceViewType::UnorderedAccess;
|
||||||
m_format = static_cast<Format>(desc.format);
|
m_format = ResolveViewFormat(texture, desc);
|
||||||
m_dimension = desc.dimension;
|
m_dimension = desc.dimension;
|
||||||
m_texture = texture;
|
m_texture = texture;
|
||||||
m_textureUnit = unit;
|
m_textureUnit = unit;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include "XCEngine/RHI/RHIRenderPass.h"
|
#include "XCEngine/RHI/RHIRenderPass.h"
|
||||||
#include "XCEngine/RHI/RHIFramebuffer.h"
|
#include "XCEngine/RHI/RHIFramebuffer.h"
|
||||||
#include "XCEngine/RHI/OpenGL/OpenGLDevice.h"
|
#include "XCEngine/RHI/OpenGL/OpenGLDevice.h"
|
||||||
|
#include "XCEngine/RHI/OpenGL/OpenGLResourceView.h"
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
|
|
||||||
using namespace XCEngine::RHI;
|
using namespace XCEngine::RHI;
|
||||||
@@ -363,6 +364,145 @@ TEST_P(RHITestFixture, CommandList_SetRenderTargets_WithRealViews) {
|
|||||||
delete texture;
|
delete texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_P(RHITestFixture, CommandList_SetRenderTargets_BindsColorAndDepthAttachmentsOnOpenGL) {
|
||||||
|
if (GetBackendType() != RHIType::OpenGL) {
|
||||||
|
GTEST_SKIP() << "OpenGL-specific framebuffer attachment verification";
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureDesc colorDesc = {};
|
||||||
|
colorDesc.width = 128;
|
||||||
|
colorDesc.height = 128;
|
||||||
|
colorDesc.format = static_cast<uint32_t>(Format::R8G8B8A8_UNorm);
|
||||||
|
colorDesc.textureType = static_cast<uint32_t>(TextureType::Texture2D);
|
||||||
|
|
||||||
|
TextureDesc depthDesc = {};
|
||||||
|
depthDesc.width = 128;
|
||||||
|
depthDesc.height = 128;
|
||||||
|
depthDesc.format = static_cast<uint32_t>(Format::D24_UNorm_S8_UInt);
|
||||||
|
depthDesc.textureType = static_cast<uint32_t>(TextureType::Texture2D);
|
||||||
|
|
||||||
|
RHITexture* colorTexture = GetDevice()->CreateTexture(colorDesc);
|
||||||
|
RHITexture* depthTexture = GetDevice()->CreateTexture(depthDesc);
|
||||||
|
ASSERT_NE(colorTexture, nullptr);
|
||||||
|
ASSERT_NE(depthTexture, nullptr);
|
||||||
|
|
||||||
|
ResourceViewDesc colorViewDesc = {};
|
||||||
|
colorViewDesc.format = colorDesc.format;
|
||||||
|
RHIResourceView* rtv = GetDevice()->CreateRenderTargetView(colorTexture, colorViewDesc);
|
||||||
|
|
||||||
|
ResourceViewDesc depthViewDesc = {};
|
||||||
|
depthViewDesc.format = depthDesc.format;
|
||||||
|
RHIResourceView* dsv = GetDevice()->CreateDepthStencilView(depthTexture, depthViewDesc);
|
||||||
|
ASSERT_NE(rtv, nullptr);
|
||||||
|
ASSERT_NE(dsv, nullptr);
|
||||||
|
|
||||||
|
CommandListDesc cmdDesc = {};
|
||||||
|
cmdDesc.commandListType = static_cast<uint32_t>(CommandQueueType::Direct);
|
||||||
|
RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc);
|
||||||
|
ASSERT_NE(cmdList, nullptr);
|
||||||
|
|
||||||
|
cmdList->Reset();
|
||||||
|
cmdList->SetRenderTargets(1, &rtv, dsv);
|
||||||
|
|
||||||
|
GLint framebuffer = 0;
|
||||||
|
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &framebuffer);
|
||||||
|
EXPECT_NE(framebuffer, 0);
|
||||||
|
EXPECT_EQ(glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER), GL_FRAMEBUFFER_COMPLETE);
|
||||||
|
|
||||||
|
GLint colorAttachment = 0;
|
||||||
|
glGetFramebufferAttachmentParameteriv(
|
||||||
|
GL_DRAW_FRAMEBUFFER,
|
||||||
|
GL_COLOR_ATTACHMENT0,
|
||||||
|
GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
|
||||||
|
&colorAttachment);
|
||||||
|
EXPECT_EQ(static_cast<GLuint>(colorAttachment), static_cast<OpenGLResourceView*>(rtv)->GetTexture());
|
||||||
|
|
||||||
|
GLint depthAttachment = 0;
|
||||||
|
glGetFramebufferAttachmentParameteriv(
|
||||||
|
GL_DRAW_FRAMEBUFFER,
|
||||||
|
GL_DEPTH_ATTACHMENT,
|
||||||
|
GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
|
||||||
|
&depthAttachment);
|
||||||
|
EXPECT_EQ(static_cast<GLuint>(depthAttachment), static_cast<OpenGLResourceView*>(dsv)->GetTexture());
|
||||||
|
|
||||||
|
cmdList->Close();
|
||||||
|
|
||||||
|
cmdList->Shutdown();
|
||||||
|
delete cmdList;
|
||||||
|
delete dsv;
|
||||||
|
delete rtv;
|
||||||
|
depthTexture->Shutdown();
|
||||||
|
delete depthTexture;
|
||||||
|
colorTexture->Shutdown();
|
||||||
|
delete colorTexture;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_P(RHITestFixture, CommandList_SetRenderTargets_BindsMultipleColorAttachmentsOnOpenGL) {
|
||||||
|
if (GetBackendType() != RHIType::OpenGL) {
|
||||||
|
GTEST_SKIP() << "OpenGL-specific multiple render target verification";
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureDesc texDesc = {};
|
||||||
|
texDesc.width = 128;
|
||||||
|
texDesc.height = 128;
|
||||||
|
texDesc.format = static_cast<uint32_t>(Format::R8G8B8A8_UNorm);
|
||||||
|
texDesc.textureType = static_cast<uint32_t>(TextureType::Texture2D);
|
||||||
|
|
||||||
|
RHITexture* texture0 = GetDevice()->CreateTexture(texDesc);
|
||||||
|
RHITexture* texture1 = GetDevice()->CreateTexture(texDesc);
|
||||||
|
ASSERT_NE(texture0, nullptr);
|
||||||
|
ASSERT_NE(texture1, nullptr);
|
||||||
|
|
||||||
|
ResourceViewDesc viewDesc = {};
|
||||||
|
viewDesc.format = texDesc.format;
|
||||||
|
RHIResourceView* rtv0 = GetDevice()->CreateRenderTargetView(texture0, viewDesc);
|
||||||
|
RHIResourceView* rtv1 = GetDevice()->CreateRenderTargetView(texture1, viewDesc);
|
||||||
|
ASSERT_NE(rtv0, nullptr);
|
||||||
|
ASSERT_NE(rtv1, nullptr);
|
||||||
|
|
||||||
|
RHIResourceView* rtvs[] = { rtv0, rtv1 };
|
||||||
|
|
||||||
|
CommandListDesc cmdDesc = {};
|
||||||
|
cmdDesc.commandListType = static_cast<uint32_t>(CommandQueueType::Direct);
|
||||||
|
RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc);
|
||||||
|
ASSERT_NE(cmdList, nullptr);
|
||||||
|
|
||||||
|
cmdList->Reset();
|
||||||
|
cmdList->SetRenderTargets(2, rtvs, nullptr);
|
||||||
|
|
||||||
|
GLint framebuffer = 0;
|
||||||
|
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &framebuffer);
|
||||||
|
EXPECT_NE(framebuffer, 0);
|
||||||
|
EXPECT_EQ(glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER), GL_FRAMEBUFFER_COMPLETE);
|
||||||
|
|
||||||
|
GLint colorAttachment0 = 0;
|
||||||
|
glGetFramebufferAttachmentParameteriv(
|
||||||
|
GL_DRAW_FRAMEBUFFER,
|
||||||
|
GL_COLOR_ATTACHMENT0,
|
||||||
|
GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
|
||||||
|
&colorAttachment0);
|
||||||
|
EXPECT_EQ(static_cast<GLuint>(colorAttachment0), static_cast<OpenGLResourceView*>(rtv0)->GetTexture());
|
||||||
|
|
||||||
|
GLint colorAttachment1 = 0;
|
||||||
|
glGetFramebufferAttachmentParameteriv(
|
||||||
|
GL_DRAW_FRAMEBUFFER,
|
||||||
|
GL_COLOR_ATTACHMENT1,
|
||||||
|
GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
|
||||||
|
&colorAttachment1);
|
||||||
|
EXPECT_EQ(static_cast<GLuint>(colorAttachment1), static_cast<OpenGLResourceView*>(rtv1)->GetTexture());
|
||||||
|
|
||||||
|
cmdList->Close();
|
||||||
|
|
||||||
|
cmdList->Shutdown();
|
||||||
|
delete cmdList;
|
||||||
|
delete rtv1;
|
||||||
|
delete rtv0;
|
||||||
|
texture1->Shutdown();
|
||||||
|
delete texture1;
|
||||||
|
texture0->Shutdown();
|
||||||
|
delete texture0;
|
||||||
|
}
|
||||||
|
|
||||||
TEST_P(RHITestFixture, CommandList_CopyResource_WithRealResources) {
|
TEST_P(RHITestFixture, CommandList_CopyResource_WithRealResources) {
|
||||||
TextureDesc texDesc = {};
|
TextureDesc texDesc = {};
|
||||||
texDesc.width = 256;
|
texDesc.width = 256;
|
||||||
|
|||||||
Reference in New Issue
Block a user