aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/scenegraph/qsgthreadedrenderloop.cpp
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2024-02-26 17:29:11 +0100
committerLaszlo Agocs <laszlo.agocs@qt.io>2024-02-29 12:08:08 +0100
commit96299182fbc0b11a89ef153bce5be8268b9d87dd (patch)
tree7e05fde745cd505d34b4aba997cbca45cd3a578e /src/quick/scenegraph/qsgthreadedrenderloop.cpp
parentd7575ae2a750173786d0d98b7b9b3cc9893ac15c (diff)
Fall back to retrying with "software" when swapchain fails
The idea being that a swapchain creation failure would end up behaving the same as as the QRhi::create() failure, in particular on Windows: for the latter we automatically retry with PreferSwRenderer set (i.e. requesting WARP), but until now this has not been done upon swapchain creation failures. (it is not clear under what circumstances we fail to create a swapchain, but reports from Qt-based applications indicate that this is happening out in the wild) If the first swapchain creation attempt fails, do what a device loss would do: drop everything, incl. the QRhi, and post a special event to the main thread do request a new round of rendering, upon which we'll attempt to reinitialize a QRhi and everything else in the scenegraph. We then recognize the flag and pass it on to QSGRhiSupport to indicate we want a software-backed adapter / physical device, if there is one. We won't retry afterwards if that fails too. This may also correct issues with device loss handling which did not correctly wake up the main thread. [ChangeLog][Qt Quick] The fallback to a software rasterizer, if applicable to the platform and 3D API, is now performed also upon the first swapchain creation failure. Previously this was only done if the QRhi initialization failed. Relevant in particular on Windows, potentially allowing functioning on systems that are incapable of proper accelerated D3D rendering, but, for whatever reason, do not fail early on upon the device/context creation, only later at swapchain creation. Pick-to: 6.7 6.6 6.5 Fixes: QTBUG-109708 Fixes: QTBUG-101200 Change-Id: I76f4aa132361d8f97ec6edfb3bf7806b4ce015b1 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Andy Nichols <andy.nichols@qt.io>
Diffstat (limited to 'src/quick/scenegraph/qsgthreadedrenderloop.cpp')
-rw-r--r--src/quick/scenegraph/qsgthreadedrenderloop.cpp50
1 files changed, 39 insertions, 11 deletions
diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
index 45a62022c4..a405099534 100644
--- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp
+++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
@@ -280,6 +280,7 @@ public:
};
void ensureRhi();
+ void teardownGraphics();
void handleDeviceLoss();
QSGThreadedRenderLoop *wm;
@@ -309,6 +310,7 @@ public:
bool rhiDeviceLost = false;
bool rhiDoomed = false;
bool guiNotifiedAboutRhiFailure = false;
+ bool swRastFallbackDueToSwapchainFailure = false;
// Local event queue stuff...
bool stopEventProcessing;
@@ -575,22 +577,27 @@ void QSGRenderThread::sync(bool inExpose)
}
}
-void QSGRenderThread::handleDeviceLoss()
+void QSGRenderThread::teardownGraphics()
{
- if (!rhi || !rhi->isDeviceLost())
- return;
-
- qWarning("Graphics device lost, cleaning up scenegraph and releasing RHI");
QQuickWindowPrivate *wd = QQuickWindowPrivate::get(window);
wd->cleanupNodesOnShutdown();
sgrc->invalidate();
wm->releaseSwapchain(window);
- rhiDeviceLost = true;
if (ownRhi)
QSGRhiSupport::instance()->destroyRhi(rhi, {});
rhi = nullptr;
}
+void QSGRenderThread::handleDeviceLoss()
+{
+ if (!rhi || !rhi->isDeviceLost())
+ return;
+
+ qWarning("Graphics device lost, cleaning up scenegraph and releasing RHI");
+ teardownGraphics();
+ rhiDeviceLost = true;
+}
+
void QSGRenderThread::syncAndRender()
{
const bool profileFrames = QSG_LOG_TIME_RENDERLOOP().isDebugEnabled();
@@ -620,6 +627,7 @@ void QSGRenderThread::syncAndRender()
pendingUpdate = 0;
QQuickWindowPrivate *cd = QQuickWindowPrivate::get(window);
+ QSGRhiSupport *rhiSupport = QSGRhiSupport::instance();
// Begin the frame before syncing -> sync is where we may invoke
// updatePaintNode() on the items and they may want to do resource updates.
// Also relevant for applications that connect to the before/afterSynchronizing
@@ -641,10 +649,29 @@ void QSGRenderThread::syncAndRender()
qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "just became exposed");
cd->hasActiveSwapchain = cd->swapchain->createOrResize();
- if (!cd->hasActiveSwapchain && rhi->isDeviceLost()) {
- handleDeviceLoss();
- QCoreApplication::postEvent(window, new QEvent(QEvent::Type(QQuickWindowPrivate::FullUpdateRequest)));
- return;
+ if (!cd->hasActiveSwapchain) {
+ bool bailOut = false;
+ if (rhi->isDeviceLost()) {
+ handleDeviceLoss();
+ bailOut = true;
+ } else if (previousOutputSize.isEmpty() && !swRastFallbackDueToSwapchainFailure && rhiSupport->attemptReinitWithSwRastUponFail()) {
+ qWarning("Failed to create swapchain."
+ " Retrying by requesting a software rasterizer, if applicable for the 3D API implementation.");
+ swRastFallbackDueToSwapchainFailure = true;
+ teardownGraphics();
+ bailOut = true;
+ }
+ if (bailOut) {
+ QCoreApplication::postEvent(window, new QEvent(QEvent::Type(QQuickWindowPrivate::FullUpdateRequest)));
+ if (syncRequested) {
+ // Lock like sync() would do. Note that exposeRequested always includes syncRequested.
+ qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- bailing out due to failed swapchain init, wake Gui");
+ mutex.lock();
+ waitCondition.wakeOne();
+ mutex.unlock();
+ }
+ return;
+ }
}
cd->swapchainJustBecameRenderable = false;
@@ -851,7 +878,8 @@ void QSGRenderThread::ensureRhi()
if (rhiDoomed) // no repeated attempts if the initial attempt failed
return;
QSGRhiSupport *rhiSupport = QSGRhiSupport::instance();
- QSGRhiSupport::RhiCreateResult rhiResult = rhiSupport->createRhi(window, offscreenSurface);
+ const bool forcePreferSwRenderer = swRastFallbackDueToSwapchainFailure;
+ QSGRhiSupport::RhiCreateResult rhiResult = rhiSupport->createRhi(window, offscreenSurface, forcePreferSwRenderer);
rhi = rhiResult.rhi;
ownRhi = rhiResult.own;
if (rhi) {