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>
This commit is contained in:
parent
4c49e0fde4
commit
bc61d6fcfa
@ -2542,6 +2542,24 @@ QRhiColorAttachment::QRhiColorAttachment(QRhiRenderBuffer *renderBuffer)
|
|||||||
QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget({ colorAtt, depthStencil });
|
QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget({ colorAtt, depthStencil });
|
||||||
\endcode
|
\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
|
\note This is a RHI API with limited compatibility guarantees, see \l QRhi
|
||||||
for details.
|
for details.
|
||||||
|
|
||||||
@ -5053,6 +5071,12 @@ QRhiResource::Type QRhiSwapChainRenderTarget::resourceType() const
|
|||||||
(QRhiTextureRenderTargetDescription::depthTexture() is set) because
|
(QRhiTextureRenderTargetDescription::depthTexture() is set) because
|
||||||
depth/stencil renderbuffers may not have any physical backing and data may
|
depth/stencil renderbuffers may not have any physical backing and data may
|
||||||
not be written out in the first place.
|
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.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -1181,7 +1181,8 @@ class Q_GUI_EXPORT QRhiTextureRenderTarget : public QRhiRenderTarget
|
|||||||
public:
|
public:
|
||||||
enum Flag {
|
enum Flag {
|
||||||
PreserveColorContents = 1 << 0,
|
PreserveColorContents = 1 << 0,
|
||||||
PreserveDepthStencilContents = 1 << 1
|
PreserveDepthStencilContents = 1 << 1,
|
||||||
|
DoNotStoreDepthStencilContents = 1 << 2
|
||||||
};
|
};
|
||||||
Q_DECLARE_FLAGS(Flags, Flag)
|
Q_DECLARE_FLAGS(Flags, Flag)
|
||||||
|
|
||||||
|
@ -3679,6 +3679,13 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb)
|
|||||||
if (caps.compute)
|
if (caps.compute)
|
||||||
f->glMemoryBarrier(cmd.args.barrier.barriers);
|
f->glMemoryBarrier(cmd.args.barrier.barriers);
|
||||||
break;
|
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:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -4506,7 +4513,10 @@ void QRhiGles2::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resource
|
|||||||
const bool hasZ = resolveTexD->m_flags.testFlag(QRhiTexture::ThreeDimensional)
|
const bool hasZ = resolveTexD->m_flags.testFlag(QRhiTexture::ThreeDimensional)
|
||||||
|| resolveTexD->m_flags.testFlag(QRhiTexture::TextureArray);
|
|| resolveTexD->m_flags.testFlag(QRhiTexture::TextureArray);
|
||||||
cmd.args.blitFromRenderbuffer.dstLayer = hasZ ? colorAtt.resolveLayer() : 0;
|
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());
|
Q_ASSERT(colorAtt.texture());
|
||||||
QGles2Texture *texD = QRHI_RES(QGles2Texture, colorAtt.texture());
|
QGles2Texture *texD = QRHI_RES(QGles2Texture, colorAtt.texture());
|
||||||
if (texD->pixelSize() != size) {
|
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;
|
cbD->recordingPass = QGles2CommandBuffer::NoPass;
|
||||||
|
@ -337,7 +337,8 @@ struct QGles2CommandBuffer : public QRhiCommandBuffer
|
|||||||
BindComputePipeline,
|
BindComputePipeline,
|
||||||
Dispatch,
|
Dispatch,
|
||||||
BarriersForPass,
|
BarriersForPass,
|
||||||
Barrier
|
Barrier,
|
||||||
|
InvalidateFramebuffer
|
||||||
};
|
};
|
||||||
Cmd cmd;
|
Cmd cmd;
|
||||||
|
|
||||||
@ -536,6 +537,10 @@ struct QGles2CommandBuffer : public QRhiCommandBuffer
|
|||||||
struct {
|
struct {
|
||||||
GLbitfield barriers;
|
GLbitfield barriers;
|
||||||
} barrier;
|
} barrier;
|
||||||
|
struct {
|
||||||
|
int attCount;
|
||||||
|
GLenum att[3];
|
||||||
|
} invalidateFramebuffer;
|
||||||
} args;
|
} args;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4226,7 +4226,7 @@ bool QMetalTextureRenderTarget::create()
|
|||||||
QMetalTexture *depthTexD = QRHI_RES(QMetalTexture, m_desc.depthTexture());
|
QMetalTexture *depthTexD = QRHI_RES(QMetalTexture, m_desc.depthTexture());
|
||||||
d->fb.dsTex = depthTexD->d->tex;
|
d->fb.dsTex = depthTexD->d->tex;
|
||||||
d->fb.hasStencil = rhiD->isStencilSupportingFormat(depthTexD->format());
|
d->fb.hasStencil = rhiD->isStencilSupportingFormat(depthTexD->format());
|
||||||
d->fb.depthNeedsStore = true;
|
d->fb.depthNeedsStore = !m_flags.testFlag(DoNotStoreDepthStencilContents);
|
||||||
if (d->colorAttCount == 0) {
|
if (d->colorAttCount == 0) {
|
||||||
d->pixelSize = depthTexD->pixelSize();
|
d->pixelSize = depthTexD->pixelSize();
|
||||||
d->sampleCount = depthTexD->samples;
|
d->sampleCount = depthTexD->samples;
|
||||||
|
@ -1439,6 +1439,7 @@ bool QRhiVulkan::createOffscreenRenderPass(QVkRenderPassDescriptor *rpD,
|
|||||||
const QRhiColorAttachment *lastColorAttachment,
|
const QRhiColorAttachment *lastColorAttachment,
|
||||||
bool preserveColor,
|
bool preserveColor,
|
||||||
bool preserveDs,
|
bool preserveDs,
|
||||||
|
bool storeDs,
|
||||||
QRhiRenderBuffer *depthStencilBuffer,
|
QRhiRenderBuffer *depthStencilBuffer,
|
||||||
QRhiTexture *depthTexture)
|
QRhiTexture *depthTexture)
|
||||||
{
|
{
|
||||||
@ -1486,7 +1487,7 @@ bool QRhiVulkan::createOffscreenRenderPass(QVkRenderPassDescriptor *rpD,
|
|||||||
const VkSampleCountFlagBits samples = depthTexture ? QRHI_RES(QVkTexture, depthTexture)->samples
|
const VkSampleCountFlagBits samples = depthTexture ? QRHI_RES(QVkTexture, depthTexture)->samples
|
||||||
: QRHI_RES(QVkRenderBuffer, depthStencilBuffer)->samples;
|
: QRHI_RES(QVkRenderBuffer, depthStencilBuffer)->samples;
|
||||||
const VkAttachmentLoadOp loadOp = preserveDs ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_CLEAR;
|
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 = {};
|
VkAttachmentDescription attDesc = {};
|
||||||
attDesc.format = dsFormat;
|
attDesc.format = dsFormat;
|
||||||
attDesc.samples = samples;
|
attDesc.samples = samples;
|
||||||
@ -6859,6 +6860,7 @@ QRhiRenderPassDescriptor *QVkTextureRenderTarget::newCompatibleRenderPassDescrip
|
|||||||
m_desc.cendColorAttachments(),
|
m_desc.cendColorAttachments(),
|
||||||
m_flags.testFlag(QRhiTextureRenderTarget::PreserveColorContents),
|
m_flags.testFlag(QRhiTextureRenderTarget::PreserveColorContents),
|
||||||
m_flags.testFlag(QRhiTextureRenderTarget::PreserveDepthStencilContents),
|
m_flags.testFlag(QRhiTextureRenderTarget::PreserveDepthStencilContents),
|
||||||
|
m_desc.depthTexture() && !m_flags.testFlag(DoNotStoreDepthStencilContents),
|
||||||
m_desc.depthStencilBuffer(),
|
m_desc.depthStencilBuffer(),
|
||||||
m_desc.depthTexture()))
|
m_desc.depthTexture()))
|
||||||
{
|
{
|
||||||
|
@ -773,6 +773,7 @@ public:
|
|||||||
const QRhiColorAttachment *lastColorAttachment,
|
const QRhiColorAttachment *lastColorAttachment,
|
||||||
bool preserveColor,
|
bool preserveColor,
|
||||||
bool preserveDs,
|
bool preserveDs,
|
||||||
|
bool storeDs,
|
||||||
QRhiRenderBuffer *depthStencilBuffer,
|
QRhiRenderBuffer *depthStencilBuffer,
|
||||||
QRhiTexture *depthTexture);
|
QRhiTexture *depthTexture);
|
||||||
bool ensurePipelineCache(const void *initialData = nullptr, size_t initialDataSize = 0);
|
bool ensurePipelineCache(const void *initialData = nullptr, size_t initialDataSize = 0);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user