From 7f69c9a0cc400e118a046e1e5b916ee25ced146e Mon Sep 17 00:00:00 2001 From: assiduous Date: Wed, 19 Aug 2020 23:31:00 -0700 Subject: GL backend: implemented render passes attachment invalidation with glInvalidateFramebuffer --- .../src/DeviceContextGLImpl.cpp | 80 ++++++++++++++++++++-- 1 file changed, 75 insertions(+), 5 deletions(-) (limited to 'Graphics/GraphicsEngineOpenGL') diff --git a/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp index 1b7b6891..cf655a01 100644 --- a/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include "SwapChainGL.h" #include "DeviceContextGLImpl.hpp" @@ -498,13 +499,20 @@ void DeviceContextGLImpl::EndSubpass() const auto& RPDesc = m_pActiveRenderPass->GetDesc(); VERIFY_EXPR(m_SubpassIndex < RPDesc.SubpassCount); const auto& SubpassDesc = RPDesc.pSubpasses[m_SubpassIndex]; - if (SubpassDesc.pResolveAttachments != nullptr) - { - const auto& SubpassFBOs = m_pBoundFramebuffer->GetSubpassFramebuffer(m_SubpassIndex); - glBindFramebuffer(GL_READ_FRAMEBUFFER, SubpassFBOs.RenderTarget); - DEV_CHECK_GL_ERROR("Failed to bind subpass render target FBO as read framebuffer"); + const auto& SubpassFBOs = m_pBoundFramebuffer->GetSubpassFramebuffer(m_SubpassIndex); +#ifdef DILIGENT_DEBUG + { + GLint glCurrReadFB = 0; + glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &glCurrReadFB); + CHECK_GL_ERROR("Failed to get current read framebuffer"); + GLuint glExpectedReadFB = SubpassFBOs.RenderTarget != 0 ? static_cast(SubpassFBOs.RenderTarget) : m_pSwapChain->GetDefaultFBO(); + VERIFY(static_cast(glCurrReadFB) == glExpectedReadFB, "Unexpected read framebuffer"); + } +#endif + if (SubpassDesc.pResolveAttachments != nullptr) + { GLuint ResolveDstFBO = SubpassFBOs.Resolve; if (ResolveDstFBO == 0) { @@ -521,6 +529,68 @@ void DeviceContextGLImpl::EndSubpass() ); DEV_CHECK_GL_ERROR("glBlitFramebuffer() failed when resolving multi-sampled attachments"); } + + if (glInvalidateFramebuffer != nullptr) + { + // It is crucially important to invalidate the framebuffer while it is bound + // https://community.arm.com/developer/tools-software/graphics/b/blog/posts/mali-performance-2-how-to-correctly-handle-framebuffers + GLsizei InvalidateAttachmentsCount = 0; + + std::array InvalidateAttachments; + for (Uint32 rt = 0; rt < SubpassDesc.RenderTargetAttachmentCount; ++rt) + { + const auto RTAttachmentIdx = SubpassDesc.pRenderTargetAttachments[rt].AttachmentIndex; + if (RTAttachmentIdx != ATTACHMENT_UNUSED) + { + auto AttachmentLastUse = m_pActiveRenderPass->GetAttachmentFirstLastUse(RTAttachmentIdx).second; + if (AttachmentLastUse == m_SubpassIndex && RPDesc.pAttachments[RTAttachmentIdx].StoreOp == ATTACHMENT_STORE_OP_DISCARD) + { + if (SubpassFBOs.RenderTarget == 0) + { + VERIFY(rt == 0, "Default framebuffer can only have single color attachment"); + InvalidateAttachments[InvalidateAttachmentsCount++] = GL_COLOR; + } + else + { + InvalidateAttachments[InvalidateAttachmentsCount++] = GL_COLOR_ATTACHMENT0 + rt; + } + } + } + } + + if (SubpassDesc.pDepthStencilAttachment != nullptr) + { + const auto DSAttachmentIdx = SubpassDesc.pDepthStencilAttachment->AttachmentIndex; + if (DSAttachmentIdx != ATTACHMENT_UNUSED) + { + auto AttachmentLastUse = m_pActiveRenderPass->GetAttachmentFirstLastUse(DSAttachmentIdx).second; + if (AttachmentLastUse == m_SubpassIndex && RPDesc.pAttachments[DSAttachmentIdx].StoreOp == ATTACHMENT_STORE_OP_DISCARD) + { + const auto& FmtAttribs = GetTextureFormatAttribs(RPDesc.pAttachments[DSAttachmentIdx].Format); + VERIFY_EXPR(FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH || FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH_STENCIL); + if (SubpassFBOs.RenderTarget == 0) + { + InvalidateAttachments[InvalidateAttachmentsCount++] = GL_DEPTH; + if (FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH_STENCIL) + InvalidateAttachments[InvalidateAttachmentsCount++] = GL_STENCIL; + } + else + { + InvalidateAttachments[InvalidateAttachmentsCount++] = FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH ? GL_DEPTH_ATTACHMENT : GL_DEPTH_STENCIL_ATTACHMENT; + } + } + } + } + + if (InvalidateAttachmentsCount > 0) + { + glInvalidateFramebuffer(GL_READ_FRAMEBUFFER, InvalidateAttachmentsCount, InvalidateAttachments.data()); + DEV_CHECK_GL_ERROR("glInvalidateFramebuffer() failed"); + } + } + + // TODO: invalidate input attachments using glInvalidateTexImage + m_ContextState.InvalidateFBO(); } -- cgit v1.2.3