From b594374ba84da986c5ebc93984961040338465d0 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 27 Jul 2021 19:42:27 +0200 Subject: rhi: Be more graceful when one destroys a resource after the QRhi One is a bad application or library in this case, but nonetheless we should handle this more gracefully then just crashing due to the QRhi already having been destroyed. Mainly because in Qt 5 one could get away with the same: releasing OpenGL objects underneath, for example, a QSGPlainTexture with no (or wrong) GL context did not generate any user visible fatal errors. So we should not crash in Qt 6 either with these code bases. In debug builds or when QT_RHI_LEAK_CHECK is set, one will get the unreleased resources warning printed in Qt 6, which is a step forward compared to Qt 5. So there is still some indication that something is badly designed, even if the application survives. Task-number: QTBUG-95394 Pick-to: 6.2 Change-Id: I944f4f425ff126e7363a82aff926b280ccf1dfc3 Reviewed-by: Qt CI Bot Reviewed-by: Andy Nichols --- tests/auto/gui/rhi/qrhi/tst_qrhi.cpp | 49 ++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) (limited to 'tests/auto/gui/rhi') diff --git a/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp b/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp index 8b6f55b3b6..be825c8ac2 100644 --- a/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp +++ b/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp @@ -137,6 +137,8 @@ private slots: void renderbufferImportOpenGL(); void threeDimTexture_data(); void threeDimTexture(); + void leakedResourceDestroy_data(); + void leakedResourceDestroy(); private: void setWindowType(QWindow *window, QRhi::Implementation impl); @@ -3985,5 +3987,52 @@ void tst_QRhi::threeDimTexture() } } +void tst_QRhi::leakedResourceDestroy_data() +{ + rhiTestData(); +} + +void tst_QRhi::leakedResourceDestroy() +{ + QFETCH(QRhi::Implementation, impl); + QFETCH(QRhiInitParams *, initParams); + + QScopedPointer rhi(QRhi::create(impl, initParams)); + if (!rhi) + QSKIP("QRhi could not be created, skipping"); + + // Incorrectly destroy the QRhi before the resources created from it. Attempting to + // destroy the resources afterwards is pointless, the native resources are leaked. + // Nonetheless, it should not crash, which is what we are testing here. + // + // We do not however have control over other, native and 3rd party components: a + // validation or debug layer, or a memory allocator may warn, assert, or abort when + // not releasing all native resources correctly. +#ifndef QT_NO_DEBUG + // don't want asserts from vkmemalloc, skip the test in debug builds + if (impl == QRhi::Vulkan) + QSKIP("Skipping leaked resource destroy test due to Vulkan and debug build"); +#endif + + QScopedPointer buffer(rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, 256)); + QVERIFY(buffer->create()); + + QScopedPointer texture(rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512), 1, QRhiTexture::RenderTarget)); + QVERIFY(texture->create()); + + QScopedPointer rt(rhi->newTextureRenderTarget({ texture.data() })); + QScopedPointer rpDesc(rt->newCompatibleRenderPassDescriptor()); + QVERIFY(rpDesc); + rt->setRenderPassDescriptor(rpDesc.data()); + QVERIFY(rt->create()); + + if (impl == QRhi::Vulkan) + qDebug("Vulkan validation layer warnings may be printed below - this is expected"); + + rhi.reset(); + + // let the scoped ptr do its job with the resources +} + #include QTEST_MAIN(tst_QRhi) -- cgit v1.2.3