From c188d0616a628b25c11d81cdd8d60607c6d1dc90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Tue, 22 Jun 2021 17:26:40 +0200 Subject: [PATCH] OpenGLRenderer: Implement AttachmentLoadOp::Discard using glInvalidateFramebuffer --- .../OpenGLRenderer/Wrapper/CoreFunctions.hpp | 1 + .../OpenGLRenderer/OpenGLCommandBuffer.cpp | 28 +++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/include/Nazara/OpenGLRenderer/Wrapper/CoreFunctions.hpp b/include/Nazara/OpenGLRenderer/Wrapper/CoreFunctions.hpp index 34eab95bd..cf056f750 100644 --- a/include/Nazara/OpenGLRenderer/Wrapper/CoreFunctions.hpp +++ b/include/Nazara/OpenGLRenderer/Wrapper/CoreFunctions.hpp @@ -115,6 +115,7 @@ typedef void (GL_APIENTRYP PFNGLSPECIALIZESHADERARBPROC) (GLuint shader, const G cb(glGetUniformiv, PFNGLGETUNIFORMIVPROC) \ cb(glGetUniformBlockIndex, PFNGLGETUNIFORMBLOCKINDEXPROC) \ cb(glIsEnabled, PFNGLISENABLEDPROC) \ + cb(glInvalidateFramebuffer, PFNGLINVALIDATEFRAMEBUFFERPROC) \ cb(glLineWidth, PFNGLLINEWIDTHPROC) \ cb(glLinkProgram, PFNGLLINKPROGRAMPROC) \ cb(glMapBufferRange, PFNGLMAPBUFFERRANGEPROC) \ diff --git a/src/Nazara/OpenGLRenderer/OpenGLCommandBuffer.cpp b/src/Nazara/OpenGLRenderer/OpenGLCommandBuffer.cpp index 226ebc6eb..eea14288c 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLCommandBuffer.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLCommandBuffer.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -141,10 +142,14 @@ namespace Nz } } + StackVector invalidateAttachments = NazaraStackVector(GLenum, colorBufferCount + 1); + if (command.framebuffer->GetType() == OpenGLFramebuffer::Type::FBO) { context->glDrawBuffers(GLsizei(colorBufferCount), fboDrawBuffers.data()); + invalidateAttachments = NazaraStackVector(GLenum, colorBufferCount + 1); + for (std::size_t i = 0; i < colorBufferCount; ++i) { std::size_t attachmentIndex = colorIndexes[i]; @@ -158,6 +163,8 @@ namespace Nz context->ResetColorWriteMasks(); context->glClearBufferfv(GL_COLOR, GLint(i), clearColor.data()); } + else if (attachmentInfo.loadOp == AttachmentLoadOp::Discard) + invalidateAttachments.push_back(GL_COLOR_ATTACHMENT0 + i); } if (depthStencilIndex) @@ -176,19 +183,31 @@ namespace Nz { context->ResetDepthWriteMasks(); context->glClearBufferfv(GL_DEPTH, 0, &clearValues.depth); + + if (depthStencilAttachment.stencilLoadOp == AttachmentLoadOp::Discard) + invalidateAttachments.push_back(GL_STENCIL_ATTACHMENT); } else if (depthStencilAttachment.stencilLoadOp == AttachmentLoadOp::Clear) { context->ResetStencilWriteMasks(); 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 { + assert(command.framebuffer->GetType() == FramebufferType::Window); + GLenum buffer = GL_BACK; context->glDrawBuffers(1, &buffer); + invalidateAttachments = NazaraStackVector(GLenum, 3); //< color + depth + stencil + if (colorIndex > 0) { std::size_t colorBufferCount = command.framebuffer->GetColorBufferCount(); @@ -206,6 +225,8 @@ namespace Nz clearFields |= GL_COLOR_BUFFER_BIT; } + else if (colorAttachment.loadOp == AttachmentLoadOp::Discard) + invalidateAttachments.push_back(GL_COLOR); } if (depthStencilIndex) @@ -220,6 +241,8 @@ namespace Nz context->glClearDepthf(clearValues.depth); 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) { @@ -227,11 +250,16 @@ namespace Nz context->glClearStencil(clearValues.stencil); clearFields |= GL_STENCIL_BUFFER_BIT; } + else if (depthStencilAttachment.stencilLoadOp == AttachmentLoadOp::Discard) + invalidateAttachments.push_back(GL_STENCIL); } if (clearFields) context->glClear(clearFields); } + + if (!invalidateAttachments.empty()) + context->glInvalidateFramebuffer(GL_FRAMEBUFFER, GLsizei(invalidateAttachments.size()), invalidateAttachments.data()); } else static_assert(AlwaysFalse::value, "non-exhaustive visitor");