rhi: Make it safe to always call deleteLater on a resource
...even when the QRhi is already gone. This should not happen in well-written applications and libraries, but we handle this gracefully in the regular dtor and destroy() for resources that register themselves to their creator QRhi, so by registering everything we can offer this to all QRhiResource subclasses. We still want to differentiate between native resource owning QRhiResources and others (that do not create native graphics objects), so do this via a flag passed to registerResource(). This way the behavior with QT_RHI_LEAK_CHECK=1 does not change. Pick-to: 6.5 Fixes: QTBUG-112914 Change-Id: I9bafc81ef7a4ae76f356fc5f6248628d1f8791e0 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Christian Strømme <christian.stromme@qt.io>
This commit is contained in:
parent
e3c9dce0b6
commit
62a4ca773a
@ -2119,11 +2119,17 @@ QRhiResource::~QRhiResource()
|
|||||||
requirement of not altering QRhiResource objects that are referenced by the
|
requirement of not altering QRhiResource objects that are referenced by the
|
||||||
frame being recorded.
|
frame being recorded.
|
||||||
|
|
||||||
|
If the QRhi that created this object is already destroyed, the object is
|
||||||
|
deleted immediately.
|
||||||
|
|
||||||
\sa destroy()
|
\sa destroy()
|
||||||
*/
|
*/
|
||||||
void QRhiResource::deleteLater()
|
void QRhiResource::deleteLater()
|
||||||
{
|
{
|
||||||
m_rhi->addDeleteLater(this);
|
if (m_rhi)
|
||||||
|
m_rhi->addDeleteLater(this);
|
||||||
|
else
|
||||||
|
delete this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -2172,10 +2178,13 @@ quint64 QRhiResource::globalResourceId() const
|
|||||||
|
|
||||||
/*!
|
/*!
|
||||||
\return the QRhi that created this resource.
|
\return the QRhi that created this resource.
|
||||||
|
|
||||||
|
If the QRhi that created this object is already destroyed, the result is
|
||||||
|
\nullptr.
|
||||||
*/
|
*/
|
||||||
QRhi *QRhiResource::rhi() const
|
QRhi *QRhiResource::rhi() const
|
||||||
{
|
{
|
||||||
return m_rhi->q;
|
return m_rhi ? m_rhi->q : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -5100,7 +5109,7 @@ QRhiResource::Type QRhiCommandBuffer::resourceType() const
|
|||||||
return CommandBuffer;
|
return CommandBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *resourceTypeStr(QRhiResource *res)
|
static const char *resourceTypeStr(const QRhiResource *res)
|
||||||
{
|
{
|
||||||
switch (res->resourceType()) {
|
switch (res->resourceType()) {
|
||||||
case QRhiResource::Buffer:
|
case QRhiResource::Buffer:
|
||||||
@ -5151,8 +5160,10 @@ QRhiImplementation::~QRhiImplementation()
|
|||||||
qWarning("QRhi %p going down with %d unreleased resources that own native graphics objects. This is not nice.",
|
qWarning("QRhi %p going down with %d unreleased resources that own native graphics objects. This is not nice.",
|
||||||
q, int(resources.size()));
|
q, int(resources.size()));
|
||||||
}
|
}
|
||||||
for (QRhiResource *res : std::as_const(resources)) {
|
for (auto it = resources.cbegin(), end = resources.cend(); it != end; ++it) {
|
||||||
if (leakCheck)
|
QRhiResource *res = it.key();
|
||||||
|
const bool ownsNativeResources = it.value();
|
||||||
|
if (leakCheck && ownsNativeResources)
|
||||||
qWarning(" %s resource %p (%s)", resourceTypeStr(res), res, res->m_objectName.constData());
|
qWarning(" %s resource %p (%s)", resourceTypeStr(res), res, res->m_objectName.constData());
|
||||||
|
|
||||||
// Null out the resource's rhi pointer. This is why it makes sense to do null
|
// Null out the resource's rhi pointer. This is why it makes sense to do null
|
||||||
|
@ -149,10 +149,14 @@ public:
|
|||||||
void textureFormatInfo(QRhiTexture::Format format, const QSize &size,
|
void textureFormatInfo(QRhiTexture::Format format, const QSize &size,
|
||||||
quint32 *bpl, quint32 *byteSize, quint32 *bytesPerPixel) const;
|
quint32 *bpl, quint32 *byteSize, quint32 *bytesPerPixel) const;
|
||||||
|
|
||||||
// only really care about resources that own native graphics resources underneath
|
void registerResource(QRhiResource *res, bool ownsNativeResources = true)
|
||||||
void registerResource(QRhiResource *res)
|
|
||||||
{
|
{
|
||||||
resources.insert(res);
|
// The ownsNativeResources is relevant for the (graphics resource) leak
|
||||||
|
// check in ~QRhiImplementation; when false, the registration's sole
|
||||||
|
// purpose is to automatically null out the resource's m_rhi pointer in
|
||||||
|
// case the rhi goes away first. (which should not happen in
|
||||||
|
// well-written applications but we try to be graceful)
|
||||||
|
resources.insert(res, ownsNativeResources);
|
||||||
}
|
}
|
||||||
|
|
||||||
void unregisterResource(QRhiResource *res)
|
void unregisterResource(QRhiResource *res)
|
||||||
@ -160,11 +164,6 @@ public:
|
|||||||
resources.remove(res);
|
resources.remove(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
QSet<QRhiResource *> activeResources() const
|
|
||||||
{
|
|
||||||
return resources;
|
|
||||||
}
|
|
||||||
|
|
||||||
void addDeleteLater(QRhiResource *res)
|
void addDeleteLater(QRhiResource *res)
|
||||||
{
|
{
|
||||||
if (inFrame)
|
if (inFrame)
|
||||||
@ -251,7 +250,7 @@ private:
|
|||||||
QVarLengthArray<QRhiResourceUpdateBatch *, 4> resUpdPool;
|
QVarLengthArray<QRhiResourceUpdateBatch *, 4> resUpdPool;
|
||||||
quint64 resUpdPoolMap = 0;
|
quint64 resUpdPoolMap = 0;
|
||||||
int lastResUpdIdx = -1;
|
int lastResUpdIdx = -1;
|
||||||
QSet<QRhiResource *> resources;
|
QHash<QRhiResource *, bool> resources;
|
||||||
QSet<QRhiResource *> pendingDeleteResources;
|
QSet<QRhiResource *> pendingDeleteResources;
|
||||||
QVarLengthArray<QRhi::CleanupCallback, 4> cleanupCallbacks;
|
QVarLengthArray<QRhi::CleanupCallback, 4> cleanupCallbacks;
|
||||||
QVarLengthArray<QRhi::GpuFrameTimeCallback, 4> gpuFrameTimeCallbacks;
|
QVarLengthArray<QRhi::GpuFrameTimeCallback, 4> gpuFrameTimeCallbacks;
|
||||||
|
@ -3588,7 +3588,9 @@ QD3D11RenderPassDescriptor::~QD3D11RenderPassDescriptor()
|
|||||||
|
|
||||||
void QD3D11RenderPassDescriptor::destroy()
|
void QD3D11RenderPassDescriptor::destroy()
|
||||||
{
|
{
|
||||||
// nothing to do here
|
QRHI_RES_RHI(QRhiD3D11);
|
||||||
|
if (rhiD)
|
||||||
|
rhiD->unregisterResource(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QD3D11RenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *other) const
|
bool QD3D11RenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *other) const
|
||||||
@ -3599,7 +3601,10 @@ bool QD3D11RenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *ot
|
|||||||
|
|
||||||
QRhiRenderPassDescriptor *QD3D11RenderPassDescriptor::newCompatibleRenderPassDescriptor() const
|
QRhiRenderPassDescriptor *QD3D11RenderPassDescriptor::newCompatibleRenderPassDescriptor() const
|
||||||
{
|
{
|
||||||
return new QD3D11RenderPassDescriptor(m_rhi);
|
QD3D11RenderPassDescriptor *rpD = new QD3D11RenderPassDescriptor(m_rhi);
|
||||||
|
QRHI_RES_RHI(QRhiD3D11);
|
||||||
|
rhiD->registerResource(rpD, false);
|
||||||
|
return rpD;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector<quint32> QD3D11RenderPassDescriptor::serializedFormat() const
|
QVector<quint32> QD3D11RenderPassDescriptor::serializedFormat() const
|
||||||
@ -3681,7 +3686,10 @@ void QD3D11TextureRenderTarget::destroy()
|
|||||||
|
|
||||||
QRhiRenderPassDescriptor *QD3D11TextureRenderTarget::newCompatibleRenderPassDescriptor()
|
QRhiRenderPassDescriptor *QD3D11TextureRenderTarget::newCompatibleRenderPassDescriptor()
|
||||||
{
|
{
|
||||||
return new QD3D11RenderPassDescriptor(m_rhi);
|
QD3D11RenderPassDescriptor *rpD = new QD3D11RenderPassDescriptor(m_rhi);
|
||||||
|
QRHI_RES_RHI(QRhiD3D11);
|
||||||
|
rhiD->registerResource(rpD, false);
|
||||||
|
return rpD;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QD3D11TextureRenderTarget::create()
|
bool QD3D11TextureRenderTarget::create()
|
||||||
@ -3845,6 +3853,10 @@ void QD3D11ShaderResourceBindings::destroy()
|
|||||||
{
|
{
|
||||||
sortedBindings.clear();
|
sortedBindings.clear();
|
||||||
boundResourceData.clear();
|
boundResourceData.clear();
|
||||||
|
|
||||||
|
QRHI_RES_RHI(QRhiD3D11);
|
||||||
|
if (rhiD)
|
||||||
|
rhiD->unregisterResource(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QD3D11ShaderResourceBindings::create()
|
bool QD3D11ShaderResourceBindings::create()
|
||||||
@ -3876,6 +3888,7 @@ bool QD3D11ShaderResourceBindings::create()
|
|||||||
}
|
}
|
||||||
|
|
||||||
generation += 1;
|
generation += 1;
|
||||||
|
rhiD->registerResource(this, false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4796,7 +4809,10 @@ QRhiSwapChainHdrInfo QD3D11SwapChain::hdrInfo()
|
|||||||
|
|
||||||
QRhiRenderPassDescriptor *QD3D11SwapChain::newCompatibleRenderPassDescriptor()
|
QRhiRenderPassDescriptor *QD3D11SwapChain::newCompatibleRenderPassDescriptor()
|
||||||
{
|
{
|
||||||
return new QD3D11RenderPassDescriptor(m_rhi);
|
QD3D11RenderPassDescriptor *rpD = new QD3D11RenderPassDescriptor(m_rhi);
|
||||||
|
QRHI_RES_RHI(QRhiD3D11);
|
||||||
|
rhiD->registerResource(rpD, false);
|
||||||
|
return rpD;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QD3D11SwapChain::newColorBuffer(const QSize &size, DXGI_FORMAT format, DXGI_SAMPLE_DESC sampleDesc,
|
bool QD3D11SwapChain::newColorBuffer(const QSize &size, DXGI_FORMAT format, DXGI_SAMPLE_DESC sampleDesc,
|
||||||
|
@ -4168,6 +4168,10 @@ QD3D12Sampler::~QD3D12Sampler()
|
|||||||
void QD3D12Sampler::destroy()
|
void QD3D12Sampler::destroy()
|
||||||
{
|
{
|
||||||
shaderVisibleDescriptor = {};
|
shaderVisibleDescriptor = {};
|
||||||
|
|
||||||
|
QRHI_RES_RHI(QRhiD3D12);
|
||||||
|
if (rhiD)
|
||||||
|
rhiD->unregisterResource(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline D3D12_FILTER toD3DFilter(QRhiSampler::Filter minFilter, QRhiSampler::Filter magFilter, QRhiSampler::Filter mipFilter)
|
static inline D3D12_FILTER toD3DFilter(QRhiSampler::Filter minFilter, QRhiSampler::Filter magFilter, QRhiSampler::Filter mipFilter)
|
||||||
@ -4248,6 +4252,9 @@ bool QD3D12Sampler::create()
|
|||||||
desc.MaxAnisotropy = 1.0f;
|
desc.MaxAnisotropy = 1.0f;
|
||||||
desc.ComparisonFunc = toD3DTextureComparisonFunc(m_compareOp);
|
desc.ComparisonFunc = toD3DTextureComparisonFunc(m_compareOp);
|
||||||
desc.MaxLOD = m_mipmapMode == None ? 0.0f : 10000.0f;
|
desc.MaxLOD = m_mipmapMode == None ? 0.0f : 10000.0f;
|
||||||
|
|
||||||
|
QRHI_RES_RHI(QRhiD3D12);
|
||||||
|
rhiD->registerResource(this, false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4326,6 +4333,8 @@ QRhiRenderPassDescriptor *QD3D12TextureRenderTarget::newCompatibleRenderPassDesc
|
|||||||
|
|
||||||
rpD->updateSerializedFormat();
|
rpD->updateSerializedFormat();
|
||||||
|
|
||||||
|
QRHI_RES_RHI(QRhiD3D12);
|
||||||
|
rhiD->registerResource(rpD);
|
||||||
return rpD;
|
return rpD;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4499,6 +4508,10 @@ QD3D12ShaderResourceBindings::~QD3D12ShaderResourceBindings()
|
|||||||
void QD3D12ShaderResourceBindings::destroy()
|
void QD3D12ShaderResourceBindings::destroy()
|
||||||
{
|
{
|
||||||
sortedBindings.clear();
|
sortedBindings.clear();
|
||||||
|
|
||||||
|
QRHI_RES_RHI(QRhiD3D12);
|
||||||
|
if (rhiD)
|
||||||
|
rhiD->unregisterResource(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QD3D12ShaderResourceBindings::create()
|
bool QD3D12ShaderResourceBindings::create()
|
||||||
@ -4533,6 +4546,7 @@ bool QD3D12ShaderResourceBindings::create()
|
|||||||
// therefore impossible.
|
// therefore impossible.
|
||||||
|
|
||||||
generation += 1;
|
generation += 1;
|
||||||
|
rhiD->registerResource(this, false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5464,7 +5478,9 @@ QD3D12RenderPassDescriptor::~QD3D12RenderPassDescriptor()
|
|||||||
|
|
||||||
void QD3D12RenderPassDescriptor::destroy()
|
void QD3D12RenderPassDescriptor::destroy()
|
||||||
{
|
{
|
||||||
// nothing to do here
|
QRHI_RES_RHI(QRhiD3D12);
|
||||||
|
if (rhiD)
|
||||||
|
rhiD->unregisterResource(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QD3D12RenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *other) const
|
bool QD3D12RenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *other) const
|
||||||
@ -5507,13 +5523,17 @@ void QD3D12RenderPassDescriptor::updateSerializedFormat()
|
|||||||
|
|
||||||
QRhiRenderPassDescriptor *QD3D12RenderPassDescriptor::newCompatibleRenderPassDescriptor() const
|
QRhiRenderPassDescriptor *QD3D12RenderPassDescriptor::newCompatibleRenderPassDescriptor() const
|
||||||
{
|
{
|
||||||
QD3D12RenderPassDescriptor *rp = new QD3D12RenderPassDescriptor(m_rhi);
|
QD3D12RenderPassDescriptor *rpD = new QD3D12RenderPassDescriptor(m_rhi);
|
||||||
rp->colorAttachmentCount = colorAttachmentCount;
|
rpD->colorAttachmentCount = colorAttachmentCount;
|
||||||
rp->hasDepthStencil = hasDepthStencil;
|
rpD->hasDepthStencil = hasDepthStencil;
|
||||||
memcpy(rp->colorFormat, colorFormat, sizeof(colorFormat));
|
memcpy(rpD->colorFormat, colorFormat, sizeof(colorFormat));
|
||||||
rp->dsFormat = dsFormat;
|
rpD->dsFormat = dsFormat;
|
||||||
rp->updateSerializedFormat();
|
|
||||||
return rp;
|
rpD->updateSerializedFormat();
|
||||||
|
|
||||||
|
QRHI_RES_RHI(QRhiD3D12);
|
||||||
|
rhiD->registerResource(rpD);
|
||||||
|
return rpD;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector<quint32> QD3D12RenderPassDescriptor::serializedFormat() const
|
QVector<quint32> QD3D12RenderPassDescriptor::serializedFormat() const
|
||||||
@ -5756,6 +5776,9 @@ QRhiRenderPassDescriptor *QD3D12SwapChain::newCompatibleRenderPassDescriptor()
|
|||||||
rpD->colorFormat[0] = int(srgbAdjustedColorFormat);
|
rpD->colorFormat[0] = int(srgbAdjustedColorFormat);
|
||||||
rpD->dsFormat = QD3D12RenderBuffer::DS_FORMAT;
|
rpD->dsFormat = QD3D12RenderBuffer::DS_FORMAT;
|
||||||
rpD->updateSerializedFormat();
|
rpD->updateSerializedFormat();
|
||||||
|
|
||||||
|
QRHI_RES_RHI(QRhiD3D12);
|
||||||
|
rhiD->registerResource(rpD);
|
||||||
return rpD;
|
return rpD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5334,7 +5334,9 @@ QGles2Sampler::~QGles2Sampler()
|
|||||||
|
|
||||||
void QGles2Sampler::destroy()
|
void QGles2Sampler::destroy()
|
||||||
{
|
{
|
||||||
// nothing to do here
|
QRHI_RES_RHI(QRhiGles2);
|
||||||
|
if (rhiD)
|
||||||
|
rhiD->unregisterResource(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QGles2Sampler::create()
|
bool QGles2Sampler::create()
|
||||||
@ -5347,6 +5349,8 @@ bool QGles2Sampler::create()
|
|||||||
d.gltexcomparefunc = toGlTextureCompareFunc(m_compareOp);
|
d.gltexcomparefunc = toGlTextureCompareFunc(m_compareOp);
|
||||||
|
|
||||||
generation += 1;
|
generation += 1;
|
||||||
|
QRHI_RES_RHI(QRhiGles2);
|
||||||
|
rhiD->registerResource(this, false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5363,7 +5367,9 @@ QGles2RenderPassDescriptor::~QGles2RenderPassDescriptor()
|
|||||||
|
|
||||||
void QGles2RenderPassDescriptor::destroy()
|
void QGles2RenderPassDescriptor::destroy()
|
||||||
{
|
{
|
||||||
// nothing to do here
|
QRHI_RES_RHI(QRhiGles2);
|
||||||
|
if (rhiD)
|
||||||
|
rhiD->unregisterResource(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QGles2RenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *other) const
|
bool QGles2RenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *other) const
|
||||||
@ -5374,7 +5380,10 @@ bool QGles2RenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *ot
|
|||||||
|
|
||||||
QRhiRenderPassDescriptor *QGles2RenderPassDescriptor::newCompatibleRenderPassDescriptor() const
|
QRhiRenderPassDescriptor *QGles2RenderPassDescriptor::newCompatibleRenderPassDescriptor() const
|
||||||
{
|
{
|
||||||
return new QGles2RenderPassDescriptor(m_rhi);
|
QGles2RenderPassDescriptor *rpD = new QGles2RenderPassDescriptor(m_rhi);
|
||||||
|
QRHI_RES_RHI(QRhiGles2);
|
||||||
|
rhiD->registerResource(rpD, false);
|
||||||
|
return rpD;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector<quint32> QGles2RenderPassDescriptor::serializedFormat() const
|
QVector<quint32> QGles2RenderPassDescriptor::serializedFormat() const
|
||||||
@ -5447,7 +5456,10 @@ void QGles2TextureRenderTarget::destroy()
|
|||||||
|
|
||||||
QRhiRenderPassDescriptor *QGles2TextureRenderTarget::newCompatibleRenderPassDescriptor()
|
QRhiRenderPassDescriptor *QGles2TextureRenderTarget::newCompatibleRenderPassDescriptor()
|
||||||
{
|
{
|
||||||
return new QGles2RenderPassDescriptor(m_rhi);
|
QGles2RenderPassDescriptor *rpD = new QGles2RenderPassDescriptor(m_rhi);
|
||||||
|
QRHI_RES_RHI(QRhiGles2);
|
||||||
|
rhiD->registerResource(rpD, false);
|
||||||
|
return rpD;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QGles2TextureRenderTarget::create()
|
bool QGles2TextureRenderTarget::create()
|
||||||
@ -5594,7 +5606,9 @@ QGles2ShaderResourceBindings::~QGles2ShaderResourceBindings()
|
|||||||
|
|
||||||
void QGles2ShaderResourceBindings::destroy()
|
void QGles2ShaderResourceBindings::destroy()
|
||||||
{
|
{
|
||||||
// nothing to do here
|
QRHI_RES_RHI(QRhiGles2);
|
||||||
|
if (rhiD)
|
||||||
|
rhiD->unregisterResource(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QGles2ShaderResourceBindings::create()
|
bool QGles2ShaderResourceBindings::create()
|
||||||
@ -5617,6 +5631,7 @@ bool QGles2ShaderResourceBindings::create()
|
|||||||
rhiD->updateLayoutDesc(this);
|
rhiD->updateLayoutDesc(this);
|
||||||
|
|
||||||
generation += 1;
|
generation += 1;
|
||||||
|
rhiD->registerResource(this, false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5981,7 +5996,10 @@ bool QGles2SwapChain::isFormatSupported(Format f)
|
|||||||
|
|
||||||
QRhiRenderPassDescriptor *QGles2SwapChain::newCompatibleRenderPassDescriptor()
|
QRhiRenderPassDescriptor *QGles2SwapChain::newCompatibleRenderPassDescriptor()
|
||||||
{
|
{
|
||||||
return new QGles2RenderPassDescriptor(m_rhi);
|
QGles2RenderPassDescriptor *rpD = new QGles2RenderPassDescriptor(m_rhi);
|
||||||
|
QRHI_RES_RHI(QRhiGles2);
|
||||||
|
rhiD->registerResource(rpD, false);
|
||||||
|
return rpD;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QGles2SwapChain::initSwapChainRenderTarget(QGles2SwapChainRenderTarget *rt)
|
void QGles2SwapChain::initSwapChainRenderTarget(QGles2SwapChainRenderTarget *rt)
|
||||||
@ -6030,7 +6048,7 @@ bool QGles2SwapChain::createOrResize()
|
|||||||
// implement a safe destroy().
|
// implement a safe destroy().
|
||||||
if (needsRegistration) {
|
if (needsRegistration) {
|
||||||
QRHI_RES_RHI(QRhiGles2);
|
QRHI_RES_RHI(QRhiGles2);
|
||||||
rhiD->registerResource(this);
|
rhiD->registerResource(this, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -3930,7 +3930,9 @@ QMetalRenderPassDescriptor::~QMetalRenderPassDescriptor()
|
|||||||
|
|
||||||
void QMetalRenderPassDescriptor::destroy()
|
void QMetalRenderPassDescriptor::destroy()
|
||||||
{
|
{
|
||||||
// nothing to do here
|
QRHI_RES_RHI(QRhiMetal);
|
||||||
|
if (rhiD)
|
||||||
|
rhiD->unregisterResource(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QMetalRenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *other) const
|
bool QMetalRenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *other) const
|
||||||
@ -3973,13 +3975,17 @@ void QMetalRenderPassDescriptor::updateSerializedFormat()
|
|||||||
|
|
||||||
QRhiRenderPassDescriptor *QMetalRenderPassDescriptor::newCompatibleRenderPassDescriptor() const
|
QRhiRenderPassDescriptor *QMetalRenderPassDescriptor::newCompatibleRenderPassDescriptor() const
|
||||||
{
|
{
|
||||||
QMetalRenderPassDescriptor *rp = new QMetalRenderPassDescriptor(m_rhi);
|
QMetalRenderPassDescriptor *rpD = new QMetalRenderPassDescriptor(m_rhi);
|
||||||
rp->colorAttachmentCount = colorAttachmentCount;
|
rpD->colorAttachmentCount = colorAttachmentCount;
|
||||||
rp->hasDepthStencil = hasDepthStencil;
|
rpD->hasDepthStencil = hasDepthStencil;
|
||||||
memcpy(rp->colorFormat, colorFormat, sizeof(colorFormat));
|
memcpy(rpD->colorFormat, colorFormat, sizeof(colorFormat));
|
||||||
rp->dsFormat = dsFormat;
|
rpD->dsFormat = dsFormat;
|
||||||
rp->updateSerializedFormat();
|
|
||||||
return rp;
|
rpD->updateSerializedFormat();
|
||||||
|
|
||||||
|
QRHI_RES_RHI(QRhiMetal);
|
||||||
|
rhiD->registerResource(rpD, false);
|
||||||
|
return rpD;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector<quint32> QMetalRenderPassDescriptor::serializedFormat() const
|
QVector<quint32> QMetalRenderPassDescriptor::serializedFormat() const
|
||||||
@ -4035,7 +4041,9 @@ QMetalTextureRenderTarget::~QMetalTextureRenderTarget()
|
|||||||
|
|
||||||
void QMetalTextureRenderTarget::destroy()
|
void QMetalTextureRenderTarget::destroy()
|
||||||
{
|
{
|
||||||
// nothing to do here
|
QRHI_RES_RHI(QRhiMetal);
|
||||||
|
if (rhiD)
|
||||||
|
rhiD->unregisterResource(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
QRhiRenderPassDescriptor *QMetalTextureRenderTarget::newCompatibleRenderPassDescriptor()
|
QRhiRenderPassDescriptor *QMetalTextureRenderTarget::newCompatibleRenderPassDescriptor()
|
||||||
@ -4058,6 +4066,9 @@ QRhiRenderPassDescriptor *QMetalTextureRenderTarget::newCompatibleRenderPassDesc
|
|||||||
rpD->dsFormat = int(QRHI_RES(QMetalRenderBuffer, m_desc.depthStencilBuffer())->d->format);
|
rpD->dsFormat = int(QRHI_RES(QMetalRenderBuffer, m_desc.depthStencilBuffer())->d->format);
|
||||||
|
|
||||||
rpD->updateSerializedFormat();
|
rpD->updateSerializedFormat();
|
||||||
|
|
||||||
|
QRHI_RES_RHI(QRhiMetal);
|
||||||
|
rhiD->registerResource(rpD, false);
|
||||||
return rpD;
|
return rpD;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4131,6 +4142,7 @@ bool QMetalTextureRenderTarget::create()
|
|||||||
|
|
||||||
QRhiRenderTargetAttachmentTracker::updateResIdList<QMetalTexture, QMetalRenderBuffer>(m_desc, &d->currentResIdList);
|
QRhiRenderTargetAttachmentTracker::updateResIdList<QMetalTexture, QMetalRenderBuffer>(m_desc, &d->currentResIdList);
|
||||||
|
|
||||||
|
rhiD->registerResource(this, false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4166,6 +4178,10 @@ void QMetalShaderResourceBindings::destroy()
|
|||||||
{
|
{
|
||||||
sortedBindings.clear();
|
sortedBindings.clear();
|
||||||
maxBinding = -1;
|
maxBinding = -1;
|
||||||
|
|
||||||
|
QRHI_RES_RHI(QRhiMetal);
|
||||||
|
if (rhiD)
|
||||||
|
rhiD->unregisterResource(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QMetalShaderResourceBindings::create()
|
bool QMetalShaderResourceBindings::create()
|
||||||
@ -4192,6 +4208,7 @@ bool QMetalShaderResourceBindings::create()
|
|||||||
memset(&bd, 0, sizeof(BoundResourceData));
|
memset(&bd, 0, sizeof(BoundResourceData));
|
||||||
|
|
||||||
generation += 1;
|
generation += 1;
|
||||||
|
rhiD->registerResource(this, false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6053,6 +6070,8 @@ bool QMetalSwapChain::isFormatSupported(Format f)
|
|||||||
|
|
||||||
QRhiRenderPassDescriptor *QMetalSwapChain::newCompatibleRenderPassDescriptor()
|
QRhiRenderPassDescriptor *QMetalSwapChain::newCompatibleRenderPassDescriptor()
|
||||||
{
|
{
|
||||||
|
QRHI_RES_RHI(QRhiMetal);
|
||||||
|
|
||||||
chooseFormats(); // ensure colorFormat and similar are filled out
|
chooseFormats(); // ensure colorFormat and similar are filled out
|
||||||
|
|
||||||
QMetalRenderPassDescriptor *rpD = new QMetalRenderPassDescriptor(m_rhi);
|
QMetalRenderPassDescriptor *rpD = new QMetalRenderPassDescriptor(m_rhi);
|
||||||
@ -6063,7 +6082,6 @@ QRhiRenderPassDescriptor *QMetalSwapChain::newCompatibleRenderPassDescriptor()
|
|||||||
|
|
||||||
#ifdef Q_OS_MACOS
|
#ifdef Q_OS_MACOS
|
||||||
// m_depthStencil may not be built yet so cannot rely on computed fields in it
|
// m_depthStencil may not be built yet so cannot rely on computed fields in it
|
||||||
QRHI_RES_RHI(QRhiMetal);
|
|
||||||
rpD->dsFormat = rhiD->d->dev.depth24Stencil8PixelFormatSupported
|
rpD->dsFormat = rhiD->d->dev.depth24Stencil8PixelFormatSupported
|
||||||
? MTLPixelFormatDepth24Unorm_Stencil8 : MTLPixelFormatDepth32Float_Stencil8;
|
? MTLPixelFormatDepth24Unorm_Stencil8 : MTLPixelFormatDepth32Float_Stencil8;
|
||||||
#else
|
#else
|
||||||
@ -6071,6 +6089,8 @@ QRhiRenderPassDescriptor *QMetalSwapChain::newCompatibleRenderPassDescriptor()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
rpD->updateSerializedFormat();
|
rpD->updateSerializedFormat();
|
||||||
|
|
||||||
|
rhiD->registerResource(rpD, false);
|
||||||
return rpD;
|
return rpD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -716,10 +716,15 @@ QNullSampler::~QNullSampler()
|
|||||||
|
|
||||||
void QNullSampler::destroy()
|
void QNullSampler::destroy()
|
||||||
{
|
{
|
||||||
|
QRHI_RES_RHI(QRhiNull);
|
||||||
|
if (rhiD)
|
||||||
|
rhiD->unregisterResource(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QNullSampler::create()
|
bool QNullSampler::create()
|
||||||
{
|
{
|
||||||
|
QRHI_RES_RHI(QRhiNull);
|
||||||
|
rhiD->registerResource(this);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -735,6 +740,9 @@ QNullRenderPassDescriptor::~QNullRenderPassDescriptor()
|
|||||||
|
|
||||||
void QNullRenderPassDescriptor::destroy()
|
void QNullRenderPassDescriptor::destroy()
|
||||||
{
|
{
|
||||||
|
QRHI_RES_RHI(QRhiNull);
|
||||||
|
if (rhiD)
|
||||||
|
rhiD->unregisterResource(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QNullRenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *other) const
|
bool QNullRenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *other) const
|
||||||
@ -745,7 +753,10 @@ bool QNullRenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *oth
|
|||||||
|
|
||||||
QRhiRenderPassDescriptor *QNullRenderPassDescriptor::newCompatibleRenderPassDescriptor() const
|
QRhiRenderPassDescriptor *QNullRenderPassDescriptor::newCompatibleRenderPassDescriptor() const
|
||||||
{
|
{
|
||||||
return new QNullRenderPassDescriptor(m_rhi);
|
QNullRenderPassDescriptor *rpD = new QNullRenderPassDescriptor(m_rhi);
|
||||||
|
QRHI_RES_RHI(QRhiNull);
|
||||||
|
rhiD->registerResource(rpD, false);
|
||||||
|
return rpD;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector<quint32> QNullRenderPassDescriptor::serializedFormat() const
|
QVector<quint32> QNullRenderPassDescriptor::serializedFormat() const
|
||||||
@ -798,11 +809,17 @@ QNullTextureRenderTarget::~QNullTextureRenderTarget()
|
|||||||
|
|
||||||
void QNullTextureRenderTarget::destroy()
|
void QNullTextureRenderTarget::destroy()
|
||||||
{
|
{
|
||||||
|
QRHI_RES_RHI(QRhiNull);
|
||||||
|
if (rhiD)
|
||||||
|
rhiD->unregisterResource(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
QRhiRenderPassDescriptor *QNullTextureRenderTarget::newCompatibleRenderPassDescriptor()
|
QRhiRenderPassDescriptor *QNullTextureRenderTarget::newCompatibleRenderPassDescriptor()
|
||||||
{
|
{
|
||||||
return new QNullRenderPassDescriptor(m_rhi);
|
QNullRenderPassDescriptor *rpD = new QNullRenderPassDescriptor(m_rhi);
|
||||||
|
QRHI_RES_RHI(QRhiNull);
|
||||||
|
rhiD->registerResource(rpD, false);
|
||||||
|
return rpD;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QNullTextureRenderTarget::create()
|
bool QNullTextureRenderTarget::create()
|
||||||
@ -820,6 +837,7 @@ bool QNullTextureRenderTarget::create()
|
|||||||
d.pixelSize = m_desc.depthTexture()->pixelSize();
|
d.pixelSize = m_desc.depthTexture()->pixelSize();
|
||||||
}
|
}
|
||||||
QRhiRenderTargetAttachmentTracker::updateResIdList<QNullTexture, QNullRenderBuffer>(m_desc, &d.currentResIdList);
|
QRhiRenderTargetAttachmentTracker::updateResIdList<QNullTexture, QNullRenderBuffer>(m_desc, &d.currentResIdList);
|
||||||
|
rhiD->registerResource(this);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -853,6 +871,9 @@ QNullShaderResourceBindings::~QNullShaderResourceBindings()
|
|||||||
|
|
||||||
void QNullShaderResourceBindings::destroy()
|
void QNullShaderResourceBindings::destroy()
|
||||||
{
|
{
|
||||||
|
QRHI_RES_RHI(QRhiNull);
|
||||||
|
if (rhiD)
|
||||||
|
rhiD->unregisterResource(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QNullShaderResourceBindings::create()
|
bool QNullShaderResourceBindings::create()
|
||||||
@ -863,6 +884,7 @@ bool QNullShaderResourceBindings::create()
|
|||||||
|
|
||||||
rhiD->updateLayoutDesc(this);
|
rhiD->updateLayoutDesc(this);
|
||||||
|
|
||||||
|
rhiD->registerResource(this, false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -883,6 +905,9 @@ QNullGraphicsPipeline::~QNullGraphicsPipeline()
|
|||||||
|
|
||||||
void QNullGraphicsPipeline::destroy()
|
void QNullGraphicsPipeline::destroy()
|
||||||
{
|
{
|
||||||
|
QRHI_RES_RHI(QRhiNull);
|
||||||
|
if (rhiD)
|
||||||
|
rhiD->unregisterResource(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QNullGraphicsPipeline::create()
|
bool QNullGraphicsPipeline::create()
|
||||||
@ -891,6 +916,7 @@ bool QNullGraphicsPipeline::create()
|
|||||||
if (!rhiD->sanityCheckGraphicsPipeline(this))
|
if (!rhiD->sanityCheckGraphicsPipeline(this))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
rhiD->registerResource(this);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -906,10 +932,15 @@ QNullComputePipeline::~QNullComputePipeline()
|
|||||||
|
|
||||||
void QNullComputePipeline::destroy()
|
void QNullComputePipeline::destroy()
|
||||||
{
|
{
|
||||||
|
QRHI_RES_RHI(QRhiNull);
|
||||||
|
if (rhiD)
|
||||||
|
rhiD->unregisterResource(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QNullComputePipeline::create()
|
bool QNullComputePipeline::create()
|
||||||
{
|
{
|
||||||
|
QRHI_RES_RHI(QRhiNull);
|
||||||
|
rhiD->registerResource(this);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -969,7 +1000,10 @@ bool QNullSwapChain::isFormatSupported(Format f)
|
|||||||
|
|
||||||
QRhiRenderPassDescriptor *QNullSwapChain::newCompatibleRenderPassDescriptor()
|
QRhiRenderPassDescriptor *QNullSwapChain::newCompatibleRenderPassDescriptor()
|
||||||
{
|
{
|
||||||
return new QNullRenderPassDescriptor(m_rhi);
|
QNullRenderPassDescriptor *rpD = new QNullRenderPassDescriptor(m_rhi);
|
||||||
|
QRHI_RES_RHI(QRhiNull);
|
||||||
|
rhiD->registerResource(rpD, false);
|
||||||
|
return rpD;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QNullSwapChain::createOrResize()
|
bool QNullSwapChain::createOrResize()
|
||||||
|
@ -5450,12 +5450,36 @@ void tst_QRhi::leakedResourceDestroy()
|
|||||||
rt->setRenderPassDescriptor(rpDesc.data());
|
rt->setRenderPassDescriptor(rpDesc.data());
|
||||||
QVERIFY(rt->create());
|
QVERIFY(rt->create());
|
||||||
|
|
||||||
|
QRhiRenderBuffer *rb = rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil, QSize(512, 512));
|
||||||
|
QVERIFY(rb->create());
|
||||||
|
|
||||||
|
QRhiShaderResourceBindings *srb = rhi->newShaderResourceBindings();
|
||||||
|
QVERIFY(srb->create());
|
||||||
|
|
||||||
if (impl == QRhi::Vulkan)
|
if (impl == QRhi::Vulkan)
|
||||||
qDebug("Vulkan validation layer warnings may be printed below - this is expected");
|
qDebug("Vulkan validation layer warnings may be printed below - this is expected");
|
||||||
|
|
||||||
|
if (impl == QRhi::D3D12)
|
||||||
|
qDebug("QD3D12CpuDescriptorPool warnings may be printed below - this is expected");
|
||||||
|
|
||||||
|
qDebug("QRhi resource leak check warnings may be printed below - this is expected");
|
||||||
|
|
||||||
|
// make the QRhi go away early
|
||||||
rhi.reset();
|
rhi.reset();
|
||||||
|
|
||||||
// let the scoped ptr do its job with the resources
|
// see if the internal rhi backpointer got nulled out
|
||||||
|
QVERIFY(buffer->rhi() == nullptr);
|
||||||
|
QVERIFY(texture->rhi() == nullptr);
|
||||||
|
QVERIFY(rt->rhi() == nullptr);
|
||||||
|
QVERIFY(rpDesc->rhi() == nullptr);
|
||||||
|
QVERIFY(rb->rhi() == nullptr);
|
||||||
|
QVERIFY(srb->rhi() == nullptr);
|
||||||
|
|
||||||
|
// test out deleteLater on some of the resources
|
||||||
|
rb->deleteLater();
|
||||||
|
srb->deleteLater();
|
||||||
|
|
||||||
|
// let the scoped ptr do its job with the rest
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QRhi::renderToFloatTexture_data()
|
void tst_QRhi::renderToFloatTexture_data()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user