diff options
author | Laszlo Agocs <laszlo.agocs@qt.io> | 2024-03-12 14:54:13 +0100 |
---|---|---|
committer | Laszlo Agocs <laszlo.agocs@qt.io> | 2024-03-14 15:54:53 +0100 |
commit | bc61d6fcfa2884f8d2f32b611505c35ada4c443b (patch) | |
tree | 1cfb2967a854cbb7444f0771d5a677c0f4681ff4 /src/gui/rhi | |
parent | 4c49e0fde4f3b586a34436c608a2c8d8f2368300 (diff) |
rhi: Make it possible to discard depth/stencil even when using a texture
Also implement this for OpenGL ES since it can be relevant with tiled
architectures wrt performance.
Task-number: QTBUG-122669
Change-Id: I90dcfe4f5f9edbb8dfb51189d46b89ef2c7a7c06
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Andy Nichols <andy.nichols@qt.io>
Diffstat (limited to 'src/gui/rhi')
-rw-r--r-- | src/gui/rhi/qrhi.cpp | 24 | ||||
-rw-r--r-- | src/gui/rhi/qrhi.h | 3 | ||||
-rw-r--r-- | src/gui/rhi/qrhigles2.cpp | 27 | ||||
-rw-r--r-- | src/gui/rhi/qrhigles2_p.h | 7 | ||||
-rw-r--r-- | src/gui/rhi/qrhimetal.mm | 2 | ||||
-rw-r--r-- | src/gui/rhi/qrhivulkan.cpp | 4 | ||||
-rw-r--r-- | src/gui/rhi/qrhivulkan_p.h | 1 |
7 files changed, 63 insertions, 5 deletions
diff --git a/src/gui/rhi/qrhi.cpp b/src/gui/rhi/qrhi.cpp index 4cba1beec3..4940b5d85e 100644 --- a/src/gui/rhi/qrhi.cpp +++ b/src/gui/rhi/qrhi.cpp @@ -2542,6 +2542,24 @@ QRhiColorAttachment::QRhiColorAttachment(QRhiRenderBuffer *renderBuffer) QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget({ colorAtt, depthStencil }); \endcode + \note when multisample resolving is enabled, the multisample data may not be + written out at all. This means that the multisample texture in a color + attachment must not be used afterwards with shaders for sampling (or other + puroses) whenever a resolve texture is set, since the multisample color + buffer is merely an intermediate storage then that gets no data written back + on some GPU architectures at all. + + \note When using setDepthTexture(), not setDepthStencilBuffer(), and the + depth (stencil) data is not of interest afterwards, set the + DoNotStoreDepthStencilContents flag on the QRhiTextureRenderTarget. This + allows indicating to the underlying 3D API that the depth/stencil data can + be discarded, leading potentially to better performance with tiled GPU + architectures. When the depth-stencil buffer is a QRhiRenderBuffer (and also + for the multisample color texture, see previous note) this is implicit, but + with a depth (stencil) QRhiTexture the intention needs to be declared + explicitly. By default QRhi assumes that the data is of interest (e.g., the + depth texture is sampled in a shader afterwards). + \note This is a RHI API with limited compatibility guarantees, see \l QRhi for details. @@ -5053,6 +5071,12 @@ QRhiResource::Type QRhiSwapChainRenderTarget::resourceType() const (QRhiTextureRenderTargetDescription::depthTexture() is set) because depth/stencil renderbuffers may not have any physical backing and data may not be written out in the first place. + + \value DoNotStoreDepthStencilContents Indicates that the contents of the + depth texture does not need to be written out. Relevant only when a + QRhiTexture, not QRhiRenderBuffer, is used as the depth-stencil buffer, + because for QRhiRenderBuffer this is implicit. This enum value is introduced + in Qt 6.8. */ /*! diff --git a/src/gui/rhi/qrhi.h b/src/gui/rhi/qrhi.h index 30d2b3c909..a9836bf892 100644 --- a/src/gui/rhi/qrhi.h +++ b/src/gui/rhi/qrhi.h @@ -1181,7 +1181,8 @@ class Q_GUI_EXPORT QRhiTextureRenderTarget : public QRhiRenderTarget public: enum Flag { PreserveColorContents = 1 << 0, - PreserveDepthStencilContents = 1 << 1 + PreserveDepthStencilContents = 1 << 1, + DoNotStoreDepthStencilContents = 1 << 2 }; Q_DECLARE_FLAGS(Flags, Flag) diff --git a/src/gui/rhi/qrhigles2.cpp b/src/gui/rhi/qrhigles2.cpp index f6b3056fa3..8e98bcd736 100644 --- a/src/gui/rhi/qrhigles2.cpp +++ b/src/gui/rhi/qrhigles2.cpp @@ -3679,6 +3679,13 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb) if (caps.compute) f->glMemoryBarrier(cmd.args.barrier.barriers); break; + case QGles2CommandBuffer::Command::InvalidateFramebuffer: + if (caps.gles && caps.ctxMajor >= 3) { + f->glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, + cmd.args.invalidateFramebuffer.attCount, + cmd.args.invalidateFramebuffer.att); + } + break; default: break; } @@ -4506,7 +4513,10 @@ void QRhiGles2::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resource const bool hasZ = resolveTexD->m_flags.testFlag(QRhiTexture::ThreeDimensional) || resolveTexD->m_flags.testFlag(QRhiTexture::TextureArray); cmd.args.blitFromRenderbuffer.dstLayer = hasZ ? colorAtt.resolveLayer() : 0; - } else if (!caps.glesMultisampleRenderToTexture) { + } else if (caps.glesMultisampleRenderToTexture) { + // Nothing to do, resolving into colorAtt.resolveTexture() is automatic, + // colorAtt.texture() is in fact not used for anything. + } else { Q_ASSERT(colorAtt.texture()); QGles2Texture *texD = QRHI_RES(QGles2Texture, colorAtt.texture()); if (texD->pixelSize() != size) { @@ -4542,6 +4552,21 @@ void QRhiGles2::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resource } } } + + const bool mayDiscardDepthStencil = rtTex->m_desc.depthStencilBuffer() + || (rtTex->m_desc.depthTexture() && rtTex->m_flags.testFlag(QRhiTextureRenderTarget::DoNotStoreDepthStencilContents)); + if (mayDiscardDepthStencil) { + QGles2CommandBuffer::Command &cmd(cbD->commands.get()); + cmd.cmd = QGles2CommandBuffer::Command::InvalidateFramebuffer; + if (caps.needsDepthStencilCombinedAttach) { + cmd.args.invalidateFramebuffer.attCount = 1; + cmd.args.invalidateFramebuffer.att[0] = GL_DEPTH_STENCIL_ATTACHMENT; + } else { + cmd.args.invalidateFramebuffer.attCount = 2; + cmd.args.invalidateFramebuffer.att[0] = GL_DEPTH_ATTACHMENT; + cmd.args.invalidateFramebuffer.att[1] = GL_STENCIL_ATTACHMENT; + } + } } cbD->recordingPass = QGles2CommandBuffer::NoPass; diff --git a/src/gui/rhi/qrhigles2_p.h b/src/gui/rhi/qrhigles2_p.h index 4407cfea36..04ef596267 100644 --- a/src/gui/rhi/qrhigles2_p.h +++ b/src/gui/rhi/qrhigles2_p.h @@ -337,7 +337,8 @@ struct QGles2CommandBuffer : public QRhiCommandBuffer BindComputePipeline, Dispatch, BarriersForPass, - Barrier + Barrier, + InvalidateFramebuffer }; Cmd cmd; @@ -536,6 +537,10 @@ struct QGles2CommandBuffer : public QRhiCommandBuffer struct { GLbitfield barriers; } barrier; + struct { + int attCount; + GLenum att[3]; + } invalidateFramebuffer; } args; }; diff --git a/src/gui/rhi/qrhimetal.mm b/src/gui/rhi/qrhimetal.mm index 7530186f11..6302a958c9 100644 --- a/src/gui/rhi/qrhimetal.mm +++ b/src/gui/rhi/qrhimetal.mm @@ -4226,7 +4226,7 @@ bool QMetalTextureRenderTarget::create() QMetalTexture *depthTexD = QRHI_RES(QMetalTexture, m_desc.depthTexture()); d->fb.dsTex = depthTexD->d->tex; d->fb.hasStencil = rhiD->isStencilSupportingFormat(depthTexD->format()); - d->fb.depthNeedsStore = true; + d->fb.depthNeedsStore = !m_flags.testFlag(DoNotStoreDepthStencilContents); if (d->colorAttCount == 0) { d->pixelSize = depthTexD->pixelSize(); d->sampleCount = depthTexD->samples; diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp index 2775530d6a..c009d22d04 100644 --- a/src/gui/rhi/qrhivulkan.cpp +++ b/src/gui/rhi/qrhivulkan.cpp @@ -1439,6 +1439,7 @@ bool QRhiVulkan::createOffscreenRenderPass(QVkRenderPassDescriptor *rpD, const QRhiColorAttachment *lastColorAttachment, bool preserveColor, bool preserveDs, + bool storeDs, QRhiRenderBuffer *depthStencilBuffer, QRhiTexture *depthTexture) { @@ -1486,7 +1487,7 @@ bool QRhiVulkan::createOffscreenRenderPass(QVkRenderPassDescriptor *rpD, const VkSampleCountFlagBits samples = depthTexture ? QRHI_RES(QVkTexture, depthTexture)->samples : QRHI_RES(QVkRenderBuffer, depthStencilBuffer)->samples; const VkAttachmentLoadOp loadOp = preserveDs ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_CLEAR; - const VkAttachmentStoreOp storeOp = depthTexture ? VK_ATTACHMENT_STORE_OP_STORE : VK_ATTACHMENT_STORE_OP_DONT_CARE; + const VkAttachmentStoreOp storeOp = storeDs ? VK_ATTACHMENT_STORE_OP_STORE : VK_ATTACHMENT_STORE_OP_DONT_CARE; VkAttachmentDescription attDesc = {}; attDesc.format = dsFormat; attDesc.samples = samples; @@ -6859,6 +6860,7 @@ QRhiRenderPassDescriptor *QVkTextureRenderTarget::newCompatibleRenderPassDescrip m_desc.cendColorAttachments(), m_flags.testFlag(QRhiTextureRenderTarget::PreserveColorContents), m_flags.testFlag(QRhiTextureRenderTarget::PreserveDepthStencilContents), + m_desc.depthTexture() && !m_flags.testFlag(DoNotStoreDepthStencilContents), m_desc.depthStencilBuffer(), m_desc.depthTexture())) { diff --git a/src/gui/rhi/qrhivulkan_p.h b/src/gui/rhi/qrhivulkan_p.h index a364634676..bdd65e177b 100644 --- a/src/gui/rhi/qrhivulkan_p.h +++ b/src/gui/rhi/qrhivulkan_p.h @@ -773,6 +773,7 @@ public: const QRhiColorAttachment *lastColorAttachment, bool preserveColor, bool preserveDs, + bool storeDs, QRhiRenderBuffer *depthStencilBuffer, QRhiTexture *depthTexture); bool ensurePipelineCache(const void *initialData = nullptr, size_t initialDataSize = 0); |