summaryrefslogtreecommitdiffstats
path: root/src/gui/rhi
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2022-02-04 22:05:35 +0100
committerLaszlo Agocs <laszlo.agocs@qt.io>2022-02-09 14:02:57 +0100
commit178c1a6243b556fe580047f716e7a0399a1597fa (patch)
treefb0287166d617005c04b17b44eb88ddf78bddbae /src/gui/rhi
parent1f93ff529b2463316417bc227645a1f3899759ff (diff)
rhi: Add the long-pending probe() helper, with backing for Metal
There is a TODO for this in Qt Quick from the 6.0 times. To decide upfront if Metal can be expected to function, or if a fallback to OpenGL needs to be triggered (especially important with macOS virtual machines, where, unlike any real macOS system, Metal may not be present at all), the scenegraph calls create() and then drops the result. The idea to make this less wasteful was back then to add a dedicated probing function which can, possibly, perform the checks in a more lightweight manner than full initialization. Implement this now, focusing on Metal. Brought to attention by QTBUG-100441: printing warnings about not having an MTLDevice is confusing in a Metal-less macOS VM, because it is not an actual error, only part of the probing at scenegraph initialization. We can now avoid printing confusing warnings there. Change-Id: Ie52c36af9224bedc3f5e4c23edb486d961c9f216 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Andy Nichols <andy.nichols@qt.io>
Diffstat (limited to 'src/gui/rhi')
-rw-r--r--src/gui/rhi/qrhi.cpp48
-rw-r--r--src/gui/rhi/qrhi_p.h1
-rw-r--r--src/gui/rhi/qrhimetal.mm11
-rw-r--r--src/gui/rhi/qrhimetal_p_p.h2
4 files changed, 62 insertions, 0 deletions
diff --git a/src/gui/rhi/qrhi.cpp b/src/gui/rhi/qrhi.cpp
index 6058dd3a55..d62b2eea61 100644
--- a/src/gui/rhi/qrhi.cpp
+++ b/src/gui/rhi/qrhi.cpp
@@ -5288,6 +5288,20 @@ QRhi::~QRhi()
subclasses of QRhiInitParams, such as, QRhiVulkanInitParams,
QRhiMetalInitParams, QRhiD3D11InitParams, QRhiGles2InitParams. See these
classes for examples on creating a QRhi.
+
+ QRhi by design does not implement any fallback logic: if the specified API
+ cannot be initialized, create() will fail, with warnings printed on the
+ debug output by the backends. The clients of QRhi, for example Qt Quick,
+ may however provide additional logic that allow falling back to an API
+ different than what was requested, depending on the platform. If the
+ intention is just to test if initialization would succeed when calling
+ create() at later point, it is preferable to use probe() instead of
+ create(), because with some backends probing can be implemented in a more
+ lightweight manner as opposed to create(), which performs full
+ initialization of the infrastructure and is wasteful if that QRhi instance
+ is then thrown immediately away.
+
+ \sa probe()
*/
QRhi *QRhi::create(Implementation impl, QRhiInitParams *params, Flags flags, QRhiNativeHandles *importDevice)
{
@@ -5358,6 +5372,40 @@ QRhi *QRhi::create(Implementation impl, QRhiInitParams *params, Flags flags, QRh
}
/*!
+ \return true if create() can be expected to succeed when called the given
+ \a impl and \a params.
+
+ For some backends this is equivalent to calling create(), checking its
+ return value, and then destroying the resulting QRhi.
+
+ For others, in particular with Metal, there may be a specific probing
+ implementation, which allows testing in a more lightweight manner without
+ polluting the debug output with warnings upon failures.
+
+ \sa create()
+ */
+bool QRhi::probe(QRhi::Implementation impl, QRhiInitParams *params)
+{
+ bool ok = false;
+
+ // The only place currently where this makes sense is Metal, where the API
+ // is simple enough so that a special probing function - doing nothing but
+ // a MTLCreateSystemDefaultDevice - is reasonable. Elsewhere, just call
+ // create() and then drop the result.
+
+ if (impl == Metal) {
+#if defined(Q_OS_MACOS) || defined(Q_OS_IOS)
+ ok = QRhiMetal::probe(static_cast<QRhiMetalInitParams *>(params));
+#endif
+ } else {
+ QRhi *rhi = create(impl, params);
+ ok = rhi != nullptr;
+ delete rhi;
+ }
+ return ok;
+}
+
+/*!
\return the backend type for this QRhi.
*/
QRhi::Implementation QRhi::backend() const
diff --git a/src/gui/rhi/qrhi_p.h b/src/gui/rhi/qrhi_p.h
index 972aed6fd8..c96b773e0b 100644
--- a/src/gui/rhi/qrhi_p.h
+++ b/src/gui/rhi/qrhi_p.h
@@ -1711,6 +1711,7 @@ public:
QRhiInitParams *params,
Flags flags = {},
QRhiNativeHandles *importDevice = nullptr);
+ static bool probe(Implementation impl, QRhiInitParams *params);
Implementation backend() const;
const char *backendName() const;
diff --git a/src/gui/rhi/qrhimetal.mm b/src/gui/rhi/qrhimetal.mm
index 3d53e8ab2d..c9cfb80d36 100644
--- a/src/gui/rhi/qrhimetal.mm
+++ b/src/gui/rhi/qrhimetal.mm
@@ -363,6 +363,17 @@ inline Int aligned(Int v, Int byteAlign)
return (v + byteAlign - 1) & ~(byteAlign - 1);
}
+bool QRhiMetal::probe(QRhiMetalInitParams *params)
+{
+ Q_UNUSED(params);
+ id<MTLDevice> dev = MTLCreateSystemDefaultDevice();
+ if (dev) {
+ [dev release];
+ return true;
+ }
+ return false;
+}
+
bool QRhiMetal::create(QRhi::Flags flags)
{
Q_UNUSED(flags);
diff --git a/src/gui/rhi/qrhimetal_p_p.h b/src/gui/rhi/qrhimetal_p_p.h
index 5234a152e1..f96ddbe209 100644
--- a/src/gui/rhi/qrhimetal_p_p.h
+++ b/src/gui/rhi/qrhimetal_p_p.h
@@ -351,6 +351,8 @@ public:
QRhiMetal(QRhiMetalInitParams *params, QRhiMetalNativeHandles *importDevice = nullptr);
~QRhiMetal();
+ static bool probe(QRhiMetalInitParams *params);
+
bool create(QRhi::Flags flags) override;
void destroy() override;