OpenGLRenderer: Implement AttachmentLoadOp::Discard using glInvalidateFramebuffer

This commit is contained in:
Jérôme Leclercq 2021-06-22 17:26:40 +02:00
parent d2892b47e7
commit c188d0616a
2 changed files with 29 additions and 0 deletions

View File

@ -115,6 +115,7 @@ typedef void (GL_APIENTRYP PFNGLSPECIALIZESHADERARBPROC) (GLuint shader, const G
cb(glGetUniformiv, PFNGLGETUNIFORMIVPROC) \ cb(glGetUniformiv, PFNGLGETUNIFORMIVPROC) \
cb(glGetUniformBlockIndex, PFNGLGETUNIFORMBLOCKINDEXPROC) \ cb(glGetUniformBlockIndex, PFNGLGETUNIFORMBLOCKINDEXPROC) \
cb(glIsEnabled, PFNGLISENABLEDPROC) \ cb(glIsEnabled, PFNGLISENABLEDPROC) \
cb(glInvalidateFramebuffer, PFNGLINVALIDATEFRAMEBUFFERPROC) \
cb(glLineWidth, PFNGLLINEWIDTHPROC) \ cb(glLineWidth, PFNGLLINEWIDTHPROC) \
cb(glLinkProgram, PFNGLLINKPROGRAMPROC) \ cb(glLinkProgram, PFNGLLINKPROGRAMPROC) \
cb(glMapBufferRange, PFNGLMAPBUFFERRANGEPROC) \ cb(glMapBufferRange, PFNGLMAPBUFFERRANGEPROC) \

View File

@ -4,6 +4,7 @@
#include <Nazara/OpenGLRenderer/OpenGLCommandBuffer.hpp> #include <Nazara/OpenGLRenderer/OpenGLCommandBuffer.hpp>
#include <Nazara/Core/StackArray.hpp> #include <Nazara/Core/StackArray.hpp>
#include <Nazara/Core/StackVector.hpp>
#include <Nazara/OpenGLRenderer/OpenGLCommandPool.hpp> #include <Nazara/OpenGLRenderer/OpenGLCommandPool.hpp>
#include <Nazara/OpenGLRenderer/OpenGLRenderPass.hpp> #include <Nazara/OpenGLRenderer/OpenGLRenderPass.hpp>
#include <Nazara/OpenGLRenderer/OpenGLRenderPipelineLayout.hpp> #include <Nazara/OpenGLRenderer/OpenGLRenderPipelineLayout.hpp>
@ -141,10 +142,14 @@ namespace Nz
} }
} }
StackVector<GLenum> invalidateAttachments = NazaraStackVector(GLenum, colorBufferCount + 1);
if (command.framebuffer->GetType() == OpenGLFramebuffer::Type::FBO) if (command.framebuffer->GetType() == OpenGLFramebuffer::Type::FBO)
{ {
context->glDrawBuffers(GLsizei(colorBufferCount), fboDrawBuffers.data()); context->glDrawBuffers(GLsizei(colorBufferCount), fboDrawBuffers.data());
invalidateAttachments = NazaraStackVector(GLenum, colorBufferCount + 1);
for (std::size_t i = 0; i < colorBufferCount; ++i) for (std::size_t i = 0; i < colorBufferCount; ++i)
{ {
std::size_t attachmentIndex = colorIndexes[i]; std::size_t attachmentIndex = colorIndexes[i];
@ -158,6 +163,8 @@ namespace Nz
context->ResetColorWriteMasks(); context->ResetColorWriteMasks();
context->glClearBufferfv(GL_COLOR, GLint(i), clearColor.data()); context->glClearBufferfv(GL_COLOR, GLint(i), clearColor.data());
} }
else if (attachmentInfo.loadOp == AttachmentLoadOp::Discard)
invalidateAttachments.push_back(GL_COLOR_ATTACHMENT0 + i);
} }
if (depthStencilIndex) if (depthStencilIndex)
@ -176,19 +183,31 @@ namespace Nz
{ {
context->ResetDepthWriteMasks(); context->ResetDepthWriteMasks();
context->glClearBufferfv(GL_DEPTH, 0, &clearValues.depth); context->glClearBufferfv(GL_DEPTH, 0, &clearValues.depth);
if (depthStencilAttachment.stencilLoadOp == AttachmentLoadOp::Discard)
invalidateAttachments.push_back(GL_STENCIL_ATTACHMENT);
} }
else if (depthStencilAttachment.stencilLoadOp == AttachmentLoadOp::Clear) else if (depthStencilAttachment.stencilLoadOp == AttachmentLoadOp::Clear)
{ {
context->ResetStencilWriteMasks(); context->ResetStencilWriteMasks();
context->glClearBufferuiv(GL_STENCIL, 0, &clearValues.stencil); context->glClearBufferuiv(GL_STENCIL, 0, &clearValues.stencil);
if (depthStencilAttachment.loadOp == AttachmentLoadOp::Discard)
invalidateAttachments.push_back(GL_DEPTH_ATTACHMENT);
} }
else if (depthStencilAttachment.loadOp == AttachmentLoadOp::Discard && depthStencilAttachment.stencilLoadOp == AttachmentLoadOp::Discard)
invalidateAttachments.push_back(GL_DEPTH_STENCIL_ATTACHMENT);
} }
} }
else else
{ {
assert(command.framebuffer->GetType() == FramebufferType::Window);
GLenum buffer = GL_BACK; GLenum buffer = GL_BACK;
context->glDrawBuffers(1, &buffer); context->glDrawBuffers(1, &buffer);
invalidateAttachments = NazaraStackVector(GLenum, 3); //< color + depth + stencil
if (colorIndex > 0) if (colorIndex > 0)
{ {
std::size_t colorBufferCount = command.framebuffer->GetColorBufferCount(); std::size_t colorBufferCount = command.framebuffer->GetColorBufferCount();
@ -206,6 +225,8 @@ namespace Nz
clearFields |= GL_COLOR_BUFFER_BIT; clearFields |= GL_COLOR_BUFFER_BIT;
} }
else if (colorAttachment.loadOp == AttachmentLoadOp::Discard)
invalidateAttachments.push_back(GL_COLOR);
} }
if (depthStencilIndex) if (depthStencilIndex)
@ -220,6 +241,8 @@ namespace Nz
context->glClearDepthf(clearValues.depth); context->glClearDepthf(clearValues.depth);
clearFields |= GL_DEPTH_BUFFER_BIT; clearFields |= GL_DEPTH_BUFFER_BIT;
} }
else if (depthStencilAttachment.loadOp == AttachmentLoadOp::Discard)
invalidateAttachments.push_back(GL_DEPTH);
if (depthStencilAttachment.stencilLoadOp == AttachmentLoadOp::Clear && PixelFormatInfo::GetContent(depthStencilAttachment.format) == PixelFormatContent::DepthStencil) if (depthStencilAttachment.stencilLoadOp == AttachmentLoadOp::Clear && PixelFormatInfo::GetContent(depthStencilAttachment.format) == PixelFormatContent::DepthStencil)
{ {
@ -227,11 +250,16 @@ namespace Nz
context->glClearStencil(clearValues.stencil); context->glClearStencil(clearValues.stencil);
clearFields |= GL_STENCIL_BUFFER_BIT; clearFields |= GL_STENCIL_BUFFER_BIT;
} }
else if (depthStencilAttachment.stencilLoadOp == AttachmentLoadOp::Discard)
invalidateAttachments.push_back(GL_STENCIL);
} }
if (clearFields) if (clearFields)
context->glClear(clearFields); context->glClear(clearFields);
} }
if (!invalidateAttachments.empty())
context->glInvalidateFramebuffer(GL_FRAMEBUFFER, GLsizei(invalidateAttachments.size()), invalidateAttachments.data());
} }
else else
static_assert(AlwaysFalse<T>::value, "non-exhaustive visitor"); static_assert(AlwaysFalse<T>::value, "non-exhaustive visitor");