aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/scenegraph/qsgrhisupport.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick/scenegraph/qsgrhisupport.cpp')
-rw-r--r--src/quick/scenegraph/qsgrhisupport.cpp124
1 files changed, 103 insertions, 21 deletions
diff --git a/src/quick/scenegraph/qsgrhisupport.cpp b/src/quick/scenegraph/qsgrhisupport.cpp
index 0df19c247f..b86667a972 100644
--- a/src/quick/scenegraph/qsgrhisupport.cpp
+++ b/src/quick/scenegraph/qsgrhisupport.cpp
@@ -42,12 +42,17 @@
#if QT_CONFIG(opengl)
# include "qsgdefaultrendercontext_p.h"
#endif
-#include <QtGui/qwindow.h>
+#include <QtQuick/private/qquickitem_p.h>
+#include <QtQuick/private/qquickwindow_p.h>
+
+#include <QtGui/qwindow.h>
#if QT_CONFIG(vulkan)
#include <QtGui/qvulkaninstance.h>
#endif
+#include <QOperatingSystemVersion>
+
QT_BEGIN_NAMESPACE
#if QT_CONFIG(vulkan)
@@ -91,7 +96,7 @@ QVulkanInstance *QSGRhiSupport::vulkanInstance()
#endif
}
-void QSGRhiSupport::cleanup()
+void QSGRhiSupport::cleanupVulkanInstance()
{
#if QT_CONFIG(vulkan)
delete s_vulkanInstance;
@@ -100,7 +105,7 @@ void QSGRhiSupport::cleanup()
}
QSGRhiSupport::QSGRhiSupport()
- : m_set(false),
+ : m_settingsApplied(false),
m_enableRhi(false),
m_debugLayer(false),
m_profile(false),
@@ -111,7 +116,7 @@ QSGRhiSupport::QSGRhiSupport()
void QSGRhiSupport::applySettings()
{
- m_set = true;
+ m_settingsApplied = true;
// This is also done when creating the renderloop but we may be before that
// in case we get here due to a setScenegraphBackend() -> configure() early
@@ -121,7 +126,7 @@ void QSGRhiSupport::applySettings()
if (m_requested.valid) {
// explicit rhi backend request from C++ (e.g. via QQuickWindow)
- m_enableRhi = m_requested.rhi;
+ m_enableRhi = true;
switch (m_requested.api) {
case QSGRendererInterface::OpenGLRhi:
m_rhiBackend = QRhi::OpenGLES2;
@@ -143,8 +148,11 @@ void QSGRhiSupport::applySettings()
break;
}
} else {
+
+ // New Qt 6 default: enable RHI, unless QSG_NO_RHI is set
+ m_enableRhi = !qEnvironmentVariableIsSet("QSG_NO_RHI");
+
// check env.vars., fall back to platform-specific defaults when backend is not set
- m_enableRhi = uint(qEnvironmentVariableIntValue("QSG_RHI"));
const QByteArray rhiBackend = qgetenv("QSG_RHI_BACKEND");
if (rhiBackend == QByteArrayLiteral("gl")
|| rhiBackend == QByteArrayLiteral("gles2")
@@ -172,12 +180,23 @@ void QSGRhiSupport::applySettings()
m_rhiBackend = QRhi::OpenGLES2;
#endif
// Vulkan has to be requested explicitly
+
+ // Now that we established our initial choice, we may want to opt
+ // for another backend under certain special circumstances.
+ if (m_enableRhi) // guard because this may do actual graphics calls on some platforms
+ adjustToPlatformQuirks();
}
}
if (!m_enableRhi)
return;
+ // At this point the RHI backend is fixed, it cannot be changed once we
+ // return from this function. This is because things like the QWindow
+ // (QQuickWindow) may depend on the graphics API as well (surfaceType
+ // f.ex.), and all that is based on what we report from here. So further
+ // adjustments are not possible (or, at minimum, not safe and portable).
+
// validation layers (Vulkan) or debug layer (D3D)
m_debugLayer = uint(qEnvironmentVariableIntValue("QSG_RHI_DEBUG_LAYER"));
@@ -200,6 +219,39 @@ void QSGRhiSupport::applySettings()
qCDebug(QSG_LOG_INFO, "Prioritizing software renderers");
}
+void QSGRhiSupport::adjustToPlatformQuirks()
+{
+#if defined(Q_OS_WIN)
+ // Temporary Windows 7 workaround: no D3D. Just stick with OpenGL like Qt 5
+ // would. Can be removed when Win 7 support is finally dropped from Qt 6.
+ // (but as long as we have a Win 7 CI, this is mandatory)
+ if (QOperatingSystemVersion::current() <= QOperatingSystemVersion::Windows7) {
+ if (m_rhiBackend == QRhi::D3D11) {
+ qCDebug(QSG_LOG_INFO, "D3D on Windows 7 is not supported. Trying OpenGL instead.");
+ m_rhiBackend = QRhi::OpenGLES2;
+ }
+ }
+#elif defined(Q_OS_MACOS) || defined(Q_OS_IOS)
+
+ // ### For now just create a throwaway QRhi instance. This will be replaced
+ // by a more lightweight way, once a helper function is added gui/rhi.
+
+ // A macOS VM may not have Metal support at all. We have to decide at this
+ // point, it will be too late afterwards, and the only way is to see if
+ // MTLCreateSystemDefaultDevice succeeds.
+ if (m_rhiBackend == QRhi::Metal) {
+ QRhiMetalInitParams rhiParams;
+ QRhi *tempRhi = QRhi::create(m_rhiBackend, &rhiParams, {});
+ if (!tempRhi) {
+ m_rhiBackend = QRhi::OpenGLES2;
+ qCDebug(QSG_LOG_INFO, "Metal does not seem to be supported. Falling back to OpenGL.");
+ } else {
+ delete tempRhi;
+ }
+ }
+#endif
+}
+
QSGRhiSupport *QSGRhiSupport::staticInst()
{
static QSGRhiSupport inst;
@@ -217,20 +269,15 @@ void QSGRhiSupport::configure(QSGRendererInterface::GraphicsApi api)
{
Q_ASSERT(QSGRendererInterface::isApiRhiBased(api));
QSGRhiSupport *inst = staticInst();
- if (inst->m_set) {
- qWarning("QRhi is already configured, request ignored");
- return;
- }
inst->m_requested.valid = true;
inst->m_requested.api = api;
- inst->m_requested.rhi = true;
inst->applySettings();
}
QSGRhiSupport *QSGRhiSupport::instance()
{
QSGRhiSupport *inst = staticInst();
- if (!inst->m_set)
+ if (!inst->m_settingsApplied)
inst->applySettings();
return inst;
}
@@ -483,11 +530,10 @@ QOffscreenSurface *QSGRhiSupport::maybeCreateOffscreenSurface(QWindow *window)
}
// must be called on the render thread
-QRhi *QSGRhiSupport::createRhi(QWindow *window, QOffscreenSurface *offscreenSurface)
+QRhi *QSGRhiSupport::createRhi(QQuickWindow *window, QOffscreenSurface *offscreenSurface)
{
-#if !QT_CONFIG(opengl) && !QT_CONFIG(vulkan)
- Q_UNUSED(window);
-#endif
+ const QQuickGraphicsDevice &customDev(QQuickWindowPrivate::get(window)->customDeviceObjects);
+ const QQuickGraphicsDevicePrivate *customDevD = QQuickGraphicsDevicePrivate::get(&customDev);
QRhi *rhi = nullptr;
@@ -509,7 +555,14 @@ QRhi *QSGRhiSupport::createRhi(QWindow *window, QOffscreenSurface *offscreenSurf
rhiParams.format = format;
rhiParams.fallbackSurface = offscreenSurface;
rhiParams.window = window;
- rhi = QRhi::create(backend, &rhiParams, flags);
+ if (customDevD->type == QQuickGraphicsDevicePrivate::Type::OpenGLContext) {
+ QRhiGles2NativeHandles importDev;
+ importDev.context = customDevD->u.context;
+ qCDebug(QSG_LOG_INFO, "Using existing QOpenGLContext %p", importDev.context);
+ rhi = QRhi::create(backend, &rhiParams, flags, &importDev);
+ } else {
+ rhi = QRhi::create(backend, &rhiParams, flags);
+ }
}
#else
Q_UNUSED(offscreenSurface);
@@ -520,8 +573,19 @@ QRhi *QSGRhiSupport::createRhi(QWindow *window, QOffscreenSurface *offscreenSurf
rhiParams.inst = window->vulkanInstance();
if (!rhiParams.inst)
qWarning("No QVulkanInstance set for QQuickWindow, this is wrong.");
- rhiParams.window = window;
- rhi = QRhi::create(backend, &rhiParams, flags);
+ if (window->handle()) // only used for vkGetPhysicalDeviceSurfaceSupportKHR and that implies having a valid native window
+ rhiParams.window = window;
+ if (customDevD->type == QQuickGraphicsDevicePrivate::Type::DeviceObjects) {
+ QRhiVulkanNativeHandles importDev;
+ importDev.physDev = reinterpret_cast<VkPhysicalDevice>(customDevD->u.deviceObjects.physicalDevice);
+ importDev.dev = reinterpret_cast<VkDevice>(customDevD->u.deviceObjects.device);
+ importDev.gfxQueueFamilyIdx = customDevD->u.deviceObjects.queueFamilyIndex;
+ qCDebug(QSG_LOG_INFO, "Using existing native Vulkan physical device %p device %p graphics queue family index %d",
+ importDev.physDev, importDev.dev, importDev.gfxQueueFamilyIdx);
+ rhi = QRhi::create(backend, &rhiParams, flags, &importDev);
+ } else {
+ rhi = QRhi::create(backend, &rhiParams, flags);
+ }
}
#endif
#ifdef Q_OS_WIN
@@ -532,13 +596,31 @@ QRhi *QSGRhiSupport::createRhi(QWindow *window, QOffscreenSurface *offscreenSurf
rhiParams.framesUntilKillingDeviceViaTdr = m_killDeviceFrameCount;
rhiParams.repeatDeviceKill = true;
}
- rhi = QRhi::create(backend, &rhiParams, flags);
+ if (customDevD->type == QQuickGraphicsDevicePrivate::Type::DeviceAndContext) {
+ QRhiD3D11NativeHandles importDev;
+ importDev.dev = customDevD->u.deviceAndContext.device;
+ importDev.context = customDevD->u.deviceAndContext.context;
+ qCDebug(QSG_LOG_INFO, "Using existing native D3D11 device %p and context %p",
+ importDev.dev, importDev.context);
+ rhi = QRhi::create(backend, &rhiParams, flags, &importDev);
+ } else {
+ rhi = QRhi::create(backend, &rhiParams, flags);
+ }
}
#endif
#if defined(Q_OS_MACOS) || defined(Q_OS_IOS)
if (backend == QRhi::Metal) {
QRhiMetalInitParams rhiParams;
- rhi = QRhi::create(backend, &rhiParams, flags);
+ if (customDevD->type == QQuickGraphicsDevicePrivate::Type::DeviceAndCommandQueue) {
+ QRhiMetalNativeHandles importDev;
+ importDev.dev = customDevD->u.deviceAndCommandQueue.device;
+ importDev.cmdQueue = customDevD->u.deviceAndCommandQueue.cmdQueue;
+ qCDebug(QSG_LOG_INFO, "Using existing native Metal device %p and command queue %p",
+ importDev.dev, importDev.cmdQueue);
+ rhi = QRhi::create(backend, &rhiParams, flags, &importDev);
+ } else {
+ rhi = QRhi::create(backend, &rhiParams, flags);
+ }
}
#endif