summaryrefslogtreecommitdiffstats
path: root/src/gui/rhi
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2024-03-12 14:54:13 +0100
committerLaszlo Agocs <laszlo.agocs@qt.io>2024-03-14 15:54:53 +0100
commitbc61d6fcfa2884f8d2f32b611505c35ada4c443b (patch)
tree1cfb2967a854cbb7444f0771d5a677c0f4681ff4 /src/gui/rhi
parent4c49e0fde4f3b586a34436c608a2c8d8f2368300 (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.cpp24
-rw-r--r--src/gui/rhi/qrhi.h3
-rw-r--r--src/gui/rhi/qrhigles2.cpp27
-rw-r--r--src/gui/rhi/qrhigles2_p.h7
-rw-r--r--src/gui/rhi/qrhimetal.mm2
-rw-r--r--src/gui/rhi/qrhivulkan.cpp4
-rw-r--r--src/gui/rhi/qrhivulkan_p.h1
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);