From 0331dbd1ed89e3aac6c7a1371db5c9b1615f8307 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Sun, 10 Dec 2017 17:13:23 +0100 Subject: Enable BlitFramebuffer with non-output render targets Task-number: QTBUG-65080 Change-Id: I711f58e67906af048a64eb7d0e2f66c8a96dd14f Reviewed-by: Sean Harmer --- src/render/backend/attachmentpack.cpp | 13 ++- src/render/backend/attachmentpack_p.h | 4 +- src/render/graphicshelpers/graphicscontext.cpp | 113 +++++++++++++++++-------- src/render/graphicshelpers/graphicscontext_p.h | 4 +- src/render/jobs/renderviewjobutils.cpp | 2 +- 5 files changed, 90 insertions(+), 46 deletions(-) diff --git a/src/render/backend/attachmentpack.cpp b/src/render/backend/attachmentpack.cpp index 9a08fdde4..a2ac8c30c 100644 --- a/src/render/backend/attachmentpack.cpp +++ b/src/render/backend/attachmentpack.cpp @@ -50,11 +50,10 @@ AttachmentPack::AttachmentPack() { } -AttachmentPack::AttachmentPack(const RenderTargetSelector *selector, const RenderTarget *target, AttachmentManager *attachmentManager) +AttachmentPack::AttachmentPack(const RenderTarget *target, + AttachmentManager *attachmentManager, + const QVector &drawBuffers) { - // Cache draw buffers list - const QVector selectedAttachmentPoints = selector->outputs(); - // Copy attachments const auto outputIds = target->renderOutputs(); for (Qt3DCore::QNodeId outputId : outputIds) { @@ -66,15 +65,15 @@ AttachmentPack::AttachmentPack(const RenderTargetSelector *selector, const Rende // Create actual DrawBuffers list that is used for glDrawBuffers // If nothing is specified, use all the attachments as draw buffers - if (selectedAttachmentPoints.isEmpty()) { + if (drawBuffers.isEmpty()) { m_drawBuffers.reserve(m_attachments.size()); for (const Attachment &attachment : qAsConst(m_attachments)) // only consider Color Attachments if (attachment.m_point <= QRenderTargetOutput::Color15) m_drawBuffers.push_back((int) attachment.m_point); } else { - m_drawBuffers.reserve(selectedAttachmentPoints.size()); - for (QRenderTargetOutput::AttachmentPoint drawBuffer : selectedAttachmentPoints) + m_drawBuffers.reserve(drawBuffers.size()); + for (QRenderTargetOutput::AttachmentPoint drawBuffer : drawBuffers) if (drawBuffer <= QRenderTargetOutput::Color15) m_drawBuffers.push_back((int) drawBuffer); } diff --git a/src/render/backend/attachmentpack_p.h b/src/render/backend/attachmentpack_p.h index 98362149a..a3a2586dd 100644 --- a/src/render/backend/attachmentpack_p.h +++ b/src/render/backend/attachmentpack_p.h @@ -84,7 +84,9 @@ class AttachmentPack { public: AttachmentPack(); - AttachmentPack(const RenderTargetSelector *selector, const RenderTarget *target, AttachmentManager *attachmentManager); + AttachmentPack(const RenderTarget *target, + AttachmentManager *attachmentManager, + const QVector &drawBuffers = QVector()); QVector attachments() const { return m_attachments; } QVector getGlDrawBuffers() const { return m_drawBuffers; } diff --git a/src/render/graphicshelpers/graphicscontext.cpp b/src/render/graphicshelpers/graphicscontext.cpp index 9a20c77e7..f9229f633 100644 --- a/src/render/graphicshelpers/graphicscontext.cpp +++ b/src/render/graphicshelpers/graphicscontext.cpp @@ -579,38 +579,11 @@ void GraphicsContext::activateRenderTarget(Qt3DCore::QNodeId renderTargetNodeId, // this is the default fbo that some platforms create (iOS), we just register it // Insert FBO into hash m_renderTargets.insert(renderTargetNodeId, fboId); - } else if ((fboId = m_glHelper->createFrameBufferObject()) != 0) { - // The FBO is created and its attachments are set once - // Insert FBO into hash - m_renderTargets.insert(renderTargetNodeId, fboId); - // Bind FBO - m_glHelper->bindFrameBufferObject(fboId, GraphicsHelperInterface::FBODraw); - bindFrameBufferAttachmentHelper(fboId, attachments); } else { - qCritical() << "Failed to create FBO"; + fboId = createRenderTarget(renderTargetNodeId, attachments); } } else { - fboId = m_renderTargets.value(renderTargetNodeId); - - // We need to check if one of the attachment was resized - bool needsResize = !m_renderTargetsSize.contains(fboId); // not even initialized yet? - if (!needsResize) { - // render target exists, has attachment been resized? - GLTextureManager *glTextureManager = m_renderer->nodeManagers()->glTextureManager(); - const QSize s = m_renderTargetsSize[fboId]; - const auto attachments_ = attachments.attachments(); - for (const Attachment &attachment : attachments_) { - GLTexture *rTex = glTextureManager->lookupResource(attachment.m_textureUuid); - needsResize |= (rTex != nullptr && rTex->size() != s); - if (attachment.m_point == QRenderTargetOutput::Color0) - m_renderTargetFormat = rTex->properties().format; - } - } - - if (needsResize) { - m_glHelper->bindFrameBufferObject(fboId, GraphicsHelperInterface::FBODraw); - bindFrameBufferAttachmentHelper(fboId, attachments); - } + fboId = updateRenderTarget(renderTargetNodeId, attachments, true); } } m_activeFBO = fboId; @@ -619,6 +592,54 @@ void GraphicsContext::activateRenderTarget(Qt3DCore::QNodeId renderTargetNodeId, activateDrawBuffers(attachments); } +GLuint GraphicsContext::createRenderTarget(Qt3DCore::QNodeId renderTargetNodeId, const AttachmentPack &attachments) +{ + const GLuint fboId = m_glHelper->createFrameBufferObject(); + if (fboId) { + // The FBO is created and its attachments are set once + // Insert FBO into hash + m_renderTargets.insert(renderTargetNodeId, fboId); + // Bind FBO + m_glHelper->bindFrameBufferObject(fboId, GraphicsHelperInterface::FBODraw); + bindFrameBufferAttachmentHelper(fboId, attachments); + } else { + qCritical("Failed to create FBO"); + } + return fboId; +} + +GLuint GraphicsContext::updateRenderTarget(Qt3DCore::QNodeId renderTargetNodeId, const AttachmentPack &attachments, bool isActiveRenderTarget) +{ + const GLuint fboId = m_renderTargets.value(renderTargetNodeId); + + // We need to check if one of the attachment was resized + bool needsResize = !m_renderTargetsSize.contains(fboId); // not even initialized yet? + if (!needsResize) { + // render target exists, has attachment been resized? + GLTextureManager *glTextureManager = m_renderer->nodeManagers()->glTextureManager(); + const QSize s = m_renderTargetsSize[fboId]; + const auto attachments_ = attachments.attachments(); + for (const Attachment &attachment : attachments_) { + GLTexture *rTex = glTextureManager->lookupResource(attachment.m_textureUuid); + // ### TODO QTBUG-64757 this check is insufficient since the + // texture may have changed to another one with the same size. That + // case is not handled atm. + needsResize |= (rTex != nullptr && rTex->size() != s); + if (isActiveRenderTarget) { + if (attachment.m_point == QRenderTargetOutput::Color0) + m_renderTargetFormat = rTex->properties().format; + } + } + } + + if (needsResize) { + m_glHelper->bindFrameBufferObject(fboId, GraphicsHelperInterface::FBODraw); + bindFrameBufferAttachmentHelper(fboId, attachments); + } + + return fboId; +} + void GraphicsContext::bindFrameBufferAttachmentHelper(GLuint fboId, const AttachmentPack &attachments) { // Set FBO attachments. These are normally textures, except that on Open GL @@ -1515,20 +1536,39 @@ bool GraphicsContext::hasGLBufferForBuffer(Buffer *buffer) return (it != m_renderBufferHash.end()); } -void GraphicsContext::blitFramebuffer(Qt3DCore::QNodeId inputRenderTarget, - Qt3DCore::QNodeId outputRenderTarget, +void GraphicsContext::blitFramebuffer(Qt3DCore::QNodeId inputRenderTargetId, + Qt3DCore::QNodeId outputRenderTargetId, QRect inputRect, QRect outputRect, uint defaultFboId, QRenderTargetOutput::AttachmentPoint inputAttachmentPoint, QRenderTargetOutput::AttachmentPoint outputAttachmentPoint, QBlitFramebuffer::InterpolationMethod interpolationMethod) { - //Find the context side name for the render targets - const GLuint inputFboId = m_renderTargets[inputRenderTarget]; + GLuint inputFboId = defaultFboId; + bool inputBufferIsDefault = true; + if (!inputRenderTargetId.isNull()) { + RenderTarget *renderTarget = m_renderer->nodeManagers()->renderTargetManager()->lookupResource(inputRenderTargetId); + if (renderTarget) { + AttachmentPack attachments(renderTarget, m_renderer->nodeManagers()->attachmentManager()); + if (m_renderTargets.contains(inputRenderTargetId)) + inputFboId = updateRenderTarget(inputRenderTargetId, attachments, false); + else + inputFboId = createRenderTarget(inputRenderTargetId, attachments); + } + inputBufferIsDefault = false; + } + GLuint outputFboId = defaultFboId; bool outputBufferIsDefault = true; - if (!outputRenderTarget.isNull() && m_renderTargets.contains(outputRenderTarget)) { - outputFboId = m_renderTargets[outputRenderTarget]; + if (!outputRenderTargetId.isNull()) { + RenderTarget *renderTarget = m_renderer->nodeManagers()->renderTargetManager()->lookupResource(outputRenderTargetId); + if (renderTarget) { + AttachmentPack attachments(renderTarget, m_renderer->nodeManagers()->attachmentManager()); + if (m_renderTargets.contains(outputRenderTargetId)) + outputFboId = updateRenderTarget(outputRenderTargetId, attachments, false); + else + outputFboId = createRenderTarget(outputRenderTargetId, attachments); + } outputBufferIsDefault = false; } @@ -1552,7 +1592,8 @@ void GraphicsContext::blitFramebuffer(Qt3DCore::QNodeId inputRenderTarget, bindFramebuffer(outputFboId, GraphicsHelperInterface::FBODraw); //Bind texture - readBuffer(GL_COLOR_ATTACHMENT0 + inputAttachmentPoint); + if (!inputBufferIsDefault) + readBuffer(GL_COLOR_ATTACHMENT0 + inputAttachmentPoint); if (!outputBufferIsDefault) drawBuffer(GL_COLOR_ATTACHMENT0 + outputAttachmentPoint); diff --git a/src/render/graphicshelpers/graphicscontext_p.h b/src/render/graphicshelpers/graphicscontext_p.h index b07a11c7e..60d1ec237 100644 --- a/src/render/graphicshelpers/graphicscontext_p.h +++ b/src/render/graphicshelpers/graphicscontext_p.h @@ -168,7 +168,7 @@ public: void releaseBuffer(Qt3DCore::QNodeId bufferId); bool hasGLBufferForBuffer(Buffer *buffer); - void blitFramebuffer(Qt3DCore::QNodeId outputRenderTarget, Qt3DCore::QNodeId inputRenderTarget, + void blitFramebuffer(Qt3DCore::QNodeId outputRenderTargetId, Qt3DCore::QNodeId inputRenderTargetId, QRect inputRect, QRect outputRect, uint defaultFboId, QRenderTargetOutput::AttachmentPoint inputAttachmentPoint, @@ -268,6 +268,8 @@ private: GraphicsHelperInterface *resolveHighestOpenGLFunctions(); + GLuint createRenderTarget(Qt3DCore::QNodeId renderTargetNodeId, const AttachmentPack &attachments); + GLuint updateRenderTarget(Qt3DCore::QNodeId renderTargetNodeId, const AttachmentPack &attachments, bool isActiveRenderTarget); void bindFrameBufferAttachmentHelper(GLuint fboId, const AttachmentPack &attachments); void activateDrawBuffers(const AttachmentPack &attachments); HGLBuffer createGLBufferFor(Buffer *buffer, GLBuffer::Type type); diff --git a/src/render/jobs/renderviewjobutils.cpp b/src/render/jobs/renderviewjobutils.cpp index cf23e572f..1f25a2353 100644 --- a/src/render/jobs/renderviewjobutils.cpp +++ b/src/render/jobs/renderviewjobutils.cpp @@ -145,7 +145,7 @@ void setRenderViewConfigFromFrameGraphLeafNode(RenderView *rv, const FrameGraphN RenderTarget *renderTarget = manager->renderTargetManager()->data(renderTargetHandle); if (renderTarget) - rv->setAttachmentPack(AttachmentPack(targetSelector, renderTarget, manager->attachmentManager())); + rv->setAttachmentPack(AttachmentPack(renderTarget, manager->attachmentManager(), targetSelector->outputs())); } break; } -- cgit v1.2.3