diff options
Diffstat (limited to 'src/quick/scenegraph/qsgrhisupport.cpp')
-rw-r--r-- | src/quick/scenegraph/qsgrhisupport.cpp | 124 |
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 |