aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2020-06-19 15:39:34 +0200
committerLaszlo Agocs <laszlo.agocs@qt.io>2020-06-19 20:22:57 +0200
commit7c6f53b128d57cfb746509b10b1abdcd5b65205e (patch)
tree8c608689701ad7ea0a45fd834e87ecf155350d9c /src
parentb4447c39a95bc03d7874a323e179d0f8cda83255 (diff)
Make it possible to specify device extensions in a future proof manner
Follow the pattern of QQuickRenderTarget and QQuickGraphicsDevice. This makes it possible to integrate with real world frameworks, such as OpenXR, that, especially with Vulkan, expect this level of configurability. (i.e. one pulls the list of extensions to be enabled on the device, that then needs to be taken into account by Quick, otherwise it will end up with a VkDevice that is not usable by OpenXR) Same goes when integrating native Vulkan rendering into an application: if certain extensions need to be enabled on the VkDevice, today that can only be done with an environment variable which is not entirely ideal. These issues are now solved by a new simple (and extensible) container QQuickGraphicsConfiguration, which is associated with the QQuickWindow. When applicable, the scene graph will then pick up the relevant settings. Expand the related docs everywhere. Also rename the vulkanInstance() to defaultVulkanInstance() to emphasize that it is the instance that is used for normal QQuickWindows, and is not provided when redirecting via QQuickRenderControl. While we are at it, include another obvious candidate: the use-depth-buffer flag. It turns out that Quick3D's Overlay render mode can be pretty problematic if Quick writes to the depth buffer. In order to avoid relying on environment variables (QSG_NO_DEPTH_BUFFER), we now provide a proper API for controlling that as well. Change-Id: Iefdb62c1f53de8bd34e3f0d393b00c5020d6188a Reviewed-by: Andy Nichols <andy.nichols@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/quick/CMakeLists.txt1
-rw-r--r--src/quick/items/items.pri7
-rw-r--r--src/quick/items/qquickgraphicsconfiguration.cpp217
-rw-r--r--src/quick/items/qquickgraphicsconfiguration.h71
-rw-r--r--src/quick/items/qquickgraphicsconfiguration_p.h76
-rw-r--r--src/quick/items/qquickrendercontrol.cpp8
-rw-r--r--src/quick/items/qquickwindow.cpp67
-rw-r--r--src/quick/items/qquickwindow.h3
-rw-r--r--src/quick/items/qquickwindow_p.h3
-rw-r--r--src/quick/scenegraph/qsgcontext.cpp5
-rw-r--r--src/quick/scenegraph/qsgcontext_p.h6
-rw-r--r--src/quick/scenegraph/qsgdefaultrendercontext.cpp12
-rw-r--r--src/quick/scenegraph/qsgdefaultrendercontext_p.h10
-rw-r--r--src/quick/scenegraph/qsgrenderloop.cpp2
-rw-r--r--src/quick/scenegraph/qsgrhilayer.cpp6
-rw-r--r--src/quick/scenegraph/qsgrhisupport.cpp8
-rw-r--r--src/quick/scenegraph/qsgrhisupport_p.h4
17 files changed, 473 insertions, 33 deletions
diff --git a/src/quick/CMakeLists.txt b/src/quick/CMakeLists.txt
index 5ccce5433c..07a9927250 100644
--- a/src/quick/CMakeLists.txt
+++ b/src/quick/CMakeLists.txt
@@ -37,6 +37,7 @@ qt_add_module(Quick
items/qquickflickable_p_p.h
items/qquickflickablebehavior_p.h
items/qquickfocusscope.cpp items/qquickfocusscope_p.h
+ items/qquickgraphicsconfiguration.cpp items/qquickgraphicsconfiguration.h items/qquickgraphicsconfiguration_p.h
items/qquickgraphicsdevice.cpp items/qquickgraphicsdevice.h items/qquickgraphicsdevice_p.h
items/qquickgraphicsinfo.cpp items/qquickgraphicsinfo_p.h
items/qquickimage.cpp items/qquickimage_p.h
diff --git a/src/quick/items/items.pri b/src/quick/items/items.pri
index dd477d0e5a..6e3fbca2b6 100644
--- a/src/quick/items/items.pri
+++ b/src/quick/items/items.pri
@@ -69,7 +69,9 @@ HEADERS += \
$$PWD/qquickrendertarget.h \
$$PWD/qquickrendertarget_p.h \
$$PWD/qquickgraphicsdevice.h \
- $$PWD/qquickgraphicsdevice_p.h
+ $$PWD/qquickgraphicsdevice_p.h \
+ $$PWD/qquickgraphicsconfiguration.h \
+ $$PWD/qquickgraphicsconfiguration_p.h
SOURCES += \
$$PWD/qquickevents.cpp \
@@ -114,7 +116,8 @@ SOURCES += \
$$PWD/qquickcolorgroup.cpp \
$$PWD/qquickpalette.cpp \
$$PWD/qquickrendertarget.cpp \
- $$PWD/qquickgraphicsdevice.cpp
+ $$PWD/qquickgraphicsdevice.cpp \
+ $$PWD/qquickgraphicsconfiguration.cpp
qtConfig(quick-draganddrop) {
HEADERS += \
diff --git a/src/quick/items/qquickgraphicsconfiguration.cpp b/src/quick/items/qquickgraphicsconfiguration.cpp
new file mode 100644
index 0000000000..ba03e4f401
--- /dev/null
+++ b/src/quick/items/qquickgraphicsconfiguration.cpp
@@ -0,0 +1,217 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickgraphicsconfiguration_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QQuickGraphicsConfiguration
+ \since 6.0
+ \inmodule QtQuick
+
+ \brief The QQuickGraphicsConfiguration class is a container for low-level
+ graphics settings that can affect how the underlying graphics API, such as
+ Vulkan, is initialized by the Qt Quick scene graph. It can also control
+ certain aspects of the scene graph renderer.
+
+ When constructing and showing a QQuickWindow that uses Vulkan to render, a
+ Vulkan instance (\c VkInstance), a physical device (\c VkPhysicalDevice), a
+ device (\c VkDevice) and associated objects (queues, pools) are initialized
+ through the Vulkan API. The same is mostly true when using
+ QQuickRenderControl to redirect the rendering into a custom render target,
+ such as a texture. While QVulkanInstance construction is under the
+ application's control then, the initialization of other graphics objects
+ happen the same way in QQuickRenderControl::initialize() as with an
+ on-screen QQuickWindow.
+
+ For the majority of applications no additional configuration is needed
+ because Qt Quick provides reasonable defaults for many low-level graphics
+ settings, for example which device extensions to enable.
+
+ This will not alway be sufficient, however. In advanced use cases, when
+ integrating direct Vulkan or other graphics API content, or when
+ integrating with an external 3D or VR engine, such as, OpenXR, the
+ application will want to specify its own set of settings when it comes to
+ details, such as which device extensions to enable.
+
+ That is what this class enables. It allows specifying, for example, a list
+ of device extensions that is then picked up by the scene graph when using
+ Vulkan, or graphics APIs where the concept is applicable. Where some
+ concepts are not applicable, the related settings are simply ignored.
+
+ Another class of settings are related to the scene graph's renderer. In
+ some cases applications may want to control certain behavior,such as using
+ the depth buffer when rendering 2D content. In Qt 5 such settings were
+ either not controllable at all, or were managed through environment
+ variables. In Qt 6, QQuickGraphicsConfiguration provides a new home for
+ these settings, while keeping support for the legacy environment variables,
+ where applicable.
+
+ \note Setting a QQuickGraphicsConfiguration on a QQuickWindow must happen
+ early enough, before the scene graph is initialized for the first time for
+ that window. With on-screen windows this means the call must be done before
+ invoking show() on the QQuickWindow or QQuickView. With QQuickRenderControl
+ the configuration must be finalized before calling
+ \l{QQuickRenderControl::initialize()}{initialize()}.
+
+ \sa QQuickWindow::setGraphicsConfiguration(), QQuickWindow, QQuickRenderControl
+*/
+
+/*!
+ Constructs a default QQuickGraphicsConfiguration that does not specify any
+ additional settings for the scene graph to take into account.
+ */
+QQuickGraphicsConfiguration::QQuickGraphicsConfiguration()
+ : d(new QQuickGraphicsConfigurationPrivate)
+{
+}
+
+/*!
+ \internal
+ */
+void QQuickGraphicsConfiguration::detach()
+{
+ qAtomicDetach(d);
+}
+
+/*!
+ \internal
+ */
+QQuickGraphicsConfiguration::QQuickGraphicsConfiguration(const QQuickGraphicsConfiguration &other)
+ : d(other.d)
+{
+ d->ref.ref();
+}
+
+/*!
+ \internal
+ */
+QQuickGraphicsConfiguration &QQuickGraphicsConfiguration::operator=(const QQuickGraphicsConfiguration &other)
+{
+ qAtomicAssign(d, other.d);
+ return *this;
+}
+
+/*!
+ Destructor.
+ */
+QQuickGraphicsConfiguration::~QQuickGraphicsConfiguration()
+{
+ if (!d->ref.deref())
+ delete d;
+}
+
+/*!
+ Sets the list of additional \a extensions to enable on the graphics device
+ (such as, the \c VkDevice).
+
+ When rendering with a graphics API where the concept is not applicable, \a
+ extensions will be ignored.
+
+ \note The list specifies additional, extra extensions. Qt Quick always
+ enables extensions that are required by the scene graph.
+ */
+void QQuickGraphicsConfiguration::setDeviceExtensions(const QByteArrayList &extensions)
+{
+ if (d->deviceExtensions != extensions) {
+ detach();
+ d->deviceExtensions = extensions;
+ }
+}
+
+/*!
+ Sets the usage of depth buffer for 2D content to \a enable.
+
+ By default the value is true, unless the \c{QSG_NO_DEPTH_BUFFER}
+ environment variable is set.
+
+ The default value of true is the most optimal setting for the vast majority
+ of scenes. Disabling depth buffer usage reduces the efficiency of the scene
+ graph's batching.
+
+ There are special cases however, when allowing the 2D content write to the
+ depth buffer is not ideal. Consider a 3D overlay, rendered via Qt Quick 3D
+ in overlay mode. In that case, having the depth buffer filled by 2D content
+ can cause unexpected results, because the way the scene graph renderer
+ handles depth values is not necessarily compatible with how a 3D scene
+ works. In that case, \a enable can be set to false.
+ */
+void QQuickGraphicsConfiguration::setDepthBufferFor2D(bool enable)
+{
+ if (d->useDepthBufferFor2D != enable) {
+ detach();
+ d->useDepthBufferFor2D = enable;
+ }
+}
+
+/*!
+ \return true if depth buffer usage is enabled for 2D content.
+
+ By default the value is true, unless the \c{QSG_NO_DEPTH_BUFFER}
+ environment variable is set.
+ */
+bool QQuickGraphicsConfiguration::isDepthBufferEnabledFor2D() const
+{
+ return d->useDepthBufferFor2D;
+}
+
+/*!
+ \return the list of the requested additional device extensions.
+ */
+QByteArrayList QQuickGraphicsConfiguration::deviceExtensions() const
+{
+ return d->deviceExtensions;
+}
+
+QQuickGraphicsConfigurationPrivate::QQuickGraphicsConfigurationPrivate()
+ : ref(1)
+{
+ static const bool useDepth = qEnvironmentVariableIsEmpty("QSG_NO_DEPTH_BUFFER");
+ useDepthBufferFor2D = useDepth;
+}
+
+QQuickGraphicsConfigurationPrivate::QQuickGraphicsConfigurationPrivate(const QQuickGraphicsConfigurationPrivate *other)
+ : ref(1),
+ deviceExtensions(other->deviceExtensions),
+ useDepthBufferFor2D(other->useDepthBufferFor2D)
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/items/qquickgraphicsconfiguration.h b/src/quick/items/qquickgraphicsconfiguration.h
new file mode 100644
index 0000000000..8716c033a0
--- /dev/null
+++ b/src/quick/items/qquickgraphicsconfiguration.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKGRAPHICSCONFIGURATION_H
+#define QQUICKGRAPHICSCONFIGURATION_H
+
+#include <QtQuick/qtquickglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickGraphicsConfigurationPrivate;
+
+class Q_QUICK_EXPORT QQuickGraphicsConfiguration
+{
+public:
+ QQuickGraphicsConfiguration();
+ ~QQuickGraphicsConfiguration();
+ QQuickGraphicsConfiguration(const QQuickGraphicsConfiguration &other);
+ QQuickGraphicsConfiguration &operator=(const QQuickGraphicsConfiguration &other);
+
+ void setDeviceExtensions(const QByteArrayList &extensions);
+ QByteArrayList deviceExtensions() const;
+
+ void setDepthBufferFor2D(bool enable);
+ bool isDepthBufferEnabledFor2D() const;
+
+private:
+ void detach();
+ QQuickGraphicsConfigurationPrivate *d;
+ friend class QQuickGraphicsConfigurationPrivate;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKGRAPHICSCONFIGURATION_H
diff --git a/src/quick/items/qquickgraphicsconfiguration_p.h b/src/quick/items/qquickgraphicsconfiguration_p.h
new file mode 100644
index 0000000000..6fa15e9891
--- /dev/null
+++ b/src/quick/items/qquickgraphicsconfiguration_p.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKGRAPHICSCONFIGURATION_P_H
+#define QQUICKGRAPHICSCONFIGURATION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtQuick/private/qtquickglobal_p.h>
+#include <QAtomicInt>
+#include <QByteArrayList>
+#include "qquickgraphicsconfiguration.h"
+
+QT_BEGIN_NAMESPACE
+
+class Q_QUICK_PRIVATE_EXPORT QQuickGraphicsConfigurationPrivate
+{
+public:
+ static QQuickGraphicsConfigurationPrivate *get(QQuickGraphicsConfiguration *p) { return p->d; }
+ static const QQuickGraphicsConfigurationPrivate *get(const QQuickGraphicsConfiguration *p) { return p->d; }
+ QQuickGraphicsConfigurationPrivate();
+ QQuickGraphicsConfigurationPrivate(const QQuickGraphicsConfigurationPrivate *other);
+
+ QAtomicInt ref;
+ QByteArrayList deviceExtensions;
+ bool useDepthBufferFor2D;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKGRAPHICSCONFIGURATION_P_H
diff --git a/src/quick/items/qquickrendercontrol.cpp b/src/quick/items/qquickrendercontrol.cpp
index 51483bce57..c2adc2ef10 100644
--- a/src/quick/items/qquickrendercontrol.cpp
+++ b/src/quick/items/qquickrendercontrol.cpp
@@ -270,6 +270,14 @@ int QQuickRenderControl::samples() const
specify an appropriate QQuickGraphicsDevice, wrapping existing graphics
objects, by calling QQuickWindow::setGraphicsDevice().
+ To configure which device extensions to enable (for example, for Vulkan),
+ call QQuickWindow::setGraphicsConfiguration() before this function.
+
+ \note When using Vulkan, QQuickRenderControl does not create a
+ QVulkanInstance automatically. Rather, it is the application's
+ responsibility to create a suitable QVulkanInstance and
+ \l{QWindow::setVulkanInstance()}{associate it} with the QQuickWindow.
+
\note This function does not need to be, and must not be, called when using
the \c software adaptation of Qt Quick.
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index faf4eb1b50..ed02c4f4c8 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -568,7 +568,7 @@ void QQuickWindowPrivate::syncSceneGraph()
else
cb = swapchain->currentFrameCommandBuffer();
}
- context->prepareSync(devicePixelRatio, cb);
+ context->prepareSync(devicePixelRatio, cb, graphicsConfig);
animationController->beforeNodeSync();
@@ -579,9 +579,9 @@ void QQuickWindowPrivate::syncSceneGraph()
QSGRootNode *rootNode = new QSGRootNode;
rootNode->appendChildNode(QQuickItemPrivate::get(contentItem)->itemNode());
- static const bool useDepth = qEnvironmentVariableIsEmpty("QSG_NO_DEPTH_BUFFER");
- static const QSGRendererInterface::RenderMode renderMode = useDepth ? QSGRendererInterface::RenderMode2D
- : QSGRendererInterface::RenderMode2DNoDepthBuffer;
+ const bool useDepth = graphicsConfig.isDepthBufferEnabledFor2D();
+ const QSGRendererInterface::RenderMode renderMode = useDepth ? QSGRendererInterface::RenderMode2D
+ : QSGRendererInterface::RenderMode2DNoDepthBuffer;
renderer = context->createRenderer(renderMode);
renderer->setRootNode(rootNode);
}
@@ -809,8 +809,14 @@ void QQuickWindowPrivate::init(QQuickWindow *c, QQuickRenderControl *control)
q->setSurfaceType(windowManager ? windowManager->windowSurfaceType() : QSurface::OpenGLSurface);
q->setFormat(sg->defaultSurfaceFormat());
#if QT_CONFIG(vulkan)
+ // Normal QQuickWindows must get a QVulkanInstance automatically (it is
+ // created when the first window is constructed and is destroyed only on
+ // exit). With QQuickRenderControl however, no QVulkanInstance is created,
+ // because it must be under the application's control then (since the
+ // default instance we could create here would not be configurable by the
+ // application in any way, and that is not acceptable in advanced use cases).
if (!renderControl && q->surfaceType() == QSurface::VulkanSurface)
- q->setVulkanInstance(QSGRhiSupport::vulkanInstance());
+ q->setVulkanInstance(QSGRhiSupport::defaultVulkanInstance());
#endif
animationController.reset(new QQuickAnimatorController(q));
@@ -1511,11 +1517,13 @@ void QQuickWindowPrivate::cleanup(QSGNode *n)
A QQuickWindow is not necessarily backed by a native window on screen. The
rendering can be redirected to target a custom render target, such as a
given native texture. This is achieved in combination with the
- QQuickRenderControl class, and functions such as setRenderTarge() and
- setGraphicsDevice(). In this case, the QQuickWindow represents the scene,
- and provides the intrastructure for rendering a frame. It will not be backed
- by a render loop and a native window. Instead, in this case the application
- drives rendering, effectively substituting for the render loops. This allows
+ QQuickRenderControl class, and functions such as setRenderTarget(),
+ setGraphicsDevice(), and setGraphicsConfiguration().
+
+ In this case, the QQuickWindow represents the scene, and provides the
+ intrastructure for rendering a frame. It will not be backed by a render
+ loop and a native window. Instead, in this case the application drives
+ rendering, effectively substituting for the render loops. This allows
generating image sequences, rendering into textures for use in external 3D
engines, or rendering Qt Quick content within a VR environment.
@@ -4216,7 +4224,8 @@ bool QQuickWindow::isSceneGraphInitialized() const
referred to in \a target are valid for the scenegraph renderer too. For
instance, with Vulkan, Metal, and Direct3D this implies that the texture or
image is created on the same graphics device that is used by the scenegraph
- internally. This is often achieved by using this function in combination
+ internally. Therefore, when texture objects created on an already existing
+ device or context are involved, this function is often used in combination
with setGraphicsDevice().
\note With graphics APIs where relevant, the application must pay attention
@@ -5660,6 +5669,12 @@ QString QQuickWindow::sceneGraphBackend()
renderer. This requires using the same graphics device (or with OpenGL,
OpenGL context).
+ \note Using QQuickRenderControl does not always imply having to call this
+ function. When adopting an existing device or context is not needed, this
+ function should not be called, and the scene graph will then initialize its
+ own devices and contexts normally, just as it would with an on-screen
+ QQuickWindow.
+
\since 6.0
\sa QQuickRenderControl, setRenderTarget(), setSceneGraphBackend()
@@ -5671,6 +5686,36 @@ void QQuickWindow::setGraphicsDevice(const QQuickGraphicsDevice &device)
}
/*!
+ Sets the graphics configuration for this window. \a config contains various
+ settings that may be taken into account by the scene graph when
+ initializing the underlying graphics devices and contexts.
+
+ Such additional configuration, specifying for example what device
+ extensions to enable for Vulkan, becomes relevant and essential when
+ integrating native graphics rendering code that relies on certain
+ extensions. The same is true when integrating with an external 3D or VR
+ engines, such as OpenXR.
+
+ \note The configuration is ignored when adopting existing graphics devices
+ via setGraphicsDevice() since the scene graph is then not in control of the
+ actual construction of those objects.
+
+ \warning Setting a QQuickGraphicsConfiguration on a QQuickWindow must
+ happen early enough, before the scene graph is initialized for the first
+ time for that window. With on-screen windows this means the call must be
+ done before invoking show() on the QQuickWindow or QQuickView. With
+ QQuickRenderControl the configuration must be finalized before calling
+ \l{QQuickRenderControl::initialize()}{initialize()}.
+
+ \since 6.0
+ */
+void QQuickWindow::setGraphicsConfiguration(const QQuickGraphicsConfiguration &config)
+{
+ Q_D(QQuickWindow);
+ d->graphicsConfig = config;
+}
+
+/*!
Creates a simple rectangle node. When the scenegraph is not initialized, the return value is null.
This is cross-backend alternative to constructing a QSGSimpleRectNode directly.
diff --git a/src/quick/items/qquickwindow.h b/src/quick/items/qquickwindow.h
index dc9eeb4e70..88b3772048 100644
--- a/src/quick/items/qquickwindow.h
+++ b/src/quick/items/qquickwindow.h
@@ -66,6 +66,7 @@ class QSGImageNode;
class QSGNinePatchNode;
class QQuickRenderTarget;
class QQuickGraphicsDevice;
+class QQuickGraphicsConfiguration;
class Q_QUICK_EXPORT QQuickWindow : public QWindow
{
@@ -186,6 +187,8 @@ public:
void setGraphicsDevice(const QQuickGraphicsDevice &device);
+ void setGraphicsConfiguration(const QQuickGraphicsConfiguration &config);
+
QSGRectangleNode *createRectangleNode() const;
QSGImageNode *createImageNode() const;
QSGNinePatchNode *createNinePatchNode() const;
diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h
index 2310367631..703e29d160 100644
--- a/src/quick/items/qquickwindow_p.h
+++ b/src/quick/items/qquickwindow_p.h
@@ -56,6 +56,7 @@
#include <QtQuick/private/qquickpaletteproviderprivatebase_p.h>
#include <QtQuick/private/qquickrendertarget_p.h>
#include <QtQuick/private/qquickgraphicsdevice_p.h>
+#include <QtQuick/private/qquickgraphicsconfiguration_p.h>
#include <QtQuick/qquickitem.h>
#include <QtQuick/qquickwindow.h>
@@ -297,6 +298,8 @@ public:
QQuickGraphicsDevice customDeviceObjects;
+ QQuickGraphicsConfiguration graphicsConfig;
+
mutable QQuickWindowIncubationController *incubationController;
static bool defaultAlphaBuffer;
diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp
index 761f35bdd6..d550b2c66a 100644
--- a/src/quick/scenegraph/qsgcontext.cpp
+++ b/src/quick/scenegraph/qsgcontext.cpp
@@ -341,10 +341,13 @@ void QSGRenderContext::invalidate()
{
}
-void QSGRenderContext::prepareSync(qreal devicePixelRatio, QRhiCommandBuffer *cb)
+void QSGRenderContext::prepareSync(qreal devicePixelRatio,
+ QRhiCommandBuffer *cb,
+ const QQuickGraphicsConfiguration &config)
{
Q_UNUSED(devicePixelRatio);
Q_UNUSED(cb);
+ Q_UNUSED(config);
}
void QSGRenderContext::beginNextFrame(QSGRenderer *renderer,
diff --git a/src/quick/scenegraph/qsgcontext_p.h b/src/quick/scenegraph/qsgcontext_p.h
index 650accd28d..fc3e3fc854 100644
--- a/src/quick/scenegraph/qsgcontext_p.h
+++ b/src/quick/scenegraph/qsgcontext_p.h
@@ -94,6 +94,7 @@ class QRhi;
class QRhiRenderTarget;
class QRhiRenderPassDescriptor;
class QRhiCommandBuffer;
+class QQuickGraphicsConfiguration;
Q_DECLARE_LOGGING_CATEGORY(QSG_LOG_TIME_RENDERLOOP)
Q_DECLARE_LOGGING_CATEGORY(QSG_LOG_TIME_COMPILATION)
@@ -174,7 +175,10 @@ public:
using RenderPassCallback = void (*)(void *);
- virtual void prepareSync(qreal devicePixelRatio, QRhiCommandBuffer *cb);
+ virtual void prepareSync(qreal devicePixelRatio,
+ QRhiCommandBuffer *cb,
+ const QQuickGraphicsConfiguration &config);
+
virtual void beginNextFrame(QSGRenderer *renderer,
RenderPassCallback mainPassRecordingStart,
RenderPassCallback mainPassRecordingEnd,
diff --git a/src/quick/scenegraph/qsgdefaultrendercontext.cpp b/src/quick/scenegraph/qsgdefaultrendercontext.cpp
index 1c7f6c5c59..6dbc20d9cb 100644
--- a/src/quick/scenegraph/qsgdefaultrendercontext.cpp
+++ b/src/quick/scenegraph/qsgdefaultrendercontext.cpp
@@ -50,6 +50,7 @@
#include <QtQuick/private/qsgcompressedtexture_p.h>
#include <QtQuick/qsgrendererinterface.h>
+#include <QtQuick/qquickgraphicsconfiguration.h>
QT_BEGIN_NAMESPACE
@@ -62,6 +63,7 @@ QSGDefaultRenderContext::QSGDefaultRenderContext(QSGContext *context)
, m_currentFrameCommandBuffer(nullptr)
, m_currentFrameRenderPass(nullptr)
, m_separateIndexBuffer(false)
+ , m_useDepthBufferFor2D(true)
{
}
@@ -150,9 +152,12 @@ void QSGDefaultRenderContext::invalidate()
emit invalidated();
}
-void QSGDefaultRenderContext::prepareSync(qreal devicePixelRatio, QRhiCommandBuffer *cb)
+void QSGDefaultRenderContext::prepareSync(qreal devicePixelRatio,
+ QRhiCommandBuffer *cb,
+ const QQuickGraphicsConfiguration &config)
{
m_currentDevicePixelRatio = devicePixelRatio;
+ m_useDepthBufferFor2D = config.isDepthBufferEnabledFor2D();
// we store the command buffer already here, in case there is something in
// an updatePaintNode() implementation that leads to needing it (for
@@ -277,11 +282,6 @@ void QSGDefaultRenderContext::initializeRhiShader(QSGMaterialShader *shader, QSh
QSGMaterialShaderPrivate::get(shader)->prepare(shaderVariant);
}
-bool QSGDefaultRenderContext::separateIndexBuffer() const
-{
- return m_separateIndexBuffer;
-}
-
void QSGDefaultRenderContext::preprocess()
{
for (auto it = m_glyphCaches.begin(); it != m_glyphCaches.end(); ++it) {
diff --git a/src/quick/scenegraph/qsgdefaultrendercontext_p.h b/src/quick/scenegraph/qsgdefaultrendercontext_p.h
index 35a0695dab..a110172a6f 100644
--- a/src/quick/scenegraph/qsgdefaultrendercontext_p.h
+++ b/src/quick/scenegraph/qsgdefaultrendercontext_p.h
@@ -90,7 +90,10 @@ public:
void initialize(const QSGRenderContext::InitParams *params) override;
void invalidate() override;
- void prepareSync(qreal devicePixelRatio, QRhiCommandBuffer *cb) override;
+ void prepareSync(qreal devicePixelRatio,
+ QRhiCommandBuffer *cb,
+ const QQuickGraphicsConfiguration &config) override;
+
void beginNextFrame(QSGRenderer *renderer,
RenderPassCallback mainPassRecordingStart,
RenderPassCallback mainPassRecordingEnd,
@@ -116,8 +119,8 @@ public:
virtual void initializeRhiShader(QSGMaterialShader *shader, QShader::Variant shaderVariant);
int maxTextureSize() const override { return m_maxTextureSize; }
- bool separateIndexBuffer() const;
-
+ bool separateIndexBuffer() const { return m_separateIndexBuffer; }
+ bool useDepthBufferFor2D() const { return m_useDepthBufferFor2D; }
int msaaSampleCount() const { return m_initParams.sampleCount; }
QRhiCommandBuffer *currentFrameCommandBuffer() const {
@@ -152,6 +155,7 @@ protected:
QRhiRenderPassDescriptor *m_currentFrameRenderPass;
qreal m_currentDevicePixelRatio;
bool m_separateIndexBuffer;
+ bool m_useDepthBufferFor2D;
};
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp
index c025e8d9af..8388fa9576 100644
--- a/src/quick/scenegraph/qsgrenderloop.cpp
+++ b/src/quick/scenegraph/qsgrenderloop.cpp
@@ -107,7 +107,7 @@ void QSGRenderLoop::cleanup()
s_instance = nullptr;
#ifdef ENABLE_DEFAULT_BACKEND
- QSGRhiSupport::cleanupVulkanInstance();
+ QSGRhiSupport::cleanupDefaultVulkanInstance();
QSGRhiProfileConnection::instance()->cleanup();
#endif
}
diff --git a/src/quick/scenegraph/qsgrhilayer.cpp b/src/quick/scenegraph/qsgrhilayer.cpp
index 9d3db8354d..0e7eb1932e 100644
--- a/src/quick/scenegraph/qsgrhilayer.cpp
+++ b/src/quick/scenegraph/qsgrhilayer.cpp
@@ -352,9 +352,9 @@ void QSGRhiLayer::grab()
return;
if (!m_renderer) {
- static const bool useDepth = qEnvironmentVariableIsEmpty("QSG_NO_DEPTH_BUFFER");
- static const QSGRendererInterface::RenderMode renderMode = useDepth ? QSGRendererInterface::RenderMode2D
- : QSGRendererInterface::RenderMode2DNoDepthBuffer;
+ const bool useDepth = m_context->useDepthBufferFor2D();
+ const QSGRendererInterface::RenderMode renderMode = useDepth ? QSGRendererInterface::RenderMode2D
+ : QSGRendererInterface::RenderMode2DNoDepthBuffer;
m_renderer = m_context->createRenderer(renderMode);
connect(m_renderer, SIGNAL(sceneGraphChanged()), this, SLOT(markDirtyTexture()));
}
diff --git a/src/quick/scenegraph/qsgrhisupport.cpp b/src/quick/scenegraph/qsgrhisupport.cpp
index 618e1f1411..aa5661fc94 100644
--- a/src/quick/scenegraph/qsgrhisupport.cpp
+++ b/src/quick/scenegraph/qsgrhisupport.cpp
@@ -60,7 +60,7 @@ QT_BEGIN_NAMESPACE
QVulkanInstance *s_vulkanInstance = nullptr;
#endif
-QVulkanInstance *QSGRhiSupport::vulkanInstance()
+QVulkanInstance *QSGRhiSupport::defaultVulkanInstance()
{
#if QT_CONFIG(vulkan)
QSGRhiSupport *inst = QSGRhiSupport::instance();
@@ -97,7 +97,7 @@ QVulkanInstance *QSGRhiSupport::vulkanInstance()
#endif
}
-void QSGRhiSupport::cleanupVulkanInstance()
+void QSGRhiSupport::cleanupDefaultVulkanInstance()
{
#if QT_CONFIG(vulkan)
delete s_vulkanInstance;
@@ -537,7 +537,8 @@ QOffscreenSurface *QSGRhiSupport::maybeCreateOffscreenSurface(QWindow *window)
// must be called on the render thread
QRhi *QSGRhiSupport::createRhi(QQuickWindow *window, QOffscreenSurface *offscreenSurface)
{
- const QQuickGraphicsDevice &customDev(QQuickWindowPrivate::get(window)->customDeviceObjects);
+ QQuickWindowPrivate *wd = QQuickWindowPrivate::get(window);
+ const QQuickGraphicsDevice &customDev(wd->customDeviceObjects);
const QQuickGraphicsDevicePrivate *customDevD = QQuickGraphicsDevicePrivate::get(&customDev);
QRhi *rhi = nullptr;
@@ -580,6 +581,7 @@ QRhi *QSGRhiSupport::createRhi(QQuickWindow *window, QOffscreenSurface *offscree
qWarning("No QVulkanInstance set for QQuickWindow, this is wrong.");
if (window->handle()) // only used for vkGetPhysicalDeviceSurfaceSupportKHR and that implies having a valid native window
rhiParams.window = window;
+ rhiParams.deviceExtensions = wd->graphicsConfig.deviceExtensions();
if (customDevD->type == QQuickGraphicsDevicePrivate::Type::DeviceObjects) {
QRhiVulkanNativeHandles importDev;
importDev.physDev = reinterpret_cast<VkPhysicalDevice>(customDevD->u.deviceObjects.physicalDevice);
diff --git a/src/quick/scenegraph/qsgrhisupport_p.h b/src/quick/scenegraph/qsgrhisupport_p.h
index 9e81706f41..24cd787afc 100644
--- a/src/quick/scenegraph/qsgrhisupport_p.h
+++ b/src/quick/scenegraph/qsgrhisupport_p.h
@@ -104,8 +104,8 @@ class Q_QUICK_PRIVATE_EXPORT QSGRhiSupport
public:
static void configure(QSGRendererInterface::GraphicsApi api);
static QSGRhiSupport *instance();
- static QVulkanInstance *vulkanInstance();
- static void cleanupVulkanInstance();
+ static QVulkanInstance *defaultVulkanInstance();
+ static void cleanupDefaultVulkanInstance();
bool isRhiEnabled() const { return m_enableRhi; }
QRhi::Implementation rhiBackend() const { return m_rhiBackend; }