[vlc-commits] [Git][videolan/vlc][master] qt: fallback to d3d warp through rhi before qt's own software mode
Felix Paul Kühne (@fkuehne)
gitlab at videolan.org
Thu Mar 19 10:11:31 UTC 2026
Felix Paul Kühne pushed to branch master at VideoLAN / VLC
Commits:
c01a7eb9 by Fatih Uzunoglu at 2026-03-19T10:08:15+01:00
qt: fallback to d3d warp through rhi before qt's own software mode
Qt's own software mode is really primitive, it can be used as the
absolute last resort.
- - - - -
1 changed file:
- modules/gui/qt/qt.cpp
Changes:
=====================================
modules/gui/qt/qt.cpp
=====================================
@@ -961,36 +961,80 @@ static void *Thread( void *obj )
// NOTE: Qt Quick does not have a cross-API RHI fallback procedure (as of Qt 6.7.1).
// We have to manually pick a graphics api here, since the default graphics
// api (Direct3D 11.2) may not be supported.
- static const auto probeRhi = []() -> QSGRendererInterface::GraphicsApi {
- QSGRendererInterface::GraphicsApi graphicsApi = QSGRendererInterface::OpenGL;
- // TODO: Probe D3D12 when it becomes the default.
- QRhiD3D11InitParams params;
- if (QRhi::probe(QRhi::D3D11, ¶ms))
- graphicsApi = QSGRendererInterface::Direct3D11;
- else
+ static const auto probeRhi = []() -> QPair<QSGRendererInterface::GraphicsApi,
+ bool /* software through rhi, such as d3d warp */> {
+
+ // TODO: Investigate if we should use D3D12. Currently it is not the default by
+ // Qt (as of Qt 6.8), and is not as battle tested as the default D3D11.
+
{
- QRhiGles2InitParams params1;
- params1.fallbackSurface = QRhiGles2InitParams::newFallbackSurface();
- if (!QRhi::probe(QRhi::OpenGLES2, ¶ms1))
- graphicsApi = QSGRendererInterface::Software;
- delete params1.fallbackSurface;
+ QRhiD3D11InitParams params;
+ if (QRhi::probe(QRhi::D3D11, ¶ms))
+ {
+ return {QSGRendererInterface::Direct3D11, false};
+ }
}
- return graphicsApi;
+
+ {
+ QRhiGles2InitParams params;
+ params.fallbackSurface = QRhiGles2InitParams::newFallbackSurface();
+ if (QRhi::probe(QRhi::OpenGLES2, ¶ms))
+ {
+ delete params.fallbackSurface;
+ return {QSGRendererInterface::OpenGL, false};
+ }
+ delete params.fallbackSurface;
+ }
+
+ // TODO: Investigate if using Vulkan makes sense on Windows.
+ // TODO: Investigate if it makes sense to try D3D12 when probing D3D11 failed.
+
+ {
+ // D3D11 Warp:
+
+ // `QRhi::probe()` does not accept rhi flags, but we can use `QRhi::create()`
+ // to see if DirectX Warp would be functional. This is essentially the same
+ // as what `::probe()` does, at least for DirectX:
+ QRhiD3D11InitParams params;
+ QRhi *rhi = QRhi::create(QRhi::D3D11, ¶ms, QRhi::PreferSoftwareRenderer);
+ if (rhi)
+ {
+ delete rhi;
+ return {QSGRendererInterface::Direct3D11, true};
+ }
+ }
+
+ // Qt's own software renderer, it can not display shader effects and is very
+ // primitive. Used as last resort:
+ return {QSGRendererInterface::Software, false};
};
static const char* const asyncRhiProbeCompletedProperty = "asyncRhiProbeCompleted";
// NOTE: `QSettings` accepts `QAnyStringView` starting from Qt 6.4, use `QLatin1String(View)`:
static constexpr QLatin1String graphicsApiKey {"graphics-api"};
+ static constexpr QLatin1String graphicsApiRhiSoftwareKey {"graphics-api-rhi-software"};
if (qEnvironmentVariableIsEmpty("QSG_RHI_BACKEND") &&
qEnvironmentVariableIsEmpty("QT_QUICK_BACKEND") &&
(QT_VERSION < QT_VERSION_CHECK(6, 4, 0) || !uint(qEnvironmentVariableIntValue("QSG_RHI_PREFER_SOFTWARE_RENDERER"))))
{
+ const auto enableRhiSoftwareRenderer = []() {
+ // We could use `QQuickGraphicsConfiguration::setPreferSoftwareDevice()`, but this
+ // is more convenient. We do not need to check if it is already explicitly set by
+ // the user, because that is already done above.
+ qWarning() << "Qt RHI can not use hardware acceleration, software renderer (such "
+ "as D3D Warp) through rhi is going to be used.";
+ qputenv("QSG_RHI_PREFER_SOFTWARE_RENDERER", QByteArrayLiteral("1"));
+ };
+
const QVariant graphicsApiValue = p_intf->mainSettings->value(graphicsApiKey);
// settings value can be string (ini file), do not use `typeId()`:
if (graphicsApiValue.isValid() && Q_LIKELY(graphicsApiValue.canConvert<int>()))
{
// A cached (by then) valid graphics api is found, use it:
QQuickWindow::setGraphicsApi(static_cast<QSGRendererInterface::GraphicsApi>(graphicsApiValue.value<int>()));
+ if (p_intf->mainSettings->value(graphicsApiRhiSoftwareKey).value<bool>())
+ enableRhiSoftwareRenderer();
+
// Asynchronous re-probe to see if the cached graphics api is still applicable.
// If not, QQuickWindow is going to emit scene graph error, and the application is
// likely going to terminate. However, when the user starts the application again
@@ -1007,14 +1051,20 @@ static void *Thread( void *obj )
// startup will use the refreshed value. That's the best we can do here
// without forcing QQuickWindow to wait (hence delaying startup).
assert(settings);
- settings->setValue(graphicsApiKey, static_cast<int>(probeRhi()));
+ const auto rhiResult = probeRhi();
+ settings->setValue(graphicsApiKey, static_cast<int>(rhiResult.first));
+ settings->setValue(graphicsApiRhiSoftwareKey, rhiResult.second);
settings->sync();
app.setProperty(asyncRhiProbeCompletedProperty, true);
}, Qt::QueuedConnection); // Asynchronous, so probing here does not cause start-up slowdown.
}
else
{
- const QSGRendererInterface::GraphicsApi graphicsApi = probeRhi();
+ const auto rhiResult = probeRhi();
+ if (rhiResult.second)
+ enableRhiSoftwareRenderer();
+
+ const QSGRendererInterface::GraphicsApi graphicsApi = rhiResult.first;
QQuickWindow::setGraphicsApi(graphicsApi);
p_intf->mainSettings->setValue(graphicsApiKey, static_cast<int>(graphicsApi));
p_intf->mainSettings->sync();
View it on GitLab: https://code.videolan.org/videolan/vlc/-/commit/c01a7eb9559c1804930e1d836997e8a2c8ef3645
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/commit/c01a7eb9559c1804930e1d836997e8a2c8ef3645
You're receiving this email because of your account on code.videolan.org.
More information about the vlc-commits
mailing list