diff options
author | Paul Lemire <paul.lemire@kdab.com> | 2023-08-17 13:01:52 +0200 |
---|---|---|
committer | Mike Krus <mike.krus@kdab.com> | 2023-11-09 09:18:30 +0000 |
commit | f1a60664d4fed11e1b1e135fcff92e728d1aa959 (patch) | |
tree | 9283bbdfa286ba3cdb050acf9fdd5b12e9fe3d13 | |
parent | ca30b206ccbd93f2304bbfa630a267d3e3ce14fb (diff) |
RHIRenderer: handle RenderTargets that target Left/Right backbuffers
When defining a RenderTarget with an attachment that targets Left or Right,
we essentially skip texture creation for the RenderTarget and simply
have is use the swapchain instead.
Change-Id: I07d6c168afbc4a7b5e7515c263243e65531e117f
Reviewed-by: Paul Lemire <paul.lemire@kdab.com>
-rw-r--r-- | src/plugins/renderers/rhi/renderer/renderer.cpp | 56 | ||||
-rw-r--r-- | src/plugins/renderers/rhi/renderer/rhirendertarget_p.h | 13 |
2 files changed, 56 insertions, 13 deletions
diff --git a/src/plugins/renderers/rhi/renderer/renderer.cpp b/src/plugins/renderers/rhi/renderer/renderer.cpp index 95c40ac07..c3fb610f5 100644 --- a/src/plugins/renderers/rhi/renderer/renderer.cpp +++ b/src/plugins/renderers/rhi/renderer/renderer.cpp @@ -1141,9 +1141,17 @@ void Renderer::createRenderTarget(RenderTarget *target) } }; + RHIRenderTarget::BackBuffer backBuffer = RHIRenderTarget::BackBuffer::None; + // Look up attachments to populate the RT description // Attachments are sorted by attachment point (Color0 is first) for (const Attachment &attachment : pack.attachments()) { + + if (attachment.m_point == QRenderTargetOutput::Left || attachment.m_point == QRenderTargetOutput::Right) { + backBuffer = attachment.m_point == QRenderTargetOutput::Left ? RHIRenderTarget::BackBuffer::Left : RHIRenderTarget::BackBuffer::Right; + break; + } + RHITexture *tex = texman->lookupResource(attachment.m_textureUuid); if (tex && tex->getRhiTexture()) { auto rhiTex = tex->getRhiTexture(); @@ -1183,6 +1191,12 @@ void Renderer::createRenderTarget(RenderTarget *target) } } + rhiTarget->backBuffer = backBuffer; + // If we are targeting one of the back buffers directly, don't create an offscreen RT + if (backBuffer != RHIRenderTarget::BackBuffer::None) + return; + + // Otherwise, create QRhiRenderBuffer and associated resources if (targetSize.width() <= 0 || targetSize.height() <= 0) { cleanAllocatedResources(); return; @@ -1232,6 +1246,12 @@ bool Renderer::setupRenderTarget(RenderView *rv, const auto &managers = *nodeManagers(); auto &renderTargetManager = *managers.renderTargetManager(); + auto useSwapchainForPipeline = [&]() { + Q_ASSERT(swapchain); + rhiPipeline->setRenderPassDescriptor(swapchain->renderPassDescriptor()); + rhiPipeline->setSampleCount(swapchain->sampleCount()); + }; + auto *renderTarget = renderTargetManager.lookupResource(rv->renderTargetId()); if (renderTarget) { // Render to texture @@ -1239,14 +1259,25 @@ bool Renderer::setupRenderTarget(RenderView *rv, RHIRenderTargetManager *rhiRenderTargetManager = m_RHIResourceManagers->rhiRenderTargetManager(); RHIRenderTarget *rhiTarget = rhiRenderTargetManager->lookupResource(renderTargetId); - if (!rhiTarget || !rhiTarget->renderTarget) { + if (!rhiTarget) { qWarning(Backend) << "Invalid RenderTarget " << renderTargetId << " for Pipeline"; return false; } - rhiPipeline->setRenderPassDescriptor(rhiTarget->renderPassDescriptor); - rhiPipeline->setSampleCount(rhiTarget->renderTarget->sampleCount()); + // The RenderTarget we reference might actually be referencing a swapchain back buffer + if (rhiTarget->backBuffer != RHIRenderTarget::BackBuffer::None) { + // Render to the default framebuffer on our swapchain + useSwapchainForPipeline(); + } else { + if (!rhiTarget->renderTarget) { + qWarning(Backend) << "Invalid RenderTarget " << renderTargetId << " for Pipeline"; + return false; + } + rhiPipeline->setRenderPassDescriptor(rhiTarget->renderPassDescriptor); + rhiPipeline->setSampleCount(rhiTarget->renderTarget->sampleCount()); + } return true; + } else if (m_submissionContext->defaultRenderTarget()) { // Use default RenderTarget if set Default FBO set by Scene3D QRhiRenderTarget *defaultTarget = m_submissionContext->defaultRenderTarget();; @@ -1254,10 +1285,8 @@ bool Renderer::setupRenderTarget(RenderView *rv, rhiPipeline->setSampleCount(defaultTarget->sampleCount()); return true; } else { - Q_ASSERT(swapchain); // Render to the default framebuffer on our swapchain - rhiPipeline->setRenderPassDescriptor(swapchain->renderPassDescriptor()); - rhiPipeline->setSampleCount(swapchain->sampleCount()); + useSwapchainForPipeline(); return true; } } @@ -2640,12 +2669,19 @@ bool Renderer::executeCommandsSubmission(const RHIPassInfo &passInfo) auto &renderTargetManager = *managers.rhiRenderTargetManager(); auto *renderTarget = renderTargetManager.lookupResource(passInfo.renderTargetId); - if (renderTarget) - rhiRenderTarget = renderTarget->renderTarget; - else if (m_submissionContext->defaultRenderTarget()) + if (renderTarget) { + // Is our RenderTarget targeting offscreen attachments? + if (renderTarget->backBuffer == RHIRenderTarget::BackBuffer::None) + rhiRenderTarget = renderTarget->renderTarget; + else // Or one of the back buffers? + rhiRenderTarget = m_submissionContext->currentSwapChain()->currentFrameRenderTarget(renderTarget->backBuffer == RHIRenderTarget::BackBuffer::Left + ? QRhiSwapChain::LeftBuffer + : QRhiSwapChain::RightBuffer); + } else if (m_submissionContext->defaultRenderTarget()) { rhiRenderTarget = m_submissionContext->defaultRenderTarget(); - else + } else { rhiRenderTarget = m_submissionContext->currentSwapChain()->currentFrameRenderTarget(); + } } auto executeDrawRenderView = [&] (RenderView* rv) { diff --git a/src/plugins/renderers/rhi/renderer/rhirendertarget_p.h b/src/plugins/renderers/rhi/renderer/rhirendertarget_p.h index 0c958b315..f699db687 100644 --- a/src/plugins/renderers/rhi/renderer/rhirendertarget_p.h +++ b/src/plugins/renderers/rhi/renderer/rhirendertarget_p.h @@ -30,9 +30,16 @@ struct RHIRenderTarget { // Note: only used when rendering to a FBO // as we don't want to remove the default framebuffer's rendertarget // TODO: at some point separate render target and graphics pipeline as the former can be reused - QRhiRenderTarget *renderTarget{}; - QRhiRenderPassDescriptor *renderPassDescriptor{}; - QRhiRenderBuffer *depthStencilBuffer{}; + QRhiRenderTarget *renderTarget{ nullptr }; + QRhiRenderPassDescriptor *renderPassDescriptor{ nullptr }; + QRhiRenderBuffer *depthStencilBuffer{ nullptr }; + + enum class BackBuffer { + None, + Left, + Right, + }; + BackBuffer backBuffer{ BackBuffer::None }; ~RHIRenderTarget(); void cleanup(); |