diff options
author | Paul Lemire <paul.lemire@kdab.com> | 2020-08-26 14:29:49 +0200 |
---|---|---|
committer | Paul Lemire <paul.lemire@kdab.com> | 2020-08-27 07:57:59 +0200 |
commit | 50c2e3a1f81b6e2ebdd956b481d756e035cd6c62 (patch) | |
tree | 0185479d32e164e3dd20a262e774b83528726c7c /src/plugins/renderers/rhi | |
parent | 8ef1bab575e5e999b4e200901f7407b3d442d96a (diff) |
rhi: Add support for QRenderCapture
Change-Id: I498c8c83d447f688cd0d88c1a8ebcc4dcb2b68a7
Reviewed-by: Mike Krus <mike.krus@kdab.com>
Diffstat (limited to 'src/plugins/renderers/rhi')
-rw-r--r-- | src/plugins/renderers/rhi/graphicshelpers/submissioncontext.cpp | 3 | ||||
-rw-r--r-- | src/plugins/renderers/rhi/renderer/renderer.cpp | 59 |
2 files changed, 58 insertions, 4 deletions
diff --git a/src/plugins/renderers/rhi/graphicshelpers/submissioncontext.cpp b/src/plugins/renderers/rhi/graphicshelpers/submissioncontext.cpp index 0ebbb2558..0126dbe17 100644 --- a/src/plugins/renderers/rhi/graphicshelpers/submissioncontext.cpp +++ b/src/plugins/renderers/rhi/graphicshelpers/submissioncontext.cpp @@ -1159,7 +1159,8 @@ SubmissionContext::SwapChainInfo *SubmissionContext::swapChainForSurface(QSurfac const int samples = format().samples(); swapChain->setWindow(window); - swapChain->setFlags(QRhiSwapChain::Flags {}); + // Allow to read back from swap chain for RenderCapture to work + swapChain->setFlags(QRhiSwapChain::Flags { QRhiSwapChain::UsedAsTransferSource }); swapChain->setSampleCount(samples); QRhiRenderBuffer *renderBuffer = diff --git a/src/plugins/renderers/rhi/renderer/renderer.cpp b/src/plugins/renderers/rhi/renderer/renderer.cpp index fd8b5c1e9..ccf2a0584 100644 --- a/src/plugins/renderers/rhi/renderer/renderer.cpp +++ b/src/plugins/renderers/rhi/renderer/renderer.cpp @@ -51,6 +51,7 @@ #include <Qt3DRender/qtechnique.h> #include <Qt3DRender/qrenderaspect.h> #include <Qt3DRender/qeffect.h> +#include <Qt3DRender/qrendercapture.h> #include <Qt3DRender/private/qsceneimporter_p.h> #include <Qt3DRender/private/renderstates_p.h> @@ -1186,8 +1187,10 @@ void Renderer::createRenderTarget(RenderTarget *target) if (tex && tex->getRhiTexture()) { auto rhiTex = tex->getRhiTexture(); - if (!rhiTex->flags().testFlag(QRhiTexture::RenderTarget)) { - rhiTex->setFlags(rhiTex->flags() | QRhiTexture::RenderTarget); + if (!rhiTex->flags().testFlag(QRhiTexture::RenderTarget) || + !rhiTex->flags().testFlag(QRhiTexture::UsedAsTransferSource)) { + // UsedAsTransferSource is required if we ever want to read back from the texture + rhiTex->setFlags(rhiTex->flags() | QRhiTexture::RenderTarget|QRhiTexture::UsedAsTransferSource); rhiTex->create(); } switch (rhiTex->format()) { @@ -2813,6 +2816,7 @@ bool Renderer::executeCommandsSubmission(const RHIPassInfo &passInfo) // All the RVs in the current passinfo target the same RenderTarget // A single beginPass should take place, unless Computes RVs are intermingled + QRhiResourceUpdateBatch *inPassUpdates = nullptr; // Per Pass Global States for (RenderView *rv : renderViews) { @@ -2851,11 +2855,60 @@ bool Renderer::executeCommandsSubmission(const RHIPassInfo &passInfo) } executeDrawRenderView(rv); + + const Qt3DCore::QNodeId renderCaptureId = rv->renderCaptureNodeId(); + if (!renderCaptureId.isNull()) { + const QRenderCaptureRequest request = rv->renderCaptureRequest(); + QRhiRenderTarget *rhiTarget = nullptr; + RHIRenderTarget *target = nullptr; + + if (rv->renderTargetId()) { + RHIRenderTargetManager *targetManager = m_RHIResourceManagers->rhiRenderTargetManager(); + target = targetManager->lookupResource(rv->renderTargetId()); + if (target != nullptr) + rhiTarget = target->renderTarget; + } + // Use FBO size if RV has one + const QSize size = rhiTarget ? rhiTarget->pixelSize() : rv->surfaceSize(); + + QRect rect(QPoint(0, 0), size); + if (!request.rect.isEmpty()) + rect = rect.intersected(request.rect); + QImage image; + if (!rect.isEmpty()) { + // Bind fbo as read framebuffer + QRhiReadbackResult *readBackResult = new QRhiReadbackResult; + readBackResult->completed = [this, readBackResult, renderCaptureId, request] () { + const QImage::Format fmt = QImage::Format_RGBA8888_Premultiplied; // fits QRhiTexture::RGBA8 + const uchar *p = reinterpret_cast<const uchar *>(readBackResult->data.constData()); + const QImage image(p, readBackResult->pixelSize.width(), readBackResult->pixelSize.height(), fmt); + + Render::RenderCapture *renderCapture = static_cast<Render::RenderCapture*>(m_nodesManager->frameGraphManager()->lookupNode(renderCaptureId)); + renderCapture->addRenderCapture(request.captureId, image); + if (!Qt3DCore::contains(m_pendingRenderCaptureSendRequests, renderCaptureId)) + m_pendingRenderCaptureSendRequests.push_back(renderCaptureId); + delete readBackResult; + }; + + QRhiReadbackDescription readbackDesc; + if (rhiTarget) { + // First texture should be Attachment 0 + QRhiTextureRenderTarget *textureRenderTarget = static_cast<QRhiTextureRenderTarget *>(rhiTarget); + const QRhiTextureRenderTargetDescription &desc = textureRenderTarget->description(); + const QRhiColorAttachment *color0Att = desc.colorAttachmentAt(0); + readbackDesc.setTexture(color0Att->texture()); + } + inPassUpdates = m_submissionContext->rhi()->nextResourceUpdateBatch(); + inPassUpdates->readBackTexture(readbackDesc, readBackResult); + } else { + qCWarning(Backend) << "Requested capture rectangle is outside framebuffer"; + } + } } } if (Q_LIKELY(inDraw)) - cb->endPass(); + cb->endPass(inPassUpdates); else if (inCompute) cb->endComputePass(); |