aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/scenegraph/coreapi
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick/scenegraph/coreapi')
-rw-r--r--src/quick/scenegraph/coreapi/qsgabstractrenderer.cpp190
-rw-r--r--src/quick/scenegraph/coreapi/qsgabstractrenderer_p.h69
-rw-r--r--src/quick/scenegraph/coreapi/qsgabstractrenderer_p_p.h47
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp924
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h126
-rw-r--r--src/quick/scenegraph/coreapi/qsggeometry.cpp71
-rw-r--r--src/quick/scenegraph/coreapi/qsggeometry.h50
-rw-r--r--src/quick/scenegraph/coreapi/qsggeometry_p.h41
-rw-r--r--src/quick/scenegraph/coreapi/qsgmaterial.cpp256
-rw-r--r--src/quick/scenegraph/coreapi/qsgmaterial.h54
-rw-r--r--src/quick/scenegraph/coreapi/qsgmaterialshader.cpp282
-rw-r--r--src/quick/scenegraph/coreapi/qsgmaterialshader.h61
-rw-r--r--src/quick/scenegraph/coreapi/qsgmaterialshader_p.h51
-rw-r--r--src/quick/scenegraph/coreapi/qsgmaterialtype.h40
-rw-r--r--src/quick/scenegraph/coreapi/qsgnode.cpp55
-rw-r--r--src/quick/scenegraph/coreapi/qsgnode.h47
-rw-r--r--src/quick/scenegraph/coreapi/qsgnode_p.h42
-rw-r--r--src/quick/scenegraph/coreapi/qsgnodeupdater.cpp40
-rw-r--r--src/quick/scenegraph/coreapi/qsgnodeupdater_p.h42
-rw-r--r--src/quick/scenegraph/coreapi/qsgrenderer.cpp57
-rw-r--r--src/quick/scenegraph/coreapi/qsgrenderer_p.h111
-rw-r--r--src/quick/scenegraph/coreapi/qsgrendererinterface.cpp142
-rw-r--r--src/quick/scenegraph/coreapi/qsgrendererinterface.h46
-rw-r--r--src/quick/scenegraph/coreapi/qsgrendernode.cpp268
-rw-r--r--src/quick/scenegraph/coreapi/qsgrendernode.h46
-rw-r--r--src/quick/scenegraph/coreapi/qsgrendernode_p.h47
-rw-r--r--src/quick/scenegraph/coreapi/qsgrhivisualizer.cpp71
-rw-r--r--src/quick/scenegraph/coreapi/qsgrhivisualizer_p.h48
-rw-r--r--src/quick/scenegraph/coreapi/qsgtexture.cpp206
-rw-r--r--src/quick/scenegraph/coreapi/qsgtexture.h44
-rw-r--r--src/quick/scenegraph/coreapi/qsgtexture_mac.mm43
-rw-r--r--src/quick/scenegraph/coreapi/qsgtexture_p.h68
-rw-r--r--src/quick/scenegraph/coreapi/qsgtexture_platform.h82
33 files changed, 1775 insertions, 1992 deletions
diff --git a/src/quick/scenegraph/coreapi/qsgabstractrenderer.cpp b/src/quick/scenegraph/coreapi/qsgabstractrenderer.cpp
index 6f14d5abff..ffa5599231 100644
--- a/src/quick/scenegraph/coreapi/qsgabstractrenderer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgabstractrenderer.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qsgabstractrenderer_p_p.h"
@@ -50,19 +14,6 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \enum QSGAbstractRenderer::ClearModeBit
-
- Used with setClearMode() to indicate which buffer should
- be cleared before the scene render.
-
- \value ClearColorBuffer Clear the color buffer using clearColor().
- \value ClearDepthBuffer Clear the depth buffer.
- \value ClearStencilBuffer Clear the stencil buffer.
-
- \sa setClearMode(), setClearColor()
- */
-
-/*!
\enum QSGAbstractRenderer::MatrixTransformFlag
Used with setProjectionMatrixToRect() to indicate the expectations towards
@@ -97,8 +48,9 @@ QT_BEGIN_NAMESPACE
QSGAbstractRendererPrivate::QSGAbstractRendererPrivate()
: m_root_node(nullptr)
, m_clear_color(Qt::transparent)
- , m_clear_mode(QSGAbstractRenderer::ClearColorBuffer | QSGAbstractRenderer::ClearDepthBuffer)
{
+ m_projection_matrix.resize(1);
+ m_projection_matrix_native_ndc.resize(1);
}
/*!
@@ -229,15 +181,7 @@ QRect QSGAbstractRenderer::viewportRect() const
*/
void QSGAbstractRenderer::setProjectionMatrixToRect(const QRectF &rect)
{
- QMatrix4x4 matrix;
- matrix.ortho(rect.x(),
- rect.x() + rect.width(),
- rect.y() + rect.height(),
- rect.y(),
- 1,
- -1);
- setProjectionMatrix(matrix);
- setProjectionMatrixWithNativeNDC(matrix);
+ setProjectionMatrixToRect(rect, {}, false);
}
/*!
@@ -253,46 +197,77 @@ void QSGAbstractRenderer::setProjectionMatrixToRect(const QRectF &rect)
*/
void QSGAbstractRenderer::setProjectionMatrixToRect(const QRectF &rect, MatrixTransformFlags flags)
{
+ setProjectionMatrixToRect(rect, flags, flags.testFlag(MatrixTransformFlipY));
+}
+
+/*!
+ Convenience method that calls setProjectionMatrix() with an
+ orthographic matrix generated from \a rect.
+
+ Set MatrixTransformFlipY in \a flags when the graphics API uses Y down in
+ its normalized device coordinate system (for example, Vulkan).
+
+ Convenience method that calls setProjectionMatrixWithNativeNDC() with an
+ orthographic matrix generated from \a rect.
+
+ Set true to \a nativeNDCFlipY to flip the Y axis relative to
+ projection matrix in its normalized device coordinate system.
+
+ \sa setProjectionMatrix(), projectionMatrix()
+ \sa setProjectionMatrixWithNativeNDC(), projectionMatrixWithNativeNDC()
+
+ \since 6.7
+ */
+void QSGAbstractRenderer::setProjectionMatrixToRect(const QRectF &rect, MatrixTransformFlags flags,
+ bool nativeNDCFlipY)
+{
const bool flipY = flags.testFlag(MatrixTransformFlipY);
+
+ const float left = rect.x();
+ const float right = rect.x() + rect.width();
+ float bottom = rect.y() + rect.height();
+ float top = rect.y();
+
+ if (flipY)
+ std::swap(top, bottom);
+
QMatrix4x4 matrix;
- matrix.ortho(rect.x(),
- rect.x() + rect.width(),
- flipY ? rect.y() : rect.y() + rect.height(),
- flipY ? rect.y() + rect.height() : rect.y(),
- 1,
- -1);
- setProjectionMatrix(matrix);
-
- if (flipY) {
+ matrix.ortho(left, right, bottom, top, 1, -1);
+ setProjectionMatrix(matrix, 0);
+
+ if (nativeNDCFlipY) {
+ std::swap(top, bottom);
+
matrix.setToIdentity();
- matrix.ortho(rect.x(),
- rect.x() + rect.width(),
- rect.y() + rect.height(),
- rect.y(),
- 1,
- -1);
+ matrix.ortho(left, right, bottom, top, 1, -1);
}
- setProjectionMatrixWithNativeNDC(matrix);
+ setProjectionMatrixWithNativeNDC(matrix, 0);
}
/*!
Use \a matrix to project the QSGNode coordinates onto surface pixels.
+ \a index specifies the view index when multiview rendering is in use.
+
\sa projectionMatrix(), setProjectionMatrixToRect()
*/
-void QSGAbstractRenderer::setProjectionMatrix(const QMatrix4x4 &matrix)
+void QSGAbstractRenderer::setProjectionMatrix(const QMatrix4x4 &matrix, int index)
{
Q_D(QSGAbstractRenderer);
- d->m_projection_matrix = matrix;
+ if (d->m_projection_matrix.count() <= index)
+ d->m_projection_matrix.resize(index + 1);
+ d->m_projection_matrix[index] = matrix;
}
/*!
\internal
*/
-void QSGAbstractRenderer::setProjectionMatrixWithNativeNDC(const QMatrix4x4 &matrix)
+void QSGAbstractRenderer::setProjectionMatrixWithNativeNDC(const QMatrix4x4 &matrix, int index)
{
Q_D(QSGAbstractRenderer);
- d->m_projection_matrix_native_ndc = matrix;
+ if (d->m_projection_matrix_native_ndc.count() <= index)
+ d->m_projection_matrix_native_ndc.resize(index + 1);
+ d->m_projection_matrix_native_ndc[index] = matrix;
}
/*!
@@ -300,67 +275,54 @@ void QSGAbstractRenderer::setProjectionMatrixWithNativeNDC(const QMatrix4x4 &mat
\sa setProjectionMatrix(), setProjectionMatrixToRect()
*/
-QMatrix4x4 QSGAbstractRenderer::projectionMatrix() const
+QMatrix4x4 QSGAbstractRenderer::projectionMatrix(int index) const
{
Q_D(const QSGAbstractRenderer);
- return d->m_projection_matrix;
+ return d->m_projection_matrix[index];
}
-/*!
- \internal
- */
-QMatrix4x4 QSGAbstractRenderer::projectionMatrixWithNativeNDC() const
+int QSGAbstractRenderer::projectionMatrixCount() const
{
Q_D(const QSGAbstractRenderer);
- return d->m_projection_matrix_native_ndc;
+ return d->m_projection_matrix.count();
}
-/*!
- Use \a color to clear the framebuffer when clearMode() is
- set to QSGAbstractRenderer::ClearColorBuffer.
-
- \sa clearColor(), setClearMode()
- */
-void QSGAbstractRenderer::setClearColor(const QColor &color)
+int QSGAbstractRenderer::projectionMatrixWithNativeNDCCount() const
{
- Q_D(QSGAbstractRenderer);
- d->m_clear_color = color;
+ Q_D(const QSGAbstractRenderer);
+ return d->m_projection_matrix_native_ndc.count();
}
/*!
- Returns the color that clears the framebuffer at the beginning
- of the rendering.
-
- \sa setClearColor(), clearMode()
+ \internal
*/
-QColor QSGAbstractRenderer::clearColor() const
+QMatrix4x4 QSGAbstractRenderer::projectionMatrixWithNativeNDC(int index) const
{
Q_D(const QSGAbstractRenderer);
- return d->m_clear_color;
+ return d->m_projection_matrix_native_ndc[index];
}
/*!
- Defines which attachment of the framebuffer should be cleared
- before each scene render with the \a mode flag.
+ Sets the \a color to clear the framebuffer.
- \sa clearMode(), setClearColor()
+ \sa clearColor()
*/
-void QSGAbstractRenderer::setClearMode(ClearMode mode)
+void QSGAbstractRenderer::setClearColor(const QColor &color)
{
Q_D(QSGAbstractRenderer);
- d->m_clear_mode = mode;
+ d->m_clear_color = color;
}
/*!
- Flags defining which attachment of the framebuffer will be cleared
- before each scene render.
+ Returns the color that clears the framebuffer at the beginning
+ of the rendering.
- \sa setClearMode(), clearColor()
+ \sa setClearColor()
*/
-QSGAbstractRenderer::ClearMode QSGAbstractRenderer::clearMode() const
+QColor QSGAbstractRenderer::clearColor() const
{
Q_D(const QSGAbstractRenderer);
- return d->m_clear_mode;
+ return d->m_clear_color;
}
/*!
@@ -377,3 +339,5 @@ void QSGAbstractRenderer::renderSceneInline()
}
QT_END_NAMESPACE
+
+#include "moc_qsgabstractrenderer_p.cpp"
diff --git a/src/quick/scenegraph/coreapi/qsgabstractrenderer_p.h b/src/quick/scenegraph/coreapi/qsgabstractrenderer_p.h
index 139edda884..5d7a3b13b6 100644
--- a/src/quick/scenegraph/coreapi/qsgabstractrenderer_p.h
+++ b/src/quick/scenegraph/coreapi/qsgabstractrenderer_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSGABSTRACTRENDERER_P_H
#define QSGABSTRACTRENDERER_P_H
@@ -53,6 +17,7 @@
#include <QtQuick/private/qtquickglobal_p.h>
#include <QtQuick/qsgnode.h>
+#include <QtCore/qobject.h>
#ifndef GLuint
#define GLuint uint
@@ -62,19 +27,10 @@ QT_BEGIN_NAMESPACE
class QSGAbstractRendererPrivate;
-class Q_QUICK_PRIVATE_EXPORT QSGAbstractRenderer : public QObject
+class Q_QUICK_EXPORT QSGAbstractRenderer : public QObject
{
Q_OBJECT
public:
- enum ClearModeBit
- {
- ClearColorBuffer = 0x0001,
- ClearDepthBuffer = 0x0002,
- ClearStencilBuffer = 0x0004
- };
- Q_DECLARE_FLAGS(ClearMode, ClearModeBit)
- Q_FLAG(ClearMode)
-
enum MatrixTransformFlag
{
MatrixTransformFlipY = 0x01
@@ -96,17 +52,18 @@ public:
void setProjectionMatrixToRect(const QRectF &rect);
void setProjectionMatrixToRect(const QRectF &rect, MatrixTransformFlags flags);
- void setProjectionMatrix(const QMatrix4x4 &matrix);
- void setProjectionMatrixWithNativeNDC(const QMatrix4x4 &matrix);
- QMatrix4x4 projectionMatrix() const;
- QMatrix4x4 projectionMatrixWithNativeNDC() const;
+ void setProjectionMatrixToRect(const QRectF &rect, MatrixTransformFlags flags,
+ bool nativeNDCFlipY);
+ void setProjectionMatrix(const QMatrix4x4 &matrix, int index = 0);
+ void setProjectionMatrixWithNativeNDC(const QMatrix4x4 &matrix, int index = 0);
+ QMatrix4x4 projectionMatrix(int index) const;
+ QMatrix4x4 projectionMatrixWithNativeNDC(int index) const;
+ int projectionMatrixCount() const;
+ int projectionMatrixWithNativeNDCCount() const;
void setClearColor(const QColor &color);
QColor clearColor() const;
- void setClearMode(ClearMode mode);
- ClearMode clearMode() const;
-
virtual void renderScene() = 0;
virtual void prepareSceneInline();
@@ -124,8 +81,6 @@ private:
friend class QSGRootNode;
};
-Q_DECLARE_OPERATORS_FOR_FLAGS(QSGAbstractRenderer::ClearMode)
-
QT_END_NAMESPACE
#endif
diff --git a/src/quick/scenegraph/coreapi/qsgabstractrenderer_p_p.h b/src/quick/scenegraph/coreapi/qsgabstractrenderer_p_p.h
index 42e9acb437..3bc04247db 100644
--- a/src/quick/scenegraph/coreapi/qsgabstractrenderer_p_p.h
+++ b/src/quick/scenegraph/coreapi/qsgabstractrenderer_p_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSGABSTRACTRENDERER_P_P_H
#define QSGABSTRACTRENDERER_P_P_H
@@ -61,7 +25,7 @@
QT_BEGIN_NAMESPACE
-class Q_QUICK_PRIVATE_EXPORT QSGAbstractRendererPrivate : public QObjectPrivate
+class Q_QUICK_EXPORT QSGAbstractRendererPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QSGAbstractRenderer)
public:
@@ -72,13 +36,12 @@ public:
QSGRootNode *m_root_node;
QColor m_clear_color;
- QSGAbstractRenderer::ClearMode m_clear_mode;
QRect m_device_rect;
QRect m_viewport_rect;
- QMatrix4x4 m_projection_matrix;
- QMatrix4x4 m_projection_matrix_native_ndc;
+ QVarLengthArray<QMatrix4x4, 1> m_projection_matrix;
+ QVarLengthArray<QMatrix4x4, 1> m_projection_matrix_native_ndc;
uint m_mirrored : 1;
};
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
index cca46986e3..5746d984bf 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
@@ -1,43 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Copyright (C) 2016 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
-** Copyright (C) 2016 Robin Burchell <robin.burchell@viroteck.net>
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// Copyright (C) 2016 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
+// Copyright (C) 2016 Robin Burchell <robin.burchell@viroteck.net>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qsgbatchrenderer_p.h"
@@ -58,7 +22,7 @@
QT_BEGIN_NAMESPACE
#ifndef QT_NO_DEBUG
-Q_QUICK_PRIVATE_EXPORT bool qsg_test_and_clear_material_failure();
+Q_QUICK_EXPORT bool qsg_test_and_clear_material_failure();
#endif
int qt_sg_envInt(const char *name, int defaultValue);
@@ -120,7 +84,11 @@ const uint DYNAMIC_VERTEX_INDEX_BUFFER_THRESHOLD = 4;
const int VERTEX_BUFFER_BINDING = 0;
const int ZORDER_BUFFER_BINDING = VERTEX_BUFFER_BINDING + 1;
-static inline uint aligned(uint v, uint byteAlign)
+const float VIEWPORT_MIN_DEPTH = 0.0f;
+const float VIEWPORT_MAX_DEPTH = 1.0f;
+
+template <class Int>
+inline Int aligned(Int v, Int byteAlign)
{
return (v + byteAlign - 1) & ~(byteAlign - 1);
}
@@ -150,8 +118,7 @@ QRhiVertexInputAttribute::Format qsg_vertexInputFormat(const QSGGeometry::Attrib
break;
}
qWarning("Unsupported attribute type 0x%x with %d components", a.type, a.tupleSize);
- Q_UNREACHABLE();
- return QRhiVertexInputAttribute::Float;
+ Q_UNREACHABLE_RETURN(QRhiVertexInputAttribute::Float);
}
static QRhiVertexInputLayout calculateVertexInputLayout(const QSGMaterialShader *s, const QSGGeometry *geometry, bool batchable)
@@ -166,7 +133,7 @@ static QRhiVertexInputLayout calculateVertexInputLayout(const QSGMaterialShader
const int attrCount = geometry->attributeCount();
QVarLengthArray<QRhiVertexInputAttribute, 8> inputAttributes;
inputAttributes.reserve(attrCount + 1);
- int offset = 0;
+ quint32 offset = 0;
for (int i = 0; i < attrCount; ++i) {
const QSGGeometry::Attribute &a = geometry->attributes()[i];
if (!sd->vertexShader->vertexInputLocations.contains(a.position)) {
@@ -204,8 +171,7 @@ QRhiCommandBuffer::IndexFormat qsg_indexFormat(const QSGGeometry *geometry)
return QRhiCommandBuffer::IndexUInt32;
break;
default:
- Q_UNREACHABLE();
- return QRhiCommandBuffer::IndexUInt16;
+ Q_UNREACHABLE_RETURN(QRhiCommandBuffer::IndexUInt16);
}
}
@@ -235,13 +201,22 @@ QRhiGraphicsPipeline::Topology qsg_topology(int geomDrawMode)
return topology;
}
+void qsg_setMultiViewFlagsOnMaterial(QSGMaterial *material, int multiViewCount)
+{
+ material->setFlag(QSGMaterial::MultiView2, multiViewCount == 2);
+ material->setFlag(QSGMaterial::MultiView3, multiViewCount == 3);
+ material->setFlag(QSGMaterial::MultiView4, multiViewCount == 4);
+}
+
ShaderManager::Shader *ShaderManager::prepareMaterial(QSGMaterial *material,
const QSGGeometry *geometry,
- QSGRendererInterface::RenderMode renderMode)
+ QSGRendererInterface::RenderMode renderMode,
+ int multiViewCount)
{
- QSGMaterialType *type = material->type();
+ qsg_setMultiViewFlagsOnMaterial(material, multiViewCount);
- ShaderKey key = qMakePair(type, renderMode);
+ QSGMaterialType *type = material->type();
+ ShaderKey key = { type, renderMode, multiViewCount };
Shader *shader = rewrittenShaders.value(key, nullptr);
if (shader)
return shader;
@@ -249,12 +224,12 @@ ShaderManager::Shader *ShaderManager::prepareMaterial(QSGMaterial *material,
shader = new Shader;
QSGMaterialShader *s = static_cast<QSGMaterialShader *>(material->createShader(renderMode));
context->initializeRhiShader(s, QShader::BatchableVertexShader);
- shader->programRhi.program = s;
- shader->programRhi.inputLayout = calculateVertexInputLayout(s, geometry, true);
+ shader->materialShader = s;
+ shader->inputLayout = calculateVertexInputLayout(s, geometry, true);
QSGMaterialShaderPrivate *sD = QSGMaterialShaderPrivate::get(s);
- shader->programRhi.shaderStages = {
- { QRhiGraphicsShaderStage::Vertex, sD->shader(QShader::VertexStage), QShader::BatchableVertexShader },
- { QRhiGraphicsShaderStage::Fragment, sD->shader(QShader::FragmentStage) }
+ shader->stages = {
+ { QRhiShaderStage::Vertex, sD->shader(QShader::VertexStage), QShader::BatchableVertexShader },
+ { QRhiShaderStage::Fragment, sD->shader(QShader::FragmentStage) }
};
shader->lastOpacity = 0;
@@ -265,11 +240,13 @@ ShaderManager::Shader *ShaderManager::prepareMaterial(QSGMaterial *material,
ShaderManager::Shader *ShaderManager::prepareMaterialNoRewrite(QSGMaterial *material,
const QSGGeometry *geometry,
- QSGRendererInterface::RenderMode renderMode)
+ QSGRendererInterface::RenderMode renderMode,
+ int multiViewCount)
{
- QSGMaterialType *type = material->type();
+ qsg_setMultiViewFlagsOnMaterial(material, multiViewCount);
- ShaderKey key = qMakePair(type, renderMode);
+ QSGMaterialType *type = material->type();
+ ShaderKey key = { type, renderMode, multiViewCount };
Shader *shader = stockShaders.value(key, nullptr);
if (shader)
return shader;
@@ -277,12 +254,12 @@ ShaderManager::Shader *ShaderManager::prepareMaterialNoRewrite(QSGMaterial *mate
shader = new Shader;
QSGMaterialShader *s = static_cast<QSGMaterialShader *>(material->createShader(renderMode));
context->initializeRhiShader(s, QShader::StandardShader);
- shader->programRhi.program = s;
- shader->programRhi.inputLayout = calculateVertexInputLayout(s, geometry, false);
+ shader->materialShader = s;
+ shader->inputLayout = calculateVertexInputLayout(s, geometry, false);
QSGMaterialShaderPrivate *sD = QSGMaterialShaderPrivate::get(s);
- shader->programRhi.shaderStages = {
- { QRhiGraphicsShaderStage::Vertex, sD->shader(QShader::VertexStage) },
- { QRhiGraphicsShaderStage::Fragment, sD->shader(QShader::FragmentStage) }
+ shader->stages = {
+ { QRhiShaderStage::Vertex, sD->shader(QShader::VertexStage) },
+ { QRhiShaderStage::Fragment, sD->shader(QShader::FragmentStage) }
};
shader->lastOpacity = 0;
@@ -299,24 +276,24 @@ void ShaderManager::invalidated()
qDeleteAll(rewrittenShaders);
rewrittenShaders.clear();
- qDeleteAll(srbCache);
- srbCache.clear();
-
qDeleteAll(pipelineCache);
pipelineCache.clear();
+
+ qDeleteAll(srbPool);
+ srbPool.clear();
}
void ShaderManager::clearCachedRendererData()
{
- for (ShaderManager::Shader *sms : stockShaders) {
- QSGMaterialShader *s = sms->programRhi.program;
+ for (ShaderManager::Shader *sms : std::as_const(stockShaders)) {
+ QSGMaterialShader *s = sms->materialShader;
if (s) {
QSGMaterialShaderPrivate *sd = QSGMaterialShaderPrivate::get(s);
sd->clearCachedRendererData();
}
}
- for (ShaderManager::Shader *sms : rewrittenShaders) {
- QSGMaterialShader *s = sms->programRhi.program;
+ for (ShaderManager::Shader *sms : std::as_const(rewrittenShaders)) {
+ QSGMaterialShader *s = sms->materialShader;
if (s) {
QSGMaterialShaderPrivate *sd = QSGMaterialShaderPrivate::get(s);
sd->clearCachedRendererData();
@@ -324,24 +301,6 @@ void ShaderManager::clearCachedRendererData()
}
}
-QRhiShaderResourceBindings *ShaderManager::srb(const ShaderResourceBindingList &bindings)
-{
- auto it = srbCache.constFind(bindings);
- if (it != srbCache.constEnd())
- return *it;
-
- QRhiShaderResourceBindings *srb = context->rhi()->newShaderResourceBindings();
- srb->setBindings(bindings.cbegin(), bindings.cend());
- if (srb->create()) {
- srbCache.insert(bindings, srb);
- } else {
- qWarning("Failed to build srb");
- delete srb;
- srb = nullptr;
- }
- return srb;
-}
-
void qsg_dumpShadowRoots(BatchRootInfo *i, int indent)
{
static int extraIndent = 0;
@@ -748,7 +707,7 @@ BatchCompatibility Batch::isMaterialCompatible(Element *e) const
QSGMaterial *m = e->node->activeMaterial();
QSGMaterial *nm = n->node->activeMaterial();
- return (nm->type() == m->type() && nm->compare(m) == 0)
+ return (nm->type() == m->type() && nm->viewCount() == m->viewCount() && nm->compare(m) == 0)
? BatchIsCompatible
: BatchBreaksOnCompare;
}
@@ -891,6 +850,8 @@ Renderer::Renderer(QSGDefaultRenderContext *ctx, QSGRendererInterface::RenderMod
, m_elementsToDelete(64)
, m_tmpAlphaElements(16)
, m_tmpOpaqueElements(16)
+ , m_vboPool(16)
+ , m_iboPool(16)
, m_rebuild(FullRebuild)
, m_zRange(0)
#if defined(QSGBATCHRENDERER_INVALIDATE_WEDGED_NODES)
@@ -918,7 +879,7 @@ Renderer::Renderer(QSGDefaultRenderContext *ctx, QSGRendererInterface::RenderMod
// The shader manager is shared between renderers (think for example Item
// layers that create a new Renderer each) with the same rendercontext (and
// so same QRhi).
- m_shaderManager = ctx->findChild<ShaderManager *>(QStringLiteral("__qt_ShaderManager"), Qt::FindDirectChildrenOnly);
+ m_shaderManager = ctx->findChild<ShaderManager *>(QString(), Qt::FindDirectChildrenOnly);
if (!m_shaderManager) {
m_shaderManager = new ShaderManager(ctx);
m_shaderManager->setObjectName(QStringLiteral("__qt_ShaderManager"));
@@ -928,17 +889,17 @@ Renderer::Renderer(QSGDefaultRenderContext *ctx, QSGRendererInterface::RenderMod
m_batchNodeThreshold = qt_sg_envInt("QSG_RENDERER_BATCH_NODE_THRESHOLD", 64);
m_batchVertexThreshold = qt_sg_envInt("QSG_RENDERER_BATCH_VERTEX_THRESHOLD", 1024);
+ m_srbPoolThreshold = qt_sg_envInt("QSG_RENDERER_SRB_POOL_THRESHOLD", 1024);
if (Q_UNLIKELY(debug_build() || debug_render())) {
- qDebug("Batch thresholds: nodes: %d vertices: %d",
- m_batchNodeThreshold, m_batchVertexThreshold);
+ qDebug("Batch thresholds: nodes: %d vertices: %d Srb pool threshold: %d",
+ m_batchNodeThreshold, m_batchVertexThreshold, m_srbPoolThreshold);
}
}
static void qsg_wipeBuffer(Buffer *buffer)
{
- if (buffer->buf)
- delete buffer->buf;
+ delete buffer->buf;
// The free here is ok because we're in one of two situations.
// 1. We're using the upload pool in which case unmap will have set the
@@ -948,11 +909,10 @@ static void qsg_wipeBuffer(Buffer *buffer)
free(buffer->data);
}
-static void qsg_wipeBatch(Batch *batch, bool separateIndexBuffer)
+static void qsg_wipeBatch(Batch *batch)
{
qsg_wipeBuffer(&batch->vbo);
- if (separateIndexBuffer)
- qsg_wipeBuffer(&batch->ibo);
+ qsg_wipeBuffer(&batch->ibo);
delete batch->ubuf;
batch->stencilClipState.reset();
delete batch;
@@ -961,32 +921,31 @@ static void qsg_wipeBatch(Batch *batch, bool separateIndexBuffer)
Renderer::~Renderer()
{
if (m_rhi) {
- // If setExternalRenderPassDescriptor() was called, we have to
- // aggressively invalidate to prevent an object, the lifetime of which
- // we have no control over, staying in the (per-window) caches.
- invalidatePipelineCacheDependency(m_external_rp_desc);
-
// Clean up batches and buffers
- const bool separateIndexBuffer = m_context->separateIndexBuffer();
for (int i = 0; i < m_opaqueBatches.size(); ++i)
- qsg_wipeBatch(m_opaqueBatches.at(i), separateIndexBuffer);
+ qsg_wipeBatch(m_opaqueBatches.at(i));
for (int i = 0; i < m_alphaBatches.size(); ++i)
- qsg_wipeBatch(m_alphaBatches.at(i), separateIndexBuffer);
+ qsg_wipeBatch(m_alphaBatches.at(i));
for (int i = 0; i < m_batchPool.size(); ++i)
- qsg_wipeBatch(m_batchPool.at(i), separateIndexBuffer);
+ qsg_wipeBatch(m_batchPool.at(i));
+ for (int i = 0; i < m_vboPool.size(); ++i)
+ delete m_vboPool.at(i);
+ for (int i = 0; i < m_iboPool.size(); ++i)
+ delete m_iboPool.at(i);
}
- for (Node *n : qAsConst(m_nodes))
+ for (Node *n : std::as_const(m_nodes)) {
+ if (n->type() == QSGNode::GeometryNodeType) {
+ Element *e = n->element();
+ if (!e->removed)
+ m_elementsToDelete.add(e);
+ }
m_nodeAllocator.release(n);
+ }
// Remaining elements...
- for (int i=0; i<m_elementsToDelete.size(); ++i) {
- Element *e = m_elementsToDelete.at(i);
- if (e->isRenderNode)
- delete static_cast<RenderNodeElement *>(e);
- else
- m_elementAllocator.release(e);
- }
+ for (int i=0; i<m_elementsToDelete.size(); ++i)
+ releaseElement(m_elementsToDelete.at(i), true);
destroyGraphicsResources();
@@ -1017,10 +976,29 @@ void Renderer::releaseCachedResources()
m_dummyTexture = nullptr;
m_rhi->releaseCachedResources();
+
+ m_vertexUploadPool.shrink(0);
+ m_vertexUploadPool.reset();
+ m_indexUploadPool.shrink(0);
+ m_indexUploadPool.reset();
+
+ for (int i = 0; i < m_vboPool.size(); ++i)
+ delete m_vboPool.at(i);
+ m_vboPool.reset();
+
+ for (int i = 0; i < m_iboPool.size(); ++i)
+ delete m_iboPool.at(i);
+ m_iboPool.reset();
}
void Renderer::invalidateAndRecycleBatch(Batch *b)
{
+ if (b->vbo.buf != nullptr)
+ m_vboPool.add(b->vbo.buf);
+ if (b->ibo.buf != nullptr)
+ m_iboPool.add(b->ibo.buf);
+ b->vbo.buf = nullptr;
+ b->ibo.buf = nullptr;
b->invalidate();
for (int i=0; i<m_batchPool.size(); ++i)
if (b == m_batchPool.at(i))
@@ -1028,14 +1006,13 @@ void Renderer::invalidateAndRecycleBatch(Batch *b)
m_batchPool.add(b);
}
-void Renderer::map(Buffer *buffer, int byteSize, bool isIndexBuf)
+void Renderer::map(Buffer *buffer, quint32 byteSize, bool isIndexBuf)
{
if (m_visualizer->mode() == Visualizer::VisualizeNothing) {
// Common case, use a shared memory pool for uploading vertex data to avoid
// excessive reevaluation
- QDataBuffer<char> &pool = m_context->separateIndexBuffer() && isIndexBuf
- ? m_indexUploadPool : m_vertexUploadPool;
- if (byteSize > pool.size())
+ QDataBuffer<char> &pool = isIndexBuf ? m_indexUploadPool : m_vertexUploadPool;
+ if (byteSize > quint32(pool.size()))
pool.resize(byteSize);
buffer->data = pool.data();
} else if (buffer->size != byteSize) {
@@ -1050,14 +1027,40 @@ void Renderer::unmap(Buffer *buffer, bool isIndexBuf)
{
// Batches are pooled and reused which means the QRhiBuffer will be
// still valid in a recycled Batch. We only hit the newBuffer() path
- // for brand new Batches.
- if (!buffer->buf) {
+ // when there are no buffers to recycle.
+ QDataBuffer<QRhiBuffer *> *bufferPool = isIndexBuf ? &m_iboPool : &m_vboPool;
+ if (!buffer->buf && bufferPool->isEmpty()) {
buffer->buf = m_rhi->newBuffer(QRhiBuffer::Immutable,
isIndexBuf ? QRhiBuffer::IndexBuffer : QRhiBuffer::VertexBuffer,
buffer->size);
- if (!buffer->buf->create())
- qWarning("Failed to build vertex/index buffer of size %d", buffer->size);
+ if (!buffer->buf->create()) {
+ qWarning("Failed to build vertex/index buffer of size %u", buffer->size);
+ delete buffer->buf;
+ buffer->buf = nullptr;
+ }
} else {
+ if (!buffer->buf) {
+ const quint32 expectedSize = buffer->size;
+ qsizetype foundBufferIndex = 0;
+ for (qsizetype i = 0; i < bufferPool->size(); ++i) {
+ QRhiBuffer *testBuffer = bufferPool->at(i);
+ if (!buffer->buf
+ || (testBuffer->size() >= expectedSize && testBuffer->size() < buffer->buf->size())
+ || (testBuffer->size() < expectedSize && testBuffer->size() > buffer->buf->size())) {
+ foundBufferIndex = i;
+ buffer->buf = testBuffer;
+ if (buffer->buf->size() == expectedSize)
+ break;
+ }
+ }
+
+ if (foundBufferIndex < bufferPool->size() - 1) {
+ qSwap(bufferPool->data()[foundBufferIndex],
+ bufferPool->data()[bufferPool->size() - 1]);
+ }
+ bufferPool->pop_back();
+ }
+
bool needsRebuild = false;
if (buffer->buf->size() < buffer->size) {
buffer->buf->setSize(buffer->size);
@@ -1070,16 +1073,23 @@ void Renderer::unmap(Buffer *buffer, bool isIndexBuf)
buffer->nonDynamicChangeCount = 0;
needsRebuild = true;
}
- if (needsRebuild)
- buffer->buf->create();
+ if (needsRebuild) {
+ if (!buffer->buf->create()) {
+ qWarning("Failed to (re)build vertex/index buffer of size %u", buffer->size);
+ delete buffer->buf;
+ buffer->buf = nullptr;
+ }
+ }
}
- if (buffer->buf->type() != QRhiBuffer::Dynamic) {
- m_resourceUpdates->uploadStaticBuffer(buffer->buf,
- 0, buffer->size, buffer->data);
- buffer->nonDynamicChangeCount += 1;
- } else {
- m_resourceUpdates->updateDynamicBuffer(buffer->buf, 0, buffer->size,
- buffer->data);
+ if (buffer->buf) {
+ if (buffer->buf->type() != QRhiBuffer::Dynamic) {
+ m_resourceUpdates->uploadStaticBuffer(buffer->buf,
+ 0, buffer->size, buffer->data);
+ buffer->nonDynamicChangeCount += 1;
+ } else {
+ m_resourceUpdates->updateDynamicBuffer(buffer->buf, 0, buffer->size,
+ buffer->data);
+ }
}
if (m_visualizer->mode() == Visualizer::VisualizeNothing)
buffer->data = nullptr;
@@ -1266,8 +1276,13 @@ void Renderer::nodeWasRemoved(Node *node)
if (e) {
e->removed = true;
m_elementsToDelete.add(e);
- if (m_renderNodeElements.isEmpty())
+ if (m_renderNodeElements.isEmpty()) {
m_forceNoDepthBuffer = false;
+ // Must have a full rebuild given useDepthBuffer() now returns
+ // a different value than before, meaning there can once again
+ // be an opaque pass.
+ m_rebuild |= FullRebuild;
+ }
if (e->batch != nullptr)
e->batch->needsPurge = true;
@@ -1726,6 +1741,7 @@ void Renderer::prepareOpaqueBatches()
&& gni->geometry()->attributes() == gnj->geometry()->attributes()
&& gni->inheritedOpacity() == gnj->inheritedOpacity()
&& gni->activeMaterial()->type() == gnj->activeMaterial()->type()
+ && gni->activeMaterial()->viewCount() == gnj->activeMaterial()->viewCount()
&& gni->activeMaterial()->compare(gnj->activeMaterial()) == 0) {
ej->batch = batch;
next->nextInBatch = ej;
@@ -1829,10 +1845,15 @@ void Renderer::prepareAlphaBatches()
if (gni->clipList() == gnj->clipList()
&& gni->geometry()->drawingMode() == gnj->geometry()->drawingMode()
- && (gni->geometry()->drawingMode() != QSGGeometry::DrawLines || gni->geometry()->lineWidth() == gnj->geometry()->lineWidth())
+ && (gni->geometry()->drawingMode() != QSGGeometry::DrawLines
+ || (gni->geometry()->lineWidth() == gnj->geometry()->lineWidth()
+ // Must not do overlap checks when the line width is not 1,
+ // we have no knowledge how such lines are rasterized.
+ && gni->geometry()->lineWidth() == 1.0f))
&& gni->geometry()->attributes() == gnj->geometry()->attributes()
&& gni->inheritedOpacity() == gnj->inheritedOpacity()
&& gni->activeMaterial()->type() == gnj->activeMaterial()->type()
+ && gni->activeMaterial()->viewCount() == gnj->activeMaterial()->viewCount()
&& gni->activeMaterial()->compare(gnj->activeMaterial()) == 0) {
if (!overlapBounds.intersects(ej->bounds) || !checkOverlap(i+1, j - 1, ej->bounds)) {
ej->batch = batch;
@@ -1878,6 +1899,12 @@ static inline int qsg_fixIndexCount(int iCount, int drawMode)
}
}
+static inline float calculateElementZOrder(const Element *e, qreal zRange)
+{
+ // Clamp the zOrder to within the min and max depth of the viewport.
+ return std::clamp(1.0f - float(e->order * zRange), VIEWPORT_MIN_DEPTH, VIEWPORT_MAX_DEPTH);
+}
+
/* These parameters warrant some explanation...
*
* vaOffset: The byte offset into the vertex data to the location of the
@@ -1922,7 +1949,7 @@ void Renderer::uploadMergedElement(Element *e, int vaOffset, char **vertexData,
if (useDepthBuffer()) {
float *vzorder = (float *) *zData;
- float zorder = 1.0f - e->order * m_zRange;
+ float zorder = calculateElementZOrder(e, m_zRange);
for (int i=0; i<vCount; ++i)
vzorder[i] = zorder;
*zData += vCount * sizeof(float);
@@ -2030,8 +2057,8 @@ void Renderer::uploadBatch(Batch *b)
bool canMerge = (g->drawingMode() == QSGGeometry::DrawTriangles || g->drawingMode() == QSGGeometry::DrawTriangleStrip ||
g->drawingMode() == QSGGeometry::DrawLines || g->drawingMode() == QSGGeometry::DrawPoints)
&& b->positionAttribute >= 0
- && g->indexType() == QSGGeometry::UnsignedShortType
- && (flags & (QSGMaterial::CustomCompileStep | QSGMaterial_FullMatrix)) == 0
+ && (g->indexType() == QSGGeometry::UnsignedShortType && g->indexCount() > 0)
+ && (flags & (QSGMaterial::NoBatching | QSGMaterial_FullMatrix)) == 0
&& ((flags & QSGMaterial::RequiresFullMatrixExceptTranslate) == 0 || b->isTranslateOnlyToRoot())
&& b->isSafeToBatch();
@@ -2086,11 +2113,7 @@ void Renderer::uploadBatch(Batch *b)
ibufferSize = unmergedIndexSize;
}
- const bool separateIndexBuffer = m_context->separateIndexBuffer();
- if (separateIndexBuffer)
- map(&b->ibo, ibufferSize, true);
- else
- bufferSize += ibufferSize;
+ map(&b->ibo, ibufferSize, true);
map(&b->vbo, bufferSize);
if (Q_UNLIKELY(debug_upload())) qDebug() << " - batch" << b << " first:" << b->first << " root:"
@@ -2100,9 +2123,7 @@ void Renderer::uploadBatch(Batch *b)
if (b->merged) {
char *vertexData = b->vbo.data;
char *zData = vertexData + b->vertexCount * g->sizeOfVertex();
- char *indexData = separateIndexBuffer
- ? b->ibo.data
- : zData + (int(useDepthBuffer()) * b->vertexCount * sizeof(float));
+ char *indexData = b->ibo.data;
quint16 iOffset16 = 0;
quint32 iOffset32 = 0;
@@ -2114,8 +2135,8 @@ void Renderer::uploadBatch(Batch *b)
const uint verticesInSetLimit = m_uint32IndexForRhi ? 0xfffffffe : 0xfffe;
int indicesInSet = 0;
b->drawSets.reset();
- int drawSetIndices = separateIndexBuffer ? 0 : indexData - vertexData;
- const char *indexBase = separateIndexBuffer ? b->ibo.data : b->vbo.data;
+ int drawSetIndices = 0;
+ const char *indexBase = b->ibo.data;
b->drawSets << DrawSet(0, zData - vertexData, drawSetIndices);
while (e) {
verticesInSet += e->node->geometry()->vertexCount();
@@ -2149,8 +2170,7 @@ void Renderer::uploadBatch(Batch *b)
}
} else {
char *vboData = b->vbo.data;
- char *iboData = separateIndexBuffer ? b->ibo.data
- : vboData + b->vertexCount * g->sizeOfVertex();
+ char *iboData = b->ibo.data;
Element *e = b->first;
while (e) {
QSGGeometry *g = e->node->geometry();
@@ -2212,9 +2232,7 @@ void Renderer::uploadBatch(Batch *b)
if (!b->drawSets.isEmpty()) {
if (m_uint32IndexForRhi) {
- const quint32 *id = (const quint32 *)(separateIndexBuffer
- ? b->ibo.data
- : b->vbo.data + b->drawSets.at(0).indices);
+ const quint32 *id = (const quint32 *) b->ibo.data;
{
QDebug iDump = qDebug();
iDump << " -- Index Data, count:" << b->indexCount;
@@ -2225,9 +2243,7 @@ void Renderer::uploadBatch(Batch *b)
}
}
} else {
- const quint16 *id = (const quint16 *)(separateIndexBuffer
- ? b->ibo.data
- : b->vbo.data + b->drawSets.at(0).indices);
+ const quint16 *id = (const quint16 *) b->ibo.data;
{
QDebug iDump = qDebug();
iDump << " -- Index Data, count:" << b->indexCount;
@@ -2248,8 +2264,7 @@ void Renderer::uploadBatch(Batch *b)
#endif // QT_NO_DEBUG_OUTPUT
unmap(&b->vbo);
- if (separateIndexBuffer)
- unmap(&b->ibo, true);
+ unmap(&b->ibo, true);
if (Q_UNLIKELY(debug_upload())) qDebug() << " --- vertex/index buffers unmapped, batch upload completed...";
@@ -2272,7 +2287,7 @@ QRhiGraphicsPipeline *Renderer::buildStencilPipeline(const Batch *batch, bool fi
QRhiGraphicsPipeline::TargetBlend blend;
blend.colorWrite = {};
ps->setTargetBlends({ blend });
- ps->setSampleCount(renderTarget()->sampleCount());
+ ps->setSampleCount(renderTarget().rt->sampleCount());
ps->setStencilTest(true);
QRhiGraphicsPipeline::StencilOpState stencilOp;
if (firstStencilClipInBatch) {
@@ -2291,11 +2306,13 @@ QRhiGraphicsPipeline *Renderer::buildStencilPipeline(const Batch *batch, bool fi
ps->setTopology(m_stencilClipCommon.topology);
- ps->setShaderStages({ QRhiGraphicsShaderStage(QRhiGraphicsShaderStage::Vertex, m_stencilClipCommon.vs),
- QRhiGraphicsShaderStage(QRhiGraphicsShaderStage::Fragment, m_stencilClipCommon.fs) });
+ ps->setMultiViewCount(renderTarget().multiViewCount);
+
+ ps->setShaderStages({ QRhiShaderStage(QRhiShaderStage::Vertex, m_stencilClipCommon.vs),
+ QRhiShaderStage(QRhiShaderStage::Fragment, m_stencilClipCommon.fs) });
ps->setVertexInputLayout(m_stencilClipCommon.inputLayout);
ps->setShaderResourceBindings(batch->stencilClipState.srb); // use something, it just needs to be layout-compatible
- ps->setRenderPassDescriptor(renderPassDescriptor());
+ ps->setRenderPassDescriptor(renderTarget().rpDesc);
if (!ps->create()) {
qWarning("Failed to build stencil clip pipeline");
@@ -2333,13 +2350,13 @@ void Renderer::updateClipState(const QSGClipNode *clipList, Batch *batch)
const QSGClipNode *clip = clipList;
batch->stencilClipState.drawCalls.reset();
- int totalVSize = 0;
- int totalISize = 0;
- int totalUSize = 0;
- const int StencilClipUbufSize = 64;
+ quint32 totalVSize = 0;
+ quint32 totalISize = 0;
+ quint32 totalUSize = 0;
+ const quint32 StencilClipUbufSize = 64;
while (clip) {
- QMatrix4x4 m = m_current_projection_matrix_native_ndc;
+ QMatrix4x4 m = m_current_projection_matrix_native_ndc[0]; // never hit for 3D and so multiview
if (clip->matrix())
m *= *clip->matrix();
@@ -2391,11 +2408,11 @@ void Renderer::updateClipState(const QSGClipNode *clipList, Batch *batch)
const int vertexByteSize = g->sizeOfVertex() * g->vertexCount();
// the 4 byte alignment may not actually be needed here
- totalVSize = aligned(totalVSize, 4) + vertexByteSize;
+ totalVSize = aligned(totalVSize, 4u) + vertexByteSize;
if (g->indexCount()) {
const int indexByteSize = g->sizeOfIndex() * g->indexCount();
// so no need to worry about NonFourAlignedEffectiveIndexBufferOffset
- totalISize = aligned(totalISize, 4) + indexByteSize;
+ totalISize = aligned(totalISize, 4u) + indexByteSize;
}
// ubuf start offsets must be aligned (typically to 256 bytes)
totalUSize = aligned(totalUSize, m_ubufAlignment) + StencilClipUbufSize;
@@ -2473,9 +2490,9 @@ void Renderer::updateClipState(const QSGClipNode *clipList, Batch *batch)
}
}
- int vOffset = 0;
- int iOffset = 0;
- int uOffset = 0;
+ quint32 vOffset = 0;
+ quint32 iOffset = 0;
+ quint32 uOffset = 0;
for (const QSGClipNode *clip : stencilClipNodes) {
const QSGGeometry *g = clip->geometry();
const QSGGeometry::Attribute *a = g->attributes();
@@ -2496,13 +2513,13 @@ void Renderer::updateClipState(const QSGClipNode *clipList, Batch *batch)
}
#endif
- drawCall.vbufOffset = aligned(vOffset, 4);
+ drawCall.vbufOffset = aligned(vOffset, 4u);
const int vertexByteSize = g->sizeOfVertex() * g->vertexCount();
vOffset = drawCall.vbufOffset + vertexByteSize;
int indexByteSize = 0;
if (g->indexCount()) {
- drawCall.ibufOffset = aligned(iOffset, 4);
+ drawCall.ibufOffset = aligned(iOffset, 4u);
indexByteSize = g->sizeOfIndex() * g->indexCount();
iOffset = drawCall.ibufOffset + indexByteSize;
}
@@ -2510,7 +2527,7 @@ void Renderer::updateClipState(const QSGClipNode *clipList, Batch *batch)
drawCall.ubufOffset = aligned(uOffset, m_ubufAlignment);
uOffset = drawCall.ubufOffset + StencilClipUbufSize;
- QMatrix4x4 matrixYUpNDC = m_current_projection_matrix;
+ QMatrix4x4 matrixYUpNDC = m_current_projection_matrix[0];
if (clip->matrix())
matrixYUpNDC *= *clip->matrix();
@@ -2565,7 +2582,7 @@ void Renderer::enqueueStencilDraw(const Batch *batch)
if (!batch->stencilClipState.updateStencilBuffer)
return;
- QRhiCommandBuffer *cb = commandBuffer();
+ QRhiCommandBuffer *cb = renderTarget().cb;
const int count = batch->stencilClipState.drawCalls.size();
for (int i = 0; i < count; ++i) {
const StencilClipState::StencilDrawCall &drawCall(batch->stencilClipState.drawCalls.at(i));
@@ -2625,10 +2642,29 @@ static inline bool needsBlendConstant(QRhiGraphicsPipeline::BlendFactor f)
bool Renderer::ensurePipelineState(Element *e, const ShaderManager::Shader *sms, bool depthPostPass)
{
- // In unmerged batches the srbs in the elements are all compatible
- // layout-wise. Note the key's == and qHash implementations: the rp desc and
- // srb are tested for (layout) compatibility, not pointer equality.
- const GraphicsPipelineStateKey k { m_gstate, sms, renderPassDescriptor(), e->srb };
+ // Note the key's == and qHash implementations: the renderpass descriptor
+ // and srb are tested for compatibility, not pointer equality.
+ //
+ // We do not store the srb pointer itself because the ownership stays with
+ // the Element and that can go away more often that we would like it
+ // to. (think scrolling a list view, constantly dropping and creating new
+ // nodes) Rather, use an opaque blob of a few uints and store and compare
+ // that. This works because once the pipeline is built, we will always call
+ // setShaderResources with an explicitly specified srb which is fine even if
+ // e->srb we used here to bake the pipeline is already gone by that point.
+ //
+ // A typical QSGMaterial's serialized srb layout is 8 uints. (uniform buffer
+ // + texture, 4 fields each) Regardless, using an implicitly shared
+ // container is essential here. (won't detach so no more allocs and copies
+ // are done, unless the Element decides to rebake the srb with a different
+ // layout - but then the detach is exactly what we need)
+ //
+ // Same story for the renderpass descriptor: the object can go away but
+ // that's fine because that has no effect on an already built pipeline, and
+ // for comparison we only rely on the serialized blob in order decide if the
+ // render target is compatible with the pipeline.
+
+ const GraphicsPipelineStateKey k = GraphicsPipelineStateKey::create(m_gstate, sms, renderTarget().rpDesc, e->srb);
// Note: dynamic state (viewport rect, scissor rect, stencil ref, blend
// constant) is never a part of GraphicsState/QRhiGraphicsPipeline.
@@ -2645,14 +2681,17 @@ bool Renderer::ensurePipelineState(Element *e, const ShaderManager::Shader *sms,
// Build a new one. This is potentially expensive.
QRhiGraphicsPipeline *ps = m_rhi->newGraphicsPipeline();
- ps->setShaderStages(sms->programRhi.shaderStages.cbegin(), sms->programRhi.shaderStages.cend());
- ps->setVertexInputLayout(sms->programRhi.inputLayout);
+ ps->setShaderStages(sms->stages.cbegin(), sms->stages.cend());
+ ps->setVertexInputLayout(sms->inputLayout);
ps->setShaderResourceBindings(e->srb);
- ps->setRenderPassDescriptor(renderPassDescriptor());
+ ps->setRenderPassDescriptor(renderTarget().rpDesc);
QRhiGraphicsPipeline::Flags flags;
- if (needsBlendConstant(m_gstate.srcColor) || needsBlendConstant(m_gstate.dstColor))
+ if (needsBlendConstant(m_gstate.srcColor) || needsBlendConstant(m_gstate.dstColor)
+ || needsBlendConstant(m_gstate.srcAlpha) || needsBlendConstant(m_gstate.dstAlpha))
+ {
flags |= QRhiGraphicsPipeline::UsesBlendConstants;
+ }
if (m_gstate.usesScissor)
flags |= QRhiGraphicsPipeline::UsesScissor;
if (m_gstate.stencilTest)
@@ -2661,12 +2700,16 @@ bool Renderer::ensurePipelineState(Element *e, const ShaderManager::Shader *sms,
ps->setFlags(flags);
ps->setTopology(qsg_topology(m_gstate.drawMode));
ps->setCullMode(m_gstate.cullMode);
+ ps->setPolygonMode(m_gstate.polygonMode);
+ ps->setMultiViewCount(m_gstate.multiViewCount);
QRhiGraphicsPipeline::TargetBlend blend;
blend.colorWrite = m_gstate.colorWrite;
blend.enable = m_gstate.blending;
- blend.srcColor = blend.srcAlpha = m_gstate.srcColor;
- blend.dstColor = blend.dstAlpha = m_gstate.dstColor;
+ blend.srcColor = m_gstate.srcColor;
+ blend.dstColor = m_gstate.dstColor;
+ blend.srcAlpha = m_gstate.srcAlpha;
+ blend.dstAlpha = m_gstate.dstAlpha;
ps->setTargetBlends({ blend });
ps->setDepthTest(m_gstate.depthTest);
@@ -2800,13 +2843,25 @@ static void rendererToMaterialGraphicsState(QSGMaterialShader::GraphicsPipelineS
Q_ASSERT(int(QSGMaterialShader::GraphicsPipelineState::OneMinusSrc1Alpha) == int(QRhiGraphicsPipeline::OneMinusSrc1Alpha));
Q_ASSERT(int(QSGMaterialShader::GraphicsPipelineState::A) == int(QRhiGraphicsPipeline::A));
Q_ASSERT(int(QSGMaterialShader::GraphicsPipelineState::CullBack) == int(QRhiGraphicsPipeline::Back));
-
+ Q_ASSERT(int(QSGMaterialShader::GraphicsPipelineState::Line) == int(QRhiGraphicsPipeline::Line));
dst->srcColor = QSGMaterialShader::GraphicsPipelineState::BlendFactor(src->srcColor);
dst->dstColor = QSGMaterialShader::GraphicsPipelineState::BlendFactor(src->dstColor);
+ // For compatibility with any existing code, separateBlendFactors defaults
+ // to _false_ which means that materials that do not touch srcAlpha and
+ // dstAlpha will continue to use srcColor and dstColor as the alpha
+ // blending factors. New code that needs different values for color/alpha,
+ // can explicitly set separateBlendFactors to true and then set srcAlpha
+ // and dstAlpha as well.
+ dst->separateBlendFactors = false;
+
+ dst->srcAlpha = QSGMaterialShader::GraphicsPipelineState::BlendFactor(src->srcAlpha);
+ dst->dstAlpha = QSGMaterialShader::GraphicsPipelineState::BlendFactor(src->dstAlpha);
+
dst->colorWrite = QSGMaterialShader::GraphicsPipelineState::ColorMask(int(src->colorWrite));
dst->cullMode = QSGMaterialShader::GraphicsPipelineState::CullMode(src->cullMode);
+ dst->polygonMode = QSGMaterialShader::GraphicsPipelineState::PolygonMode(src->polygonMode);
}
static void materialToRendererGraphicsState(GraphicsState *dst,
@@ -2815,22 +2870,32 @@ static void materialToRendererGraphicsState(GraphicsState *dst,
dst->blending = src->blendEnable;
dst->srcColor = QRhiGraphicsPipeline::BlendFactor(src->srcColor);
dst->dstColor = QRhiGraphicsPipeline::BlendFactor(src->dstColor);
+ if (src->separateBlendFactors) {
+ dst->srcAlpha = QRhiGraphicsPipeline::BlendFactor(src->srcAlpha);
+ dst->dstAlpha = QRhiGraphicsPipeline::BlendFactor(src->dstAlpha);
+ } else {
+ dst->srcAlpha = dst->srcColor;
+ dst->dstAlpha = dst->dstColor;
+ }
dst->colorWrite = QRhiGraphicsPipeline::ColorMask(int(src->colorWrite));
dst->cullMode = QRhiGraphicsPipeline::CullMode(src->cullMode);
+ dst->polygonMode = QRhiGraphicsPipeline::PolygonMode(src->polygonMode);
}
void Renderer::updateMaterialDynamicData(ShaderManager::Shader *sms,
QSGMaterialShader::RenderState &renderState,
QSGMaterial *material,
- ShaderManager::ShaderResourceBindingList *bindings,
const Batch *batch,
+ Element *e,
int ubufOffset,
int ubufRegionSize)
{
m_current_resource_update_batch = m_resourceUpdates;
- QSGMaterialShader *shader = sms->programRhi.program;
+ QSGMaterialShader *shader = sms->materialShader;
QSGMaterialShaderPrivate *pd = QSGMaterialShaderPrivate::get(shader);
+ QVarLengthArray<QRhiShaderResourceBinding, 8> bindings;
+
if (pd->ubufBinding >= 0) {
m_current_uniform_data = &pd->masterUniformData;
const bool changed = shader->updateUniformData(renderState, material, m_currentMaterial);
@@ -2839,11 +2904,11 @@ void Renderer::updateMaterialDynamicData(ShaderManager::Shader *sms,
if (changed || !batch->ubufDataValid)
m_resourceUpdates->updateDynamicBuffer(batch->ubuf, ubufOffset, ubufRegionSize, pd->masterUniformData.constData());
- bindings->append(QRhiShaderResourceBinding::uniformBuffer(pd->ubufBinding,
- pd->ubufStages,
- batch->ubuf,
- ubufOffset,
- ubufRegionSize));
+ bindings.append(QRhiShaderResourceBinding::uniformBuffer(pd->ubufBinding,
+ pd->ubufStages,
+ batch->ubuf,
+ ubufOffset,
+ ubufRegionSize));
}
for (int binding = 0; binding < QSGMaterialShaderPrivate::MAX_SHADER_RESOURCE_BINDINGS; ++binding) {
@@ -2851,63 +2916,167 @@ void Renderer::updateMaterialDynamicData(ShaderManager::Shader *sms,
if (!stages)
continue;
- QSGTexture *prevTex = pd->textureBindingTable[binding];
- QSGTexture *t = prevTex;
+ QVarLengthArray<QSGTexture *, 4> prevTex = pd->textureBindingTable[binding];
+ QVarLengthArray<QSGTexture *, 4> nextTex = prevTex;
+
+ const int count = pd->combinedImageSamplerCount[binding];
+ nextTex.resize(count);
+
+ shader->updateSampledImage(renderState, binding, nextTex.data(), material,
+ m_currentMaterial);
- shader->updateSampledImage(renderState, binding, &t, material, m_currentMaterial);
- if (!t) {
+ if (nextTex.contains(nullptr)) {
qWarning("No QSGTexture provided from updateSampledImage(). This is wrong.");
continue;
}
- QSGTexturePrivate *td = QSGTexturePrivate::get(t);
+ bool hasDirtySamplerOptions = false;
+ bool isAnisotropic = false;
+ for (QSGTexture *t : nextTex) {
+ QSGTexturePrivate *td = QSGTexturePrivate::get(t);
+ hasDirtySamplerOptions |= td->hasDirtySamplerOptions();
+ isAnisotropic |= t->anisotropyLevel() != QSGTexture::AnisotropyNone;
+ td->resetDirtySamplerOptions();
+ }
+
// prevTex may be invalid at this point, avoid dereferencing it
- if (t != prevTex || td->hasDirtySamplerOptions()) {
+ if (nextTex != prevTex || hasDirtySamplerOptions) {
+
// The QSGTexture, and so the sampler parameters, may have changed.
// The rhiTexture is not relevant here.
- td->resetDirtySamplerOptions();
- pd->textureBindingTable[binding] = t; // does not own
- pd->samplerBindingTable[binding] = nullptr;
- if (t->anisotropyLevel() != QSGTexture::AnisotropyNone) // ###
+ pd->textureBindingTable[binding] = nextTex; // does not own
+ pd->samplerBindingTable[binding].clear();
+
+ if (isAnisotropic) // ###
qWarning("QSGTexture anisotropy levels are not currently supported");
- const QSGSamplerDescription samplerDesc = QSGSamplerDescription::fromTexture(t);
- QRhiSampler *sampler = nullptr;
- auto it = m_samplers.constFind(samplerDesc);
- if (it != m_samplers.constEnd()) {
- sampler = *it;
- Q_ASSERT(sampler);
- } else {
- sampler = newSampler(m_rhi, samplerDesc);
- if (!sampler->create()) {
- qWarning("Failed to build sampler");
- delete sampler;
- continue;
+ QVarLengthArray<QRhiSampler *, 4> samplers;
+
+ for (QSGTexture *t : nextTex) {
+ const QSGSamplerDescription samplerDesc = QSGSamplerDescription::fromTexture(t);
+
+ QRhiSampler *sampler = m_samplers[samplerDesc];
+
+ if (!sampler) {
+ sampler = newSampler(m_rhi, samplerDesc);
+ if (!sampler->create()) {
+ qWarning("Failed to build sampler");
+ delete sampler;
+ continue;
+ }
+ m_samplers[samplerDesc] = sampler;
}
- m_samplers.insert(samplerDesc, sampler);
+ samplers.append(sampler);
}
- pd->samplerBindingTable[binding] = sampler; // does not own
+
+ pd->samplerBindingTable[binding] = samplers; // does not own
}
- if (pd->textureBindingTable[binding] && pd->samplerBindingTable[binding]) {
- QRhiTexture *texture = pd->textureBindingTable[binding]->rhiTexture();
- // texture may be null if the update above failed for any reason,
- // or if the QSGTexture chose to return null intentionally. This is
- // valid and we still need to provide something to the shader.
- if (!texture)
- texture = dummyTexture();
- QRhiSampler *sampler = pd->samplerBindingTable[binding];
- bindings->append(QRhiShaderResourceBinding::sampledTexture(binding,
- stages,
- texture,
- sampler));
+ if (pd->textureBindingTable[binding].size() == pd->samplerBindingTable[binding].size()) {
+
+ QVarLengthArray<QRhiShaderResourceBinding::TextureAndSampler, 4> textureSamplers;
+
+ for (int i = 0; i < pd->textureBindingTable[binding].size(); ++i) {
+
+ QRhiTexture *texture = pd->textureBindingTable[binding].at(i)->rhiTexture();
+
+ // texture may be null if the update above failed for any reason,
+ // or if the QSGTexture chose to return null intentionally. This is
+ // valid and we still need to provide something to the shader.
+ if (!texture)
+ texture = dummyTexture();
+
+ QRhiSampler *sampler = pd->samplerBindingTable[binding].at(i);
+
+ textureSamplers.append(
+ QRhiShaderResourceBinding::TextureAndSampler { texture, sampler });
+ }
+
+ if (!textureSamplers.isEmpty())
+ bindings.append(QRhiShaderResourceBinding::sampledTextures(
+ binding, stages, count, textureSamplers.constData()));
}
}
#ifndef QT_NO_DEBUG
- if (bindings->isEmpty())
+ if (bindings.isEmpty())
qWarning("No shader resources for material %p, this is odd.", material);
#endif
+
+ enum class SrbAction {
+ Unknown,
+ DoNothing,
+ UpdateResources,
+ Rebake
+ } srbAction = SrbAction::Unknown;
+
+ // First, if the Element has no srb created at all, then try to find an existing,
+ // currently unused srb that is layout-compatible with our binding list.
+ if (!e->srb) {
+ // reuse a QVector as our work area, thus possibly reusing the underlying allocation too
+ QVector<quint32> &layoutDesc(m_shaderManager->srbLayoutDescSerializeWorkspace);
+ layoutDesc.clear();
+ QRhiShaderResourceBinding::serializeLayoutDescription(bindings.cbegin(), bindings.cend(), std::back_inserter(layoutDesc));
+ e->srb = m_shaderManager->srbPool.take(layoutDesc);
+ if (e->srb) {
+ // Here we know layout compatibility is satisfied, but do not spend time on full
+ // comparison. The chance of getting an srb that refers to the same resources
+ // (buffer, textures) is low in practice. So reuse, but write new resources.
+ srbAction = SrbAction::UpdateResources;
+ }
+ }
+
+ // If the Element had an existing srb, investigate:
+ // - It may be used as-is (when nothing changed in the scene regarding this node compared to the previous frame).
+ // - Otherwise it may be able to go with a lightweight update (replace resources, binding list layout is the same).
+ // - If all else fails rebake the full thing, meaning we reuse the memory allocation but will recreate everything underneath.
+ if (srbAction == SrbAction::Unknown && e->srb) {
+ if (std::equal(e->srb->cbeginBindings(), e->srb->cendBindings(), bindings.cbegin(), bindings.cend())) {
+ srbAction = SrbAction::DoNothing;
+ } else if (std::equal(e->srb->cbeginBindings(), e->srb->cendBindings(), bindings.cbegin(), bindings.cend(),
+ [](const auto &a, const auto &b) { return a.isLayoutCompatible(b); }))
+ {
+ srbAction = SrbAction::UpdateResources;
+ } else {
+ srbAction = SrbAction::Rebake;
+ }
+ }
+
+ // If the Element had no srb associated at all and could not find a layout-compatible
+ // one from the pool, then create a whole new object.
+ if (!e->srb) {
+ e->srb = m_rhi->newShaderResourceBindings();
+ srbAction = SrbAction::Rebake;
+ }
+
+ Q_ASSERT(srbAction != SrbAction::Unknown && e->srb);
+
+ switch (srbAction) {
+ case SrbAction::DoNothing:
+ break;
+ case SrbAction::UpdateResources:
+ {
+ e->srb->setBindings(bindings.cbegin(), bindings.cend());
+ QRhiShaderResourceBindings::UpdateFlags flags;
+ // Due to the way the binding list is built up above, if we have a uniform buffer
+ // at binding point 0 (or none at all) then the sampledTexture bindings are added
+ // with increasing binding points afterwards, so the list is already sorted based
+ // on the binding points, thus we can save some time by telling the QRhi backend
+ // not to sort again.
+ if (pd->ubufBinding <= 0 || bindings.size() <= 1)
+ flags |= QRhiShaderResourceBindings::BindingsAreSorted;
+
+ e->srb->updateResources(flags);
+ }
+ break;
+ case SrbAction::Rebake:
+ e->srb->setBindings(bindings.cbegin(), bindings.cend());
+ if (!e->srb->create())
+ qWarning("Failed to build srb");
+ break;
+ default:
+ Q_ASSERT_X(false, "updateMaterialDynamicData", "No srb action set, this cannot happen");
+ }
}
void Renderer::updateMaterialStaticData(ShaderManager::Shader *sms,
@@ -2916,7 +3085,7 @@ void Renderer::updateMaterialStaticData(ShaderManager::Shader *sms,
Batch *batch,
bool *gstateChanged)
{
- QSGMaterialShader *shader = sms->programRhi.program;
+ QSGMaterialShader *shader = sms->materialShader;
*gstateChanged = false;
if (shader->flags().testFlag(QSGMaterialShader::UpdatesGraphicsPipelineState)) {
// generate the public mini-state from m_gstate, invoke the material,
@@ -2928,8 +3097,11 @@ void Renderer::updateMaterialStaticData(ShaderManager::Shader *sms,
if (changed) {
m_gstateStack.push(m_gstate);
materialToRendererGraphicsState(&m_gstate, &shaderPs);
- if (needsBlendConstant(m_gstate.srcColor) || needsBlendConstant(m_gstate.dstColor))
+ if (needsBlendConstant(m_gstate.srcColor) || needsBlendConstant(m_gstate.dstColor)
+ || needsBlendConstant(m_gstate.srcAlpha) || needsBlendConstant(m_gstate.dstAlpha))
+ {
batch->blendConstant = shaderPs.blendConstant;
+ }
*gstateChanged = true;
}
}
@@ -2973,22 +3145,30 @@ bool Renderer::prepareRenderMergedBatch(Batch *batch, PreparedRenderBatch *rende
else
m_current_model_view_matrix.setToIdentity();
m_current_determinant = m_current_model_view_matrix.determinant();
- m_current_projection_matrix = projectionMatrix();
- m_current_projection_matrix_native_ndc = projectionMatrixWithNativeNDC();
+
+ const int viewCount = projectionMatrixCount();
+ m_current_projection_matrix.resize(viewCount);
+ for (int viewIndex = 0; viewIndex < viewCount; ++viewIndex)
+ m_current_projection_matrix[viewIndex] = projectionMatrix(viewIndex);
+
+ m_current_projection_matrix_native_ndc.resize(projectionMatrixWithNativeNDCCount());
+ for (int viewIndex = 0; viewIndex < projectionMatrixWithNativeNDCCount(); ++viewIndex)
+ m_current_projection_matrix_native_ndc[viewIndex] = projectionMatrixWithNativeNDC(viewIndex);
QSGMaterial *material = gn->activeMaterial();
if (m_renderMode != QSGRendererInterface::RenderMode3D)
updateClipState(gn->clipList(), batch);
const QSGGeometry *g = gn->geometry();
- ShaderManager::Shader *sms = useDepthBuffer() ? m_shaderManager->prepareMaterial(material, g, m_renderMode)
- : m_shaderManager->prepareMaterialNoRewrite(material, g, m_renderMode);
+ const int multiViewCount = renderTarget().multiViewCount;
+ ShaderManager::Shader *sms = useDepthBuffer() ? m_shaderManager->prepareMaterial(material, g, m_renderMode, multiViewCount)
+ : m_shaderManager->prepareMaterialNoRewrite(material, g, m_renderMode, multiViewCount);
if (!sms)
return false;
- Q_ASSERT(sms->programRhi.program);
+ Q_ASSERT(sms->materialShader);
if (m_currentShader != sms)
- setActiveRhiShader(sms->programRhi.program, sms);
+ setActiveRhiShader(sms->materialShader, sms);
m_current_opacity = gn->inheritedOpacity();
if (!qFuzzyCompare(sms->lastOpacity, float(m_current_opacity))) {
@@ -2996,8 +3176,8 @@ bool Renderer::prepareRenderMergedBatch(Batch *batch, PreparedRenderBatch *rende
sms->lastOpacity = m_current_opacity;
}
- QSGMaterialShaderPrivate *pd = QSGMaterialShaderPrivate::get(sms->programRhi.program);
- const int ubufSize = pd->masterUniformData.size();
+ QSGMaterialShaderPrivate *pd = QSGMaterialShaderPrivate::get(sms->materialShader);
+ const quint32 ubufSize = quint32(pd->masterUniformData.size());
if (pd->ubufBinding >= 0) {
bool ubufRebuild = false;
if (!batch->ubuf) {
@@ -3012,7 +3192,7 @@ bool Renderer::prepareRenderMergedBatch(Batch *batch, PreparedRenderBatch *rende
if (ubufRebuild) {
batch->ubufDataValid = false;
if (!batch->ubuf->create()) {
- qWarning("Failed to build uniform buffer of size %d bytes", ubufSize);
+ qWarning("Failed to build uniform buffer of size %u bytes", ubufSize);
delete batch->ubuf;
batch->ubuf = nullptr;
return false;
@@ -3025,8 +3205,7 @@ bool Renderer::prepareRenderMergedBatch(Batch *batch, PreparedRenderBatch *rende
bool pendingGStatePop = false;
updateMaterialStaticData(sms, renderState, material, batch, &pendingGStatePop);
- ShaderManager::ShaderResourceBindingList bindings;
- updateMaterialDynamicData(sms, renderState, material, &bindings, batch, 0, ubufSize);
+ updateMaterialDynamicData(sms, renderState, material, batch, e, 0, ubufSize);
#ifndef QT_NO_DEBUG
if (qsg_test_and_clear_material_failure()) {
@@ -3041,8 +3220,6 @@ bool Renderer::prepareRenderMergedBatch(Batch *batch, PreparedRenderBatch *rende
}
#endif
- e->srb = m_shaderManager->srb(bindings);
-
m_gstate.drawMode = QSGGeometry::DrawingMode(g->drawingMode());
m_gstate.lineWidth = g->lineWidth();
@@ -3099,6 +3276,9 @@ void Renderer::checkLineWidth(QSGGeometry *g)
void Renderer::renderMergedBatch(PreparedRenderBatch *renderBatch, bool depthPostPass)
{
const Batch *batch = renderBatch->batch;
+ if (!batch->vbo.buf || !batch->ibo.buf)
+ return;
+
Element *e = batch->first;
QSGGeometryNode *gn = e->node;
QSGGeometry *g = gn->geometry();
@@ -3107,7 +3287,7 @@ void Renderer::renderMergedBatch(PreparedRenderBatch *renderBatch, bool depthPos
if (batch->clipState.type & ClipState::StencilClip)
enqueueStencilDraw(batch);
- QRhiCommandBuffer *cb = commandBuffer();
+ QRhiCommandBuffer *cb = renderTarget().cb;
setGraphicsPipeline(cb, batch, e, depthPostPass);
for (int i = 0, ie = batch->drawSets.size(); i != ie; ++i) {
@@ -3146,8 +3326,14 @@ bool Renderer::prepareRenderUnmergedBatch(Batch *batch, PreparedRenderBatch *ren
batch->uploadedThisFrame = false;
}
- m_current_projection_matrix = projectionMatrix();
- m_current_projection_matrix_native_ndc = projectionMatrixWithNativeNDC();
+ const int viewCount = projectionMatrixCount();
+ m_current_projection_matrix.resize(viewCount);
+ for (int viewIndex = 0; viewIndex < viewCount; ++viewIndex)
+ m_current_projection_matrix[viewIndex] = projectionMatrix(viewIndex);
+
+ m_current_projection_matrix_native_ndc.resize(projectionMatrixWithNativeNDCCount());
+ for (int viewIndex = 0; viewIndex < projectionMatrixWithNativeNDCCount(); ++viewIndex)
+ m_current_projection_matrix_native_ndc[viewIndex] = projectionMatrixWithNativeNDC(viewIndex);
QSGGeometryNode *gn = e->node;
if (m_renderMode != QSGRendererInterface::RenderMode3D)
@@ -3160,13 +3346,13 @@ bool Renderer::prepareRenderUnmergedBatch(Batch *batch, PreparedRenderBatch *ren
// unmerged batch since the material (and so the shaders) is the same.
QSGGeometry *g = gn->geometry();
QSGMaterial *material = gn->activeMaterial();
- ShaderManager::Shader *sms = m_shaderManager->prepareMaterialNoRewrite(material, g);
+ ShaderManager::Shader *sms = m_shaderManager->prepareMaterialNoRewrite(material, g, m_renderMode, renderTarget().multiViewCount);
if (!sms)
return false;
- Q_ASSERT(sms->programRhi.program);
+ Q_ASSERT(sms->materialShader);
if (m_currentShader != sms)
- setActiveRhiShader(sms->programRhi.program, sms);
+ setActiveRhiShader(sms->materialShader, sms);
m_current_opacity = gn->inheritedOpacity();
if (sms->lastOpacity != m_current_opacity) {
@@ -3176,10 +3362,10 @@ bool Renderer::prepareRenderUnmergedBatch(Batch *batch, PreparedRenderBatch *ren
QMatrix4x4 rootMatrix = batch->root ? qsg_matrixForRoot(batch->root) : QMatrix4x4();
- QSGMaterialShaderPrivate *pd = QSGMaterialShaderPrivate::get(sms->programRhi.program);
- const int ubufSize = pd->masterUniformData.size();
+ QSGMaterialShaderPrivate *pd = QSGMaterialShaderPrivate::get(sms->materialShader);
+ const quint32 ubufSize = quint32(pd->masterUniformData.size());
if (pd->ubufBinding >= 0) {
- int totalUBufSize = 0;
+ quint32 totalUBufSize = 0;
while (e) {
totalUBufSize += aligned(ubufSize, m_ubufAlignment);
e = e->nextInBatch;
@@ -3197,7 +3383,7 @@ bool Renderer::prepareRenderUnmergedBatch(Batch *batch, PreparedRenderBatch *ren
if (ubufRebuild) {
batch->ubufDataValid = false;
if (!batch->ubuf->create()) {
- qWarning("Failed to build uniform buffer of size %d bytes", totalUBufSize);
+ qWarning("Failed to build uniform buffer of size %u bytes", totalUBufSize);
delete batch->ubuf;
batch->ubuf = nullptr;
return false;
@@ -3220,17 +3406,23 @@ bool Renderer::prepareRenderUnmergedBatch(Batch *batch, PreparedRenderBatch *ren
m_current_model_view_matrix = rootMatrix * *gn->matrix();
m_current_determinant = m_current_model_view_matrix.determinant();
- m_current_projection_matrix = projectionMatrix();
- m_current_projection_matrix_native_ndc = projectionMatrixWithNativeNDC();
+ const int viewCount = projectionMatrixCount();
+ m_current_projection_matrix.resize(viewCount);
+ for (int viewIndex = 0; viewIndex < viewCount; ++viewIndex)
+ m_current_projection_matrix[viewIndex] = projectionMatrix(viewIndex);
+
+ m_current_projection_matrix_native_ndc.resize(projectionMatrixWithNativeNDCCount());
+ for (int viewIndex = 0; viewIndex < projectionMatrixWithNativeNDCCount(); ++viewIndex)
+ m_current_projection_matrix_native_ndc[viewIndex] = projectionMatrixWithNativeNDC(viewIndex);
+
if (useDepthBuffer()) {
- m_current_projection_matrix(2, 2) = m_zRange;
- m_current_projection_matrix(2, 3) = 1.0f - e->order * m_zRange;
+ // this cannot be multiview
+ m_current_projection_matrix[0](2, 2) = m_zRange;
+ m_current_projection_matrix[0](2, 3) = calculateElementZOrder(e, m_zRange);
}
QSGMaterialShader::RenderState renderState = state(QSGMaterialShader::RenderState::DirtyStates(int(dirty)));
- ShaderManager::ShaderResourceBindingList bindings;
- updateMaterialDynamicData(sms, renderState,
- material, &bindings, batch, ubufOffset, ubufSize);
+ updateMaterialDynamicData(sms, renderState, material, batch, e, ubufOffset, ubufSize);
#ifndef QT_NO_DEBUG
if (qsg_test_and_clear_material_failure()) {
@@ -3242,8 +3434,6 @@ bool Renderer::prepareRenderUnmergedBatch(Batch *batch, PreparedRenderBatch *ren
}
#endif
- e->srb = m_shaderManager->srb(bindings);
-
ubufOffset += aligned(ubufSize, m_ubufAlignment);
const QSGGeometry::DrawingMode prevDrawMode = m_gstate.drawMode;
@@ -3298,19 +3488,20 @@ bool Renderer::prepareRenderUnmergedBatch(Batch *batch, PreparedRenderBatch *ren
void Renderer::renderUnmergedBatch(PreparedRenderBatch *renderBatch, bool depthPostPass)
{
const Batch *batch = renderBatch->batch;
+ if (!batch->vbo.buf)
+ return;
+
Element *e = batch->first;
- QSGGeometryNode *gn = e->node;
if (batch->clipState.type & ClipState::StencilClip)
enqueueStencilDraw(batch);
- int vOffset = 0;
- int iOffset = 0;
- QRhiCommandBuffer *cb = commandBuffer();
+ quint32 vOffset = 0;
+ quint32 iOffset = 0;
+ QRhiCommandBuffer *cb = renderTarget().cb;
while (e) {
- gn = e->node;
- QSGGeometry *g = gn->geometry();
+ QSGGeometry *g = e->node->geometry();
checkLineWidth(g);
const int effectiveIndexSize = m_uint32IndexForRhi ? sizeof(quint32) : g->sizeOfIndex();
@@ -3318,11 +3509,13 @@ void Renderer::renderUnmergedBatch(PreparedRenderBatch *renderBatch, bool depthP
const QRhiCommandBuffer::VertexInput vbufBinding(batch->vbo.buf, vOffset);
if (g->indexCount()) {
- cb->setVertexInput(VERTEX_BUFFER_BINDING, 1, &vbufBinding,
- batch->ibo.buf, iOffset,
- effectiveIndexSize == sizeof(quint32) ? QRhiCommandBuffer::IndexUInt32
- : QRhiCommandBuffer::IndexUInt16);
- cb->drawIndexed(g->indexCount());
+ if (batch->ibo.buf) {
+ cb->setVertexInput(VERTEX_BUFFER_BINDING, 1, &vbufBinding,
+ batch->ibo.buf, iOffset,
+ effectiveIndexSize == sizeof(quint32) ? QRhiCommandBuffer::IndexUInt32
+ : QRhiCommandBuffer::IndexUInt16);
+ cb->drawIndexed(g->indexCount());
+ }
} else {
cb->setVertexInput(VERTEX_BUFFER_BINDING, 1, &vbufBinding);
cb->draw(g->vertexCount());
@@ -3368,6 +3561,26 @@ void Renderer::setGraphicsPipeline(QRhiCommandBuffer *cb, const Batch *batch, El
cb->setShaderResources(e->srb);
}
+void Renderer::releaseElement(Element *e, bool inDestructor)
+{
+ if (e->isRenderNode) {
+ delete static_cast<RenderNodeElement *>(e);
+ } else {
+ if (e->srb) {
+ if (!inDestructor) {
+ if (m_shaderManager->srbPool.size() < m_srbPoolThreshold)
+ m_shaderManager->srbPool.insert(e->srb->serializedLayoutDescription(), e->srb);
+ else
+ delete e->srb;
+ } else {
+ delete e->srb;
+ }
+ e->srb = nullptr;
+ }
+ m_elementAllocator.release(e);
+ }
+}
+
void Renderer::deleteRemovedElements()
{
if (!m_elementsToDelete.size())
@@ -3384,13 +3597,9 @@ void Renderer::deleteRemovedElements()
*e = nullptr;
}
- for (int i=0; i<m_elementsToDelete.size(); ++i) {
- Element *e = m_elementsToDelete.at(i);
- if (e->isRenderNode)
- delete static_cast<RenderNodeElement *>(e);
- else
- m_elementAllocator.release(e);
- }
+ for (int i=0; i<m_elementsToDelete.size(); ++i)
+ releaseElement(m_elementsToDelete.at(i));
+
m_elementsToDelete.reset();
}
@@ -3398,7 +3607,7 @@ void Renderer::render()
{
// Gracefully handle the lack of a render target - some autotests may rely
// on this in odd cases.
- if (!renderTarget())
+ if (!renderTarget().rt)
return;
prepareRenderPass(&m_mainRenderPassContext);
@@ -3543,14 +3752,14 @@ void Renderer::prepareRenderPass(RenderPassContext *ctx)
if (Q_UNLIKELY(debug_render())) ctx->timeSorting = ctx->timer.restart();
- int largestVBO = 0;
- int largestIBO = 0;
+ // Set size to 0, nothing is deallocated, they will "grow" again
+ // as part of uploadBatch.
+ m_vertexUploadPool.reset();
+ m_indexUploadPool.reset();
if (Q_UNLIKELY(debug_upload())) qDebug("Uploading Opaque Batches:");
for (int i=0; i<m_opaqueBatches.size(); ++i) {
Batch *b = m_opaqueBatches.at(i);
- largestVBO = qMax(b->vbo.size, largestVBO);
- largestIBO = qMax(b->ibo.size, largestIBO);
uploadBatch(b);
}
if (Q_UNLIKELY(debug_render())) ctx->timeUploadOpaque = ctx->timer.restart();
@@ -3559,16 +3768,9 @@ void Renderer::prepareRenderPass(RenderPassContext *ctx)
for (int i=0; i<m_alphaBatches.size(); ++i) {
Batch *b = m_alphaBatches.at(i);
uploadBatch(b);
- largestVBO = qMax(b->vbo.size, largestVBO);
- largestIBO = qMax(b->ibo.size, largestIBO);
}
if (Q_UNLIKELY(debug_render())) ctx->timeUploadAlpha = ctx->timer.restart();
- if (largestVBO * 2 < m_vertexUploadPool.size())
- m_vertexUploadPool.resize(largestVBO * 2);
- if (m_context->separateIndexBuffer() && largestIBO * 2 < m_indexUploadPool.size())
- m_indexUploadPool.resize(largestIBO * 2);
-
if (Q_UNLIKELY(debug_render())) {
qDebug().nospace() << "Rendering:" << Qt::endl
<< " -> Opaque: " << qsg_countNodesInBatches(m_opaqueBatches) << " nodes in " << m_opaqueBatches.size() << " batches..." << Qt::endl
@@ -3586,7 +3788,9 @@ void Renderer::prepareRenderPass(RenderPassContext *ctx)
bool renderOpaque = !debug_noopaque();
bool renderAlpha = !debug_noalpha();
- m_pstate.viewport = QRhiViewport(viewport.x(), deviceRect().bottom() - viewport.bottom(), viewport.width(), viewport.height());
+ m_pstate.viewport =
+ QRhiViewport(viewport.x(), deviceRect().bottom() - viewport.bottom(), viewport.width(),
+ viewport.height(), VIEWPORT_MIN_DEPTH, VIEWPORT_MAX_DEPTH);
m_pstate.clearColor = clearColor();
m_pstate.dsClear = QRhiDepthStencilClearValue(1.0f, 0);
m_pstate.viewportSet = false;
@@ -3598,6 +3802,7 @@ void Renderer::prepareRenderPass(RenderPassContext *ctx)
m_gstate.blending = false;
m_gstate.cullMode = QRhiGraphicsPipeline::None;
+ m_gstate.polygonMode = QRhiGraphicsPipeline::Fill;
m_gstate.colorWrite = QRhiGraphicsPipeline::R
| QRhiGraphicsPipeline::G
| QRhiGraphicsPipeline::B
@@ -3605,7 +3810,8 @@ void Renderer::prepareRenderPass(RenderPassContext *ctx)
m_gstate.usesScissor = false;
m_gstate.stencilTest = false;
- m_gstate.sampleCount = renderTarget()->sampleCount();
+ m_gstate.sampleCount = renderTarget().rt->sampleCount();
+ m_gstate.multiViewCount = renderTarget().multiViewCount;
ctx->opaqueRenderBatches.clear();
if (Q_LIKELY(renderOpaque)) {
@@ -3664,20 +3870,21 @@ void Renderer::prepareRenderPass(RenderPassContext *ctx)
if (m_visualizer->mode() != Visualizer::VisualizeNothing)
m_visualizer->prepareVisualize();
- commandBuffer()->resourceUpdate(m_resourceUpdates);
+ renderTarget().cb->resourceUpdate(m_resourceUpdates);
m_resourceUpdates = nullptr;
}
void Renderer::beginRenderPass(RenderPassContext *)
{
- commandBuffer()->beginPass(renderTarget(), m_pstate.clearColor, m_pstate.dsClear, nullptr,
- // we cannot tell if the application will have
- // native rendering thrown in to this pass
- // (QQuickWindow::beginExternalCommands()), so
- // we have no choice but to set the flag always
- // (thus triggering using secondary command
- // buffers with Vulkan)
- QRhiCommandBuffer::ExternalContent);
+ const QSGRenderTarget &rt(renderTarget());
+ rt.cb->beginPass(rt.rt, m_pstate.clearColor, m_pstate.dsClear, nullptr,
+ // we cannot tell if the application will have
+ // native rendering thrown in to this pass
+ // (QQuickWindow::beginExternalCommands()), so
+ // we have no choice but to set the flag always
+ // (thus triggering using secondary command
+ // buffers with Vulkan)
+ QRhiCommandBuffer::ExternalContent);
if (m_renderPassRecordingCallbacks.start)
m_renderPassRecordingCallbacks.start(m_renderPassRecordingCallbacks.userData);
@@ -3698,10 +3905,12 @@ void Renderer::recordRenderPass(RenderPassContext *ctx)
ctx->valid = false;
- QRhiCommandBuffer *cb = commandBuffer();
+ QRhiCommandBuffer *cb = renderTarget().cb;
cb->debugMarkBegin(QByteArrayLiteral("Qt Quick scene render"));
- for (int i = 0, ie = ctx->opaqueRenderBatches.count(); i != ie; ++i) {
+ for (int i = 0, ie = ctx->opaqueRenderBatches.size(); i != ie; ++i) {
+ if (i == 0)
+ cb->debugMarkMsg(QByteArrayLiteral("Qt Quick opaque batches"));
PreparedRenderBatch *renderBatch = &ctx->opaqueRenderBatches[i];
if (renderBatch->batch->merged)
renderMergedBatch(renderBatch);
@@ -3709,7 +3918,13 @@ void Renderer::recordRenderPass(RenderPassContext *ctx)
renderUnmergedBatch(renderBatch);
}
- for (int i = 0, ie = ctx->alphaRenderBatches.count(); i != ie; ++i) {
+ for (int i = 0, ie = ctx->alphaRenderBatches.size(); i != ie; ++i) {
+ if (i == 0) {
+ if (m_renderMode == QSGRendererInterface::RenderMode3D)
+ cb->debugMarkMsg(QByteArrayLiteral("Qt Quick 2D-in-3D batches"));
+ else
+ cb->debugMarkMsg(QByteArrayLiteral("Qt Quick alpha batches"));
+ }
PreparedRenderBatch *renderBatch = &ctx->alphaRenderBatches[i];
if (renderBatch->batch->merged)
renderMergedBatch(renderBatch);
@@ -3720,8 +3935,15 @@ void Renderer::recordRenderPass(RenderPassContext *ctx)
}
if (m_renderMode == QSGRendererInterface::RenderMode3D) {
- // depth post-pass
- for (int i = 0, ie = ctx->alphaRenderBatches.count(); i != ie; ++i) {
+ // Depth post-pass to fill up the depth buffer in a way that it
+ // corresponds to what got rendered to the color buffer in the previous
+ // (alpha) pass. The previous pass cannot enable depth write due to Z
+ // fighting. Rather, do it separately in a dedicated color-write-off,
+ // depth-write-on pass. This enables the 3D content drawn afterwards to
+ // depth test against the 2D items' rendering.
+ for (int i = 0, ie = ctx->alphaRenderBatches.size(); i != ie; ++i) {
+ if (i == 0)
+ cb->debugMarkMsg(QByteArrayLiteral("Qt Quick 2D-in-3D depth post-pass"));
PreparedRenderBatch *renderBatch = &ctx->alphaRenderBatches[i];
if (renderBatch->batch->merged)
renderMergedBatch(renderBatch, true);
@@ -3753,7 +3975,7 @@ void Renderer::endRenderPass(RenderPassContext *)
if (m_visualizer->mode() != Visualizer::VisualizeNothing)
m_visualizer->visualize();
- commandBuffer()->endPass();
+ renderTarget().cb->endPass();
}
struct RenderNodeState : public QSGRenderNode::RenderState
@@ -3810,7 +4032,8 @@ bool Renderer::prepareRhiRenderNode(Batch *batch, PreparedRenderBatch *renderBat
}
xform = xform->parent();
}
- rd->m_matrix = &matrix;
+ rd->m_localMatrix = matrix;
+ rd->m_matrix = &rd->m_localMatrix;
QSGNode *opacity = e->renderNode->parent();
rd->m_opacity = 1.0;
@@ -3822,6 +4045,19 @@ bool Renderer::prepareRhiRenderNode(Batch *batch, PreparedRenderBatch *renderBat
opacity = opacity->parent();
}
+ rd->m_rt = renderTarget();
+
+ const int viewCount = projectionMatrixCount();
+ rd->m_projectionMatrix.resize(viewCount);
+ for (int viewIndex = 0; viewIndex < viewCount; ++viewIndex)
+ rd->m_projectionMatrix[viewIndex] = projectionMatrix(viewIndex);
+
+ if (useDepthBuffer()) {
+ // this cannot be multiview
+ rd->m_projectionMatrix[0](2, 2) = m_zRange;
+ rd->m_projectionMatrix[0](2, 3) = calculateElementZOrder(e, m_zRange);
+ }
+
e->renderNode->prepare();
renderBatch->batch = batch;
@@ -3838,14 +4074,10 @@ void Renderer::renderRhiRenderNode(const Batch *batch)
RenderNodeElement *e = static_cast<RenderNodeElement *>(batch->first);
QSGRenderNodePrivate *rd = QSGRenderNodePrivate::get(e->renderNode);
- QMatrix4x4 pm = projectionMatrix();
- if (useDepthBuffer()) {
- pm(2, 2) = m_zRange;
- pm(2, 3) = 1.0f - e->order * m_zRange;
- }
-
RenderNodeState state;
- state.m_projectionMatrix = &pm;
+ // Expose only the first matrix through the state object, the rest are
+ // queriable through the QSGRenderNode getters anyway.
+ state.m_projectionMatrix = &rd->m_projectionMatrix[0];
const std::array<int, 4> scissor = batch->clipState.scissor.scissor();
state.m_scissorRect = QRect(scissor[0], scissor[1], scissor[2], scissor[3]);
state.m_stencilValue = batch->clipState.stencilRef;
@@ -3854,7 +4086,7 @@ void Renderer::renderRhiRenderNode(const Batch *batch)
const QSGRenderNode::StateFlags changes = e->renderNode->changedStates();
- QRhiCommandBuffer *cb = commandBuffer();
+ QRhiCommandBuffer *cb = renderTarget().cb;
const bool needsExternal = !e->renderNode->flags().testFlag(QSGRenderNode::NoExternalRendering);
if (needsExternal)
cb->beginExternal();
@@ -3899,22 +4131,6 @@ bool Renderer::hasVisualizationModeWithContinuousUpdate() const
return m_visualizer->mode() == Visualizer::VisualizeOverdraw;
}
-void Renderer::invalidatePipelineCacheDependency(QRhiRenderPassDescriptor *rpDesc)
-{
- if (!rpDesc)
- return;
-
- for (auto it = m_shaderManager->pipelineCache.begin(); it != m_shaderManager->pipelineCache.end(); ) {
- if (it.key().compatibleRenderPassDescriptor == rpDesc) {
- QRhiGraphicsPipeline *ps = it.value();
- it = m_shaderManager->pipelineCache.erase(it);
- ps->deleteLater(); // QRhi takes care of it in endFrame()
- } else {
- ++it;
- }
- }
-}
-
bool operator==(const GraphicsState &a, const GraphicsState &b) noexcept
{
return a.depthTest == b.depthTest
@@ -3923,13 +4139,17 @@ bool operator==(const GraphicsState &a, const GraphicsState &b) noexcept
&& a.blending == b.blending
&& a.srcColor == b.srcColor
&& a.dstColor == b.dstColor
+ && a.srcAlpha == b.srcAlpha
+ && a.dstAlpha == b.dstAlpha
&& a.colorWrite == b.colorWrite
&& a.cullMode == b.cullMode
&& a.usesScissor == b.usesScissor
&& a.stencilTest == b.stencilTest
&& a.sampleCount == b.sampleCount
&& a.drawMode == b.drawMode
- && a.lineWidth == b.lineWidth;
+ && a.lineWidth == b.lineWidth
+ && a.polygonMode == b.polygonMode
+ && a.multiViewCount == b.multiViewCount;
}
bool operator!=(const GraphicsState &a, const GraphicsState &b) noexcept
@@ -3949,15 +4169,16 @@ size_t qHash(const GraphicsState &s, size_t seed) noexcept
+ s.cullMode
+ s.usesScissor
+ s.stencilTest
- + s.sampleCount;
+ + s.sampleCount
+ + s.multiViewCount;
}
bool operator==(const GraphicsPipelineStateKey &a, const GraphicsPipelineStateKey &b) noexcept
{
return a.state == b.state
- && a.sms->programRhi.program == b.sms->programRhi.program
- && a.compatibleRenderPassDescriptor->isCompatible(b.compatibleRenderPassDescriptor)
- && a.layoutCompatibleSrb->isLayoutCompatible(b.layoutCompatibleSrb);
+ && a.sms->materialShader == b.sms->materialShader
+ && a.renderTargetDescription == b.renderTargetDescription
+ && a.srbLayoutDescription == b.srbLayoutDescription;
}
bool operator!=(const GraphicsPipelineStateKey &a, const GraphicsPipelineStateKey &b) noexcept
@@ -3967,8 +4188,27 @@ bool operator!=(const GraphicsPipelineStateKey &a, const GraphicsPipelineStateKe
size_t qHash(const GraphicsPipelineStateKey &k, size_t seed) noexcept
{
- // no srb and rp included due to their special comparison semantics and lack of hash keys
- return qHash(k.state, seed) + qHash(k.sms->programRhi.program, seed);
+ return qHash(k.state, seed)
+ ^ qHash(k.sms->materialShader)
+ ^ k.extra.renderTargetDescriptionHash
+ ^ k.extra.srbLayoutDescriptionHash;
+}
+
+bool operator==(const ShaderKey &a, const ShaderKey &b) noexcept
+{
+ return a.type == b.type
+ && a.renderMode == b.renderMode
+ && a.multiViewCount == b.multiViewCount;
+}
+
+bool operator!=(const ShaderKey &a, const ShaderKey &b) noexcept
+{
+ return !(a == b);
+}
+
+size_t qHash(const ShaderKey &k, size_t seed) noexcept
+{
+ return qHash(k.type, seed) ^ int(k.renderMode) ^ k.multiViewCount;
}
Visualizer::Visualizer(Renderer *renderer)
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
index a42c41304f..a84797a4c6 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
@@ -1,43 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
-** Copyright (C) 2016 Robin Burchell <robin.burchell@viroteck.net>
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2016 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
+// Copyright (C) 2016 Robin Burchell <robin.burchell@viroteck.net>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSGBATCHRENDERER_P_H
#define QSGBATCHRENDERER_P_H
@@ -63,7 +27,7 @@
#include <QtCore/QBitArray>
#include <QtCore/QStack>
-#include <QtGui/private/qrhi_p.h>
+#include <rhi/qrhi.h>
QT_BEGIN_NAMESPACE
@@ -151,7 +115,7 @@ public:
// one. when an item is released, we'll reset m_freePage anyway.
if (!p) {
p = new AllocatorPage<Type, PageSize>();
- m_freePage = pages.count();
+ m_freePage = pages.size();
pages.push_back(p);
}
uint pos = p->blocks[PageSize - p->available];
@@ -295,7 +259,7 @@ inline QDebug operator << (QDebug d, const Rect &r) {
}
struct Buffer {
- int size;
+ quint32 size;
// Data is only valid while preparing the upload. Exception is if we are using the
// broken IBO workaround or we are using a visualization mode.
char *data;
@@ -633,6 +597,8 @@ struct GraphicsState
bool blending = false;
QRhiGraphicsPipeline::BlendFactor srcColor = QRhiGraphicsPipeline::One;
QRhiGraphicsPipeline::BlendFactor dstColor = QRhiGraphicsPipeline::OneMinusSrcAlpha;
+ QRhiGraphicsPipeline::BlendFactor srcAlpha = QRhiGraphicsPipeline::One;
+ QRhiGraphicsPipeline::BlendFactor dstAlpha = QRhiGraphicsPipeline::OneMinusSrcAlpha;
QRhiGraphicsPipeline::ColorMask colorWrite = QRhiGraphicsPipeline::ColorMask(0xF);
QRhiGraphicsPipeline::CullMode cullMode = QRhiGraphicsPipeline::None;
bool usesScissor = false;
@@ -640,6 +606,8 @@ struct GraphicsState
int sampleCount = 1;
QSGGeometry::DrawingMode drawMode = QSGGeometry::DrawTriangles;
float lineWidth = 1.0f;
+ QRhiGraphicsPipeline::PolygonMode polygonMode = QRhiGraphicsPipeline::Fill;
+ int multiViewCount = 0;
};
bool operator==(const GraphicsState &a, const GraphicsState &b) noexcept;
@@ -652,24 +620,46 @@ struct GraphicsPipelineStateKey
{
GraphicsState state;
const ShaderManagerShader *sms;
- const QRhiRenderPassDescriptor *compatibleRenderPassDescriptor;
- const QRhiShaderResourceBindings *layoutCompatibleSrb;
+ QVector<quint32> renderTargetDescription;
+ QVector<quint32> srbLayoutDescription;
+ struct {
+ size_t renderTargetDescriptionHash;
+ size_t srbLayoutDescriptionHash;
+ } extra;
+ static GraphicsPipelineStateKey create(const GraphicsState &state,
+ const ShaderManagerShader *sms,
+ const QRhiRenderPassDescriptor *rpDesc,
+ const QRhiShaderResourceBindings *srb)
+ {
+ const QVector<quint32> rtDesc = rpDesc->serializedFormat();
+ const QVector<quint32> srbDesc = srb->serializedLayoutDescription();
+ return { state, sms, rtDesc, srbDesc, { qHash(rtDesc), qHash(srbDesc) } };
+ }
};
bool operator==(const GraphicsPipelineStateKey &a, const GraphicsPipelineStateKey &b) noexcept;
bool operator!=(const GraphicsPipelineStateKey &a, const GraphicsPipelineStateKey &b) noexcept;
size_t qHash(const GraphicsPipelineStateKey &k, size_t seed = 0) noexcept;
+struct ShaderKey
+{
+ QSGMaterialType *type;
+ QSGRendererInterface::RenderMode renderMode;
+ int multiViewCount;
+};
+
+bool operator==(const ShaderKey &a, const ShaderKey &b) noexcept;
+bool operator!=(const ShaderKey &a, const ShaderKey &b) noexcept;
+size_t qHash(const ShaderKey &k, size_t seed = 0) noexcept;
+
struct ShaderManagerShader
{
~ShaderManagerShader() {
- delete programRhi.program;
+ delete materialShader;
}
- struct {
- QSGMaterialShader *program = nullptr;
- QRhiVertexInputLayout inputLayout;
- QVarLengthArray<QRhiGraphicsShaderStage, 2> shaderStages;
- } programRhi;
+ QSGMaterialShader *materialShader = nullptr;
+ QRhiVertexInputLayout inputLayout;
+ QVarLengthArray<QRhiShaderStage, 2> stages;
float lastOpacity;
};
@@ -687,26 +677,29 @@ public:
void clearCachedRendererData();
- using ShaderResourceBindingList = QVarLengthArray<QRhiShaderResourceBinding, 8>;
- QRhiShaderResourceBindings *srb(const ShaderResourceBindingList &bindings);
-
QHash<GraphicsPipelineStateKey, QRhiGraphicsPipeline *> pipelineCache;
+ QMultiHash<QVector<quint32>, QRhiShaderResourceBindings *> srbPool;
+ QVector<quint32> srbLayoutDescSerializeWorkspace;
+
public Q_SLOTS:
void invalidated();
public:
- Shader *prepareMaterial(QSGMaterial *material, const QSGGeometry *geometry = nullptr, QSGRendererInterface::RenderMode renderMode = QSGRendererInterface::RenderMode2D);
- Shader *prepareMaterialNoRewrite(QSGMaterial *material, const QSGGeometry *geometry = nullptr, QSGRendererInterface::RenderMode renderMode = QSGRendererInterface::RenderMode2D);
+ Shader *prepareMaterial(QSGMaterial *material,
+ const QSGGeometry *geometry = nullptr,
+ QSGRendererInterface::RenderMode renderMode = QSGRendererInterface::RenderMode2D,
+ int multiViewCount = 0);
+ Shader *prepareMaterialNoRewrite(QSGMaterial *material,
+ const QSGGeometry *geometry = nullptr,
+ QSGRendererInterface::RenderMode renderMode = QSGRendererInterface::RenderMode2D,
+ int multiViewCount = 0);
private:
- typedef QPair<QSGMaterialType *, QSGRendererInterface::RenderMode> ShaderKey;
QHash<ShaderKey, Shader *> rewrittenShaders;
QHash<ShaderKey, Shader *> stockShaders;
QSGDefaultRenderContext *context;
-
- QHash<ShaderResourceBindingList, QRhiShaderResourceBindings *> srbCache;
};
struct RenderPassState
@@ -747,7 +740,7 @@ protected:
QHash<Node *, uint> m_visualizeChangeSet;
};
-class Q_QUICK_PRIVATE_EXPORT Renderer : public QSGRenderer
+class Q_QUICK_EXPORT Renderer : public QSGRenderer
{
public:
Renderer(QSGDefaultRenderContext *ctx, QSGRendererInterface::RenderMode renderMode = QSGRendererInterface::RenderMode2D);
@@ -801,7 +794,7 @@ private:
friend class RhiVisualizer;
void destroyGraphicsResources();
- void map(Buffer *buffer, int size, bool isIndexBuf = false);
+ void map(Buffer *buffer, quint32 byteSize, bool isIndexBuf = false);
void unmap(Buffer *buffer, bool isIndexBuf = false);
void buildRenderListsFromScratch();
@@ -822,8 +815,7 @@ private:
bool ensurePipelineState(Element *e, const ShaderManager::Shader *sms, bool depthPostPass = false);
QRhiTexture *dummyTexture();
void updateMaterialDynamicData(ShaderManager::Shader *sms, QSGMaterialShader::RenderState &renderState,
- QSGMaterial *material, ShaderManager::ShaderResourceBindingList *bindings,
- const Batch *batch, int ubufOffset, int ubufRegionSize);
+ QSGMaterial *material, const Batch *batch, Element *e, int ubufOffset, int ubufRegionSize);
void updateMaterialStaticData(ShaderManager::Shader *sms, QSGMaterialShader::RenderState &renderState,
QSGMaterial *material, Batch *batch, bool *gstateChanged);
void checkLineWidth(QSGGeometry *g);
@@ -858,12 +850,11 @@ private:
inline Batch *newBatch();
void invalidateAndRecycleBatch(Batch *b);
+ void releaseElement(Element *e, bool inDestructor = false);
void setVisualizationMode(const QByteArray &mode) override;
bool hasVisualizationModeWithContinuousUpdate() const override;
- void invalidatePipelineCacheDependency(QRhiRenderPassDescriptor *rpDesc) override;
-
QSGDefaultRenderContext *m_context;
QSGRendererInterface::RenderMode m_renderMode;
QSet<Node *> m_taggedRoots;
@@ -884,6 +875,9 @@ private:
QDataBuffer<Element *> m_tmpAlphaElements;
QDataBuffer<Element *> m_tmpOpaqueElements;
+ QDataBuffer<QRhiBuffer *> m_vboPool;
+ QDataBuffer<QRhiBuffer *> m_iboPool;
+
uint m_rebuild;
qreal m_zRange;
#if defined(QSGBATCHRENDERER_INVALIDATE_WEDGED_NODES)
@@ -893,6 +887,7 @@ private:
int m_batchNodeThreshold;
int m_batchVertexThreshold;
+ int m_srbPoolThreshold;
Visualizer *m_visualizer;
@@ -1020,6 +1015,7 @@ void StencilClipState::reset()
Q_DECLARE_TYPEINFO(QSGBatchRenderer::GraphicsState, Q_RELOCATABLE_TYPE);
Q_DECLARE_TYPEINFO(QSGBatchRenderer::GraphicsPipelineStateKey, Q_RELOCATABLE_TYPE);
Q_DECLARE_TYPEINFO(QSGBatchRenderer::RenderPassState, Q_RELOCATABLE_TYPE);
+Q_DECLARE_TYPEINFO(QSGBatchRenderer::DrawSet, Q_PRIMITIVE_TYPE);
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/coreapi/qsggeometry.cpp b/src/quick/scenegraph/coreapi/qsggeometry.cpp
index c8ecf49767..9541107b78 100644
--- a/src/quick/scenegraph/coreapi/qsggeometry.cpp
+++ b/src/quick/scenegraph/coreapi/qsggeometry.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt scene graph research project.
-**
-** $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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qsggeometry.h"
#include "qsggeometry_p.h"
@@ -406,8 +370,10 @@ const QSGGeometry::AttributeSet &QSGGeometry::defaultAttributes_ColoredPoint2D()
Geometry objects are constructed by default with DrawTriangleStrip as
the drawing mode.
- The attribute structure is assumed to be POD and the geometry object
- assumes this will not go away. There is no memory management involved.
+ \note \a attributes and the \l Attribute objects referenced by it must
+ stay valid for the entire lifetime of the QSGGeometry.
+ QSGGeometry stores a reference to \a attributes and does not delete
+ the \l Attribute objects.
*/
QSGGeometry::QSGGeometry(const QSGGeometry::AttributeSet &attributes,
@@ -530,13 +496,18 @@ const void *QSGGeometry::indexData() const
Specifies the drawing mode, also called primitive topology.
+ \note Starting with Qt 6 the scene graph only exposes topologies that are
+ supported across all the supported 3D graphics APIs. As a result, the
+ values \c DrawLineLoop and \c DrawTriangleFan are no longer supported at
+ run time in Qt 6, even though the enum values themselves are still present.
+
\value DrawPoints
\value DrawLines
- \value DrawLineLoop
+ \omitvalue DrawLineLoop
\value DrawLineStrip
\value DrawTriangles
\value DrawTriangleStrip
- \value DrawTriangleFan
+ \omitvalue DrawTriangleFan
*/
/*!
@@ -570,10 +541,10 @@ void QSGGeometry::setDrawingMode(unsigned int mode)
}
/*!
- Gets the current line or point width or to be used for this
- geometry. This property only applies to line width when the drawingMode
- is DrawLines, DarwLineStrip, or DrawLineLoop. When supported, it also
- applies to point size when the drawingMode is DrawPoints.
+ Gets the current line or point width or to be used for this geometry. This
+ property only applies to line width when the drawingMode is DrawLines or
+ DrawLineStrip. When supported, it also applies to point size when the
+ drawingMode is DrawPoints.
The default value is \c 1.0
@@ -592,10 +563,10 @@ float QSGGeometry::lineWidth() const
}
/*!
- Sets the line or point width to be used for this geometry to \a
- width. This property only applies to line width when the drawingMode is
- DrawLines, DrawLineStrip, or DrawLineLoop. When supported, it also
- applies to point size when the drawingMode is DrawPoints.
+ Sets the line or point width to be used for this geometry to \a width. This
+ property only applies to line width when the drawingMode is DrawLines or
+ DrawLineStrip. When supported, it also applies to point size when the
+ drawingMode is DrawPoints.
\note Support for point and line drawing may be limited at run time,
depending on the platform and graphics API. For example, some APIs do
diff --git a/src/quick/scenegraph/coreapi/qsggeometry.h b/src/quick/scenegraph/coreapi/qsggeometry.h
index 060d896b3c..7fff62a915 100644
--- a/src/quick/scenegraph/coreapi/qsggeometry.h
+++ b/src/quick/scenegraph/coreapi/qsggeometry.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt scene graph research project.
-**
-** $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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSGGEOMETRY_H
#define QSGGEOMETRY_H
@@ -66,8 +30,6 @@ public:
StaticPattern = 3
};
- // Equivalents to GL_* drawing modes.
- // Keep in sync with GL headers.
enum DrawingMode {
DrawPoints = 0x0000,
DrawLines = 0x0001,
@@ -78,8 +40,6 @@ public:
DrawTriangleFan = 0x0006
};
- // Equivalents to GL_BYTE and similar type constants.
- // Keep in sync with GL headers.
enum Type {
ByteType = 0x1400,
UnsignedByteType = 0x1401,
@@ -134,7 +94,10 @@ public:
unsigned char r, g, b, a;
void set(float nx, float ny, uchar nr, uchar ng, uchar nb, uchar na) {
x = nx; y = ny;
- r = nr; g = ng, b = nb; a = na;
+ r = nr;
+ g = ng;
+ b = nb;
+ a = na;
}
};
@@ -201,6 +164,7 @@ public:
void setLineWidth(float w);
private:
+ Q_DISABLE_COPY_MOVE(QSGGeometry)
friend class QSGGeometryData;
int m_drawing_mode;
diff --git a/src/quick/scenegraph/coreapi/qsggeometry_p.h b/src/quick/scenegraph/coreapi/qsggeometry_p.h
index a80be662df..97463b6535 100644
--- a/src/quick/scenegraph/coreapi/qsggeometry_p.h
+++ b/src/quick/scenegraph/coreapi/qsggeometry_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSGGEOMETRY_P_H
#define QSGGEOMETRY_P_H
@@ -52,6 +16,7 @@
//
#include "qsggeometry.h"
+#include "private/qglobal_p.h"
QT_BEGIN_NAMESPACE
diff --git a/src/quick/scenegraph/coreapi/qsgmaterial.cpp b/src/quick/scenegraph/coreapi/qsgmaterial.cpp
index be18504f9b..49508c1c35 100644
--- a/src/quick/scenegraph/coreapi/qsgmaterial.cpp
+++ b/src/quick/scenegraph/coreapi/qsgmaterial.cpp
@@ -1,47 +1,13 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qsgmaterial.h"
#include "qsgrenderer_p.h"
QT_BEGIN_NAMESPACE
+Q_DECLARE_LOGGING_CATEGORY(lcQsgLeak)
+
#ifndef QT_NO_DEBUG
bool qsg_material_failure = false;
bool qsg_test_and_clear_material_failure()
@@ -57,10 +23,6 @@ void qsg_set_material_failure()
}
#endif
-#ifndef QT_NO_DEBUG
-static const bool qsg_leak_check = !qEnvironmentVariableIsEmpty("QML_LEAK_CHECK");
-#endif
-
/*!
\group qtquick-scenegraph-materials
\title Qt Quick Scene Graph Material Classes
@@ -75,7 +37,7 @@ static int qt_material_count = 0;
static void qt_print_material_count()
{
- qDebug("Number of leaked materials: %i", qt_material_count);
+ qCDebug(lcQsgLeak, "Number of leaked materials: %i", qt_material_count);
qt_material_count = -1;
}
#endif
@@ -145,7 +107,7 @@ QSGMaterial::QSGMaterial()
{
Q_UNUSED(m_reserved);
#ifndef QT_NO_DEBUG
- if (qsg_leak_check) {
+ if (lcQsgLeak().isDebugEnabled()) {
++qt_material_count;
static bool atexit_registered = false;
if (!atexit_registered) {
@@ -164,10 +126,10 @@ QSGMaterial::QSGMaterial()
QSGMaterial::~QSGMaterial()
{
#ifndef QT_NO_DEBUG
- if (qsg_leak_check) {
+ if (lcQsgLeak().isDebugEnabled()) {
--qt_material_count;
if (qt_material_count < 0)
- qDebug("Material destroyed after qt_print_material_count() was called.");
+ qCDebug(lcQsgLeak, "Material destroyed after qt_print_material_count() was called.");
}
#endif
}
@@ -177,7 +139,7 @@ QSGMaterial::~QSGMaterial()
/*!
\enum QSGMaterial::Flag
- \value Blending Set this flag to true if the material requires GL_BLEND to be
+ \value Blending Set this flag to true if the material requires blending to be
enabled during rendering.
\value RequiresDeterminant Set this flag to true if the material relies on
@@ -189,9 +151,22 @@ QSGMaterial::~QSGMaterial()
\value RequiresFullMatrix Set this flag to true if the material relies on
the full matrix of the geometry nodes for rendering.
- \value CustomCompileStep Starting with Qt 5.2, the scene graph will not always call
- QSGMaterialShader::compile() when its shader program is compiled and linked.
- Set this flag to enforce that the function is called.
+ \value NoBatching Set this flag to true if the material uses shaders that are
+ incompatible with the \l{Qt Quick Scene Graph Default Renderer}{scene graph's batching
+ mechanism}. This is relevant in certain advanced usages, such as, directly
+ manipulating \c{gl_Position.z} in the vertex shader. Such solutions are often tied to
+ a specific scene structure, and are likely not safe to use with arbitrary contents in
+ a scene. Thus this flag should only be set after appropriate investigation, and will
+ never be needed for the vast majority of materials. Setting this flag can lead to
+ reduced performance due to having to issue more draw calls. This flag was introduced
+ in Qt 6.3.
+
+ \value CustomCompileStep In Qt 6 this flag is identical to NoBatching. Prefer using
+ NoBatching instead.
+
+ \omitvalue MultiView2
+ \omitvalue MultiView3
+ \omitvalue MultiView4
*/
/*!
@@ -276,4 +251,185 @@ int QSGMaterial::compare(const QSGMaterial *other) const
RenderMode3D is in use.
*/
+/*!
+ \return The number of views in case of the material is used in multiview
+ rendering.
+
+ \note The return value is valid only when called from createShader(), and
+ afterwards. The value is not necessarily up-to-date before createShader()
+ is invokved by the scene graph.
+
+ Normally the return value is \c 1. A view count greater than 2 implies a
+ \e{multiview render pass}. Materials that support multiview are expected to
+ query viewCount() in createShader(), or in their QSGMaterialShader
+ constructor, and ensure the appropriate shaders are picked. The vertex
+ shader is then expected to use
+ \c{gl_ViewIndex} to index the modelview-projection matrix array as there
+ are multiple matrices in multiview mode. (one for each view)
+
+ As an example, take the following simple vertex shader:
+
+ \badcode
+ #version 440
+
+ layout(location = 0) in vec4 vertexCoord;
+ layout(location = 1) in vec4 vertexColor;
+
+ layout(location = 0) out vec4 color;
+
+ layout(std140, binding = 0) uniform buf {
+ mat4 matrix[2];
+ float opacity;
+ };
+
+ void main()
+ {
+ gl_Position = matrix[gl_ViewIndex] * vertexCoord;
+ color = vertexColor * opacity;
+ }
+ \endcode
+
+ This shader is prepared to handle 2 views, and 2 views only. It is not
+ compatible with other view counts. When conditioning the shader, the \c qsb
+ tool has to be invoked with \c{--view-count 2} or, if using the CMake
+ integration,
+ \c{VIEW_COUNT 2} must be specified in the \c{qt_add_shaders()} command.
+
+ \note A line with \c{#extension GL_EXT_multiview : require} is injected
+ automatically by \c qsb whenever a view count of 2 or greater is set.
+
+ Developers are encouraged to use the automatically injected preprocessor
+ variable \c{QSHADER_VIEW_COUNT} to simplify the handling of the different
+ number of views. For example, if there is a need to support both
+ non-multiview and multiview with a view count of 2 in the same source file,
+ the following could be done:
+
+ \badcode
+ #version 440
+
+ layout(location = 0) in vec4 vertexCoord;
+ layout(location = 1) in vec4 vertexColor;
+
+ layout(location = 0) out vec4 color;
+
+ layout(std140, binding = 0) uniform buf {
+ #if QSHADER_VIEW_COUNT >= 2
+ mat4 matrix[QSHADER_VIEW_COUNT];
+ #else
+ mat4 matrix;
+ #endif
+ float opacity;
+ };
+
+ void main()
+ {
+ #if QSHADER_VIEW_COUNT >= 2
+ gl_Position = matrix[gl_ViewIndex] * vertexCoord;
+ #else
+ gl_Position = matrix * vertexCoord;
+ #endif
+ color = vertexColor * opacity;
+ }
+ \endcode
+
+ The same source file can now be run through \c qsb or \c{qt_add_shaders()}
+ twice, once without specify the view count, and once with the view count
+ set to 2. The material can then pick the appropriate .qsb file based on
+ viewCount() at run time.
+
+ With CMake, this could looks similar to the following. With this example
+ the corresponding QSGMaterialShader is expected to choose between
+ \c{:/shaders/example.vert.qsb} and \c{:/shaders/multiview/example.vert.qsb}
+ based on the value of viewCount(). (same goes for the fragment shader)
+
+ \badcode
+ qt_add_shaders(application "application_shaders"
+ PREFIX
+ /
+ FILES
+ shaders/example.vert
+ shaders/example.frag
+ )
+
+ qt_add_shaders(application "application_multiview_shaders"
+ GLSL
+ 330,300es
+ HLSL
+ 61
+ MSL
+ 12
+ VIEW_COUNT
+ 2
+ PREFIX
+ /
+ FILES
+ shaders/example.vert
+ shaders/example.frag
+ OUTPUTS
+ shaders/multiview/example.vert
+ shaders/multiview/example.frag
+ )
+ \endcode
+
+ \note The fragment shader should be treated the same way the vertex shader
+ is, even though the fragment shader code cannot have any dependency on the
+ view count (\c{gl_ViewIndex}), for maximum portability. There are two
+ reasons for including fragment shaders too in the multiview set. One is that
+ mixing different shader versions within the same graphics pipeline can be
+ problematic, depending on the underlying graphics API: with D3D12 for
+ example, mixing HLSL shaders for shader model 5.0 and 6.1 would generate an
+ error. The other is that having \c QSHADER_VIEW_COUNT defined in fragment
+ shaders can be very useful, for example when sharing a uniform buffer layout
+ between the vertex and fragment stages.
+
+ \note For OpenGL the minimum GLSL version for vertex shaders relying on
+ \c{gl_ViewIndex} is \c 330. Lower versions may be accepted at build time,
+ but may lead to an error at run time, depending on the OpenGL implementation.
+
+ As a convenience, there is also a \c MULTIVIEW option for qt_add_shaders().
+ This first runs the \c qsb tool normally, then overrides \c VIEW_COUNT to
+ \c 2, sets \c GLSL, \c HLSL, \c MSL to some suitable defaults, and runs \c
+ qsb again, this time outputting .qsb files with a suffix added. The material
+ implementation can then use the \l QSGMaterialShader::setShaderFileName()
+ overload taking a \c viewCount argument, that automatically picks the
+ correct .qsb file.
+
+ The following is therefore mostly equivalent to the example call shown
+ above, except that no manually managed output files need to be specified.
+ Note that there can be cases when the automatically chosen shading language
+ versions are not sufficient, in which case applications should continue
+ specify everything explicitly.
+
+ \badcode
+ qt_add_shaders(application "application_multiview_shaders"
+ MULTIVIEW
+ PREFIX
+ /
+ FILES
+ shaders/example.vert
+ shaders/example.frag
+ )
+ \endcode
+
+ See \l QRhi::MultiView, \l QRhiColorAttachment::setMultiViewCount(), and
+ \l QRhiGraphicsPipeline::setMultiViewCount() for further, lower-level details
+ on multiview support in Qt. The Qt Quick scene graph renderer is prepared to
+ recognize multiview render targets, when specified via
+ \l QQuickRenderTarget::fromRhiRenderTarget() or the \c MultiView
+ functions such as \l{QQuickRenderTarget::}{fromVulkanImageMultiView()}, and
+ propagate the view count to graphics pipelines and the materials.
+
+ \since 6.8
+ */
+int QSGMaterial::viewCount() const
+{
+ if (m_flags.testFlag(MultiView4))
+ return 4;
+ if (m_flags.testFlag(MultiView3))
+ return 3;
+ if (m_flags.testFlag(MultiView2))
+ return 2;
+ return 1;
+}
+
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/coreapi/qsgmaterial.h b/src/quick/scenegraph/coreapi/qsgmaterial.h
index bd21c6e24c..ca3f134a9d 100644
--- a/src/quick/scenegraph/coreapi/qsgmaterial.h
+++ b/src/quick/scenegraph/coreapi/qsgmaterial.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 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$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSGMATERIAL_H
#define QSGMATERIAL_H
@@ -55,8 +19,18 @@ public:
RequiresDeterminant = 0x0002, // Allow precalculated translation and 2D rotation
RequiresFullMatrixExceptTranslate = 0x0004 | RequiresDeterminant, // Allow precalculated translation
RequiresFullMatrix = 0x0008 | RequiresFullMatrixExceptTranslate,
+ NoBatching = 0x0010,
+
+ MultiView2 = 0x10000,
+ MultiView3 = 0x20000,
+ MultiView4 = 0x40000,
+
+#if QT_DEPRECATED_SINCE(6, 3)
+ CustomCompileStep Q_DECL_ENUMERATOR_DEPRECATED_X(
+ "Qt 6 does not have custom shader compilation support. If the intention is to just disable batching, use NoBatching instead."
+ ) = NoBatching
+#endif
- CustomCompileStep = 0x0010
};
Q_DECLARE_FLAGS(Flags, Flag)
@@ -70,6 +44,8 @@ public:
QSGMaterial::Flags flags() const { return m_flags; }
void setFlag(Flags flags, bool on = true);
+ int viewCount() const;
+
private:
Flags m_flags;
void *m_reserved;
diff --git a/src/quick/scenegraph/coreapi/qsgmaterialshader.cpp b/src/quick/scenegraph/coreapi/qsgmaterialshader.cpp
index 45e7a6fb4e..a661e47765 100644
--- a/src/quick/scenegraph/coreapi/qsgmaterialshader.cpp
+++ b/src/quick/scenegraph/coreapi/qsgmaterialshader.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 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$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qsgmaterial.h"
#include "qsgrenderer_p.h"
@@ -212,9 +176,9 @@ QShader QSGMaterialShaderPrivate::loadShader(const QString &filename)
void QSGMaterialShaderPrivate::clearCachedRendererData()
{
for (int i = 0; i < MAX_SHADER_RESOURCE_BINDINGS; ++i)
- textureBindingTable[i] = nullptr;
+ textureBindingTable[i].clear();
for (int i = 0; i < MAX_SHADER_RESOURCE_BINDINGS; ++i)
- samplerBindingTable[i] = nullptr;
+ samplerBindingTable[i].clear();
}
static inline QRhiShaderResourceBinding::StageFlags toSrbStage(QShader::Stage stage)
@@ -237,14 +201,15 @@ void QSGMaterialShaderPrivate::prepare(QShader::Variant vertexShaderVariant)
ubufSize = 0;
ubufStages = { };
memset(static_cast<void *>(combinedImageSamplerBindings), 0, sizeof(combinedImageSamplerBindings));
+ memset(static_cast<void *>(combinedImageSamplerCount), 0, sizeof(combinedImageSamplerCount));
vertexShader = fragmentShader = nullptr;
masterUniformData.clear();
clearCachedRendererData();
for (QShader::Stage stage : { QShader::VertexStage, QShader::FragmentStage }) {
- auto it = shaderFileNames.find(stage);
- if (it != shaderFileNames.end()) {
+ auto it = shaderFileNames.constFind(stage);
+ if (it != shaderFileNames.cend()) {
QString fn = *it;
const QShader s = loadShader(*it);
if (!s.isValid())
@@ -282,7 +247,7 @@ void QSGMaterialShaderPrivate::prepare(QShader::Variant vertexShaderVariant)
const QShaderDescription desc = it->shader.description();
const QVector<QShaderDescription::UniformBlock> ubufs = desc.uniformBlocks();
- const int ubufCount = ubufs.count();
+ const int ubufCount = ubufs.size();
if (ubufCount > 1) {
qWarning("Multiple uniform blocks found in shader. "
"This should be avoided as Qt Quick supports only one.");
@@ -307,14 +272,25 @@ void QSGMaterialShaderPrivate::prepare(QShader::Variant vertexShaderVariant)
}
const QVector<QShaderDescription::InOutVariable> imageSamplers = desc.combinedImageSamplers();
- const int imageSamplersCount = imageSamplers.count();
+ const int imageSamplersCount = imageSamplers.size();
for (int i = 0; i < imageSamplersCount; ++i) {
const QShaderDescription::InOutVariable &var(imageSamplers[i]);
- if (var.binding >= 0 && var.binding < MAX_SHADER_RESOURCE_BINDINGS)
+
+ if (var.binding < 0)
+ continue;
+
+ if (var.binding < MAX_SHADER_RESOURCE_BINDINGS) {
combinedImageSamplerBindings[var.binding] |= toSrbStage(it->shader.stage());
- else
+
+ int count = 1;
+ for (int dim : var.arrayDims)
+ count *= dim;
+
+ combinedImageSamplerCount[var.binding] = count;
+ } else {
qWarning("Encountered invalid combined image sampler (%s) binding %d",
var.name.constData(), var.binding);
+ }
}
if (it.key() == QShader::VertexStage)
@@ -360,8 +336,7 @@ static inline QShader::Stage toShaderStage(QSGMaterialShader::Stage stage)
case QSGMaterialShader::FragmentStage:
return QShader::FragmentStage;
default:
- Q_UNREACHABLE();
- return QShader::VertexStage;
+ Q_UNREACHABLE_RETURN(QShader::VertexStage);
}
}
@@ -386,6 +361,33 @@ void QSGMaterialShader::setShaderFileName(Stage stage, const QString &filename)
}
/*!
+ Sets the \a filename for the shader for the specified \a stage.
+
+ The file is expected to contain a serialized QShader.
+
+ This overload is used when enabling \l{QSGMaterial::viewCount()}{multiview}
+ rendering, in particular when the \l{Qt Shader Tools Build System
+ Integration}{build system's MULTIVIEW convenience option} is used.
+
+ \a viewCount should be 2, 3, or 4. The \a filename is adjusted automatically
+ based on this.
+
+ \since 6.8
+ */
+void QSGMaterialShader::setShaderFileName(Stage stage, const QString &filename, int viewCount)
+{
+ Q_D(QSGMaterialShader);
+ if (viewCount == 2)
+ d->shaderFileNames[toShaderStage(stage)] = filename + QStringLiteral(".mv2qsb");
+ else if (viewCount == 3)
+ d->shaderFileNames[toShaderStage(stage)] = filename + QStringLiteral(".mv3qsb");
+ else if (viewCount == 4)
+ d->shaderFileNames[toShaderStage(stage)] = filename + QStringLiteral(".mv4qsb");
+ else
+ d->shaderFileNames[toShaderStage(stage)] = filename;
+}
+
+/*!
\return the currently set flags for this material shader.
*/
QSGMaterialShader::Flags QSGMaterialShader::flags() const
@@ -417,6 +419,37 @@ void QSGMaterialShader::setFlags(Flags flags)
}
/*!
+ Returns the number of elements in the combined image sampler variable at \a
+ binding. This value is introspected from the shader code. The variable may
+ be an array, and may have more than one dimension.
+
+ The count reflects the total number of combined image sampler items in the
+ variable. In the following example, the count for \c{srcA} is 1, \c{srcB}
+ is 4, and \c{srcC} is 6.
+
+ \badcode
+ layout (binding = 0) uniform sampler2D srcA;
+ layout (binding = 1) uniform sampler2D srcB[4];
+ layout (binding = 2) uniform sampler2D srcC[2][3];
+ \endcode
+
+ This count is the number of QSGTexture pointers in the texture parameter
+ of \l{QSGMaterialShader::updateSampledImage}.
+
+ \sa QSGMaterialShader::updateSampledImage
+ \since 6.4
+ */
+int QSGMaterialShader::combinedImageSamplerCount(int binding) const
+{
+ Q_D(const QSGMaterialShader);
+
+ if (binding >= 0 && binding < d->MAX_SHADER_RESOURCE_BINDINGS)
+ return d->combinedImageSamplerCount[binding];
+
+ return 0;
+}
+
+/*!
This function is called by the scene graph to get the contents of the
shader program's uniform buffer updated. The implementation is not expected
to perform any real graphics operations, it is merely responsible for
@@ -451,27 +484,35 @@ bool QSGMaterialShader::updateUniformData(RenderState &state,
}
/*!
- This function is called by the scene graph to prepare using a sampled image
- in the shader, typically in form of a combined image sampler.
+ This function is called by the scene graph to prepare use of sampled images
+ in the shader, typically in the form of combined image samplers.
\a binding is the binding number of the sampler. The function is called for
each combined image sampler variable in the shader code associated with the
QSGMaterialShader.
- When *\a{texture} is null, it must be set to a QSGTexture pointer before
- returning. When non-null, it is up to the material to decide if a new
- \c{QSGTexture *} is stored to it, or if it updates some parameters on the
- already known QSGTexture. The ownership of the QSGTexture is not
- transferred.
+ \a{texture} is an array of QSGTexture pointers. The number of elements in
+ the array matches the number of elements in the image sampler variable
+ specified in the shader code. This variable may be an array, and may have
+ more than one dimension. The number of elements in the array may be
+ found via \l{QSGMaterialShader::combinedImageSamplerCount}
+
+ When an element in \a{texture} is null, it must be set to a valid
+ QSGTexture pointer before returning. When non-null, it is up to the
+ material to decide if a new \c{QSGTexture *} is stored to it, or if it
+ updates some parameters on the already known QSGTexture. The ownership of
+ the QSGTexture is not transferred.
The current rendering \a state is passed from the scene graph. Where
relevant, it is up to the material to trigger enqueuing texture data
- uploads.
+ uploads via QSGTexture::commitTextureOperations().
The subclass specific state can be extracted from \a newMaterial.
\a oldMaterial can be used to minimize changes. When \a oldMaterial is null,
this shader was just activated.
+
+ \sa QSGMaterialShader::combinedImageSamplerCount
*/
void QSGMaterialShader::updateSampledImage(RenderState &state,
int binding,
@@ -586,6 +627,12 @@ bool QSGMaterialShader::updateGraphicsPipelineState(RenderState &state, Graphics
updatePipelineState() implementation, if there is one. The scenegraph will
then internally apply these changes to the active graphics pipeline state,
then rolling them back as appropriate.
+
+ When updateGraphicsPipelineState() is called, the struct has all members
+ set to a valid value to reflect the renderer's current state. Not changing
+ any values (or not reimplementing the function) indicates that the material
+ is fine with the defaults (which are dynamic however, depending on
+ QSGMaterial flags, for example).
*/
/*!
@@ -633,6 +680,98 @@ bool QSGMaterialShader::updateGraphicsPipelineState(RenderState &state, Graphics
*/
/*!
+ \enum QSGMaterialShader::GraphicsPipelineState::PolygonMode
+ \since 6.4
+ \brief Specifies the polygon rasterization mode
+
+ Polygon Mode (Triangle Fill Mode in Metal, Fill Mode in D3D) specifies
+ the fill mode used when rasterizing polygons. Polygons may be drawn as
+ solids (Fill), or as a wire mesh (Line).
+
+ \warning OpenGL ES does not support the \c{Line} polygon mode. OpenGL ES
+ will rasterize all polygons as filled no matter what polygon mode is set.
+ Using \c{Line} will make your application non-portable.
+
+ \value Fill The interior of the polygon is filled (default)
+ \value Line Boundary edges of the polygon are drawn as line segments.
+ */
+
+/*!
+ \variable QSGMaterialShader::GraphicsPipelineState::blendEnable
+ \since 5.14
+ \brief Enables blending.
+
+ \note Changing this flag should be done with care, and is best avoided.
+ Rather, materials should always use the QSGMaterial::Blend flag to indicate
+ that they wish to use blending. Changing this value from false to true for
+ a material that did not declare QSGMaterial::Blend can lead to unexpected
+ visual results.
+ */
+
+/*!
+ \variable QSGMaterialShader::GraphicsPipelineState::srcColor
+ \since 5.14
+ \brief Source blending factor, either RGB or RGBA depending on separateBlendFactors.
+ */
+
+/*!
+ \variable QSGMaterialShader::GraphicsPipelineState::dstColor
+ \since 5.14
+ \brief Destination blending factor, either RGB or RGBA depending on separateBlendFactors.
+ */
+
+/*!
+ \variable QSGMaterialShader::GraphicsPipelineState::colorWrite
+ \since 5.14
+ \brief Color write mask.
+ */
+
+/*!
+ \variable QSGMaterialShader::GraphicsPipelineState::blendConstant
+ \since 5.14
+ \brief Blend constant applicable when a blending factor is set to use a constant value.
+ */
+
+/*!
+ \variable QSGMaterialShader::GraphicsPipelineState::cullMode
+ \since 5.14
+ \brief Cull mode.
+ */
+
+/*!
+ \variable QSGMaterialShader::GraphicsPipelineState::polygonMode
+ \since 6.4
+ \brief Polygon rasterization mode.
+ */
+
+/*!
+ \variable QSGMaterialShader::GraphicsPipelineState::separateBlendFactors
+ \since 6.5
+ \brief Indicates that alpha blending factors are specified separately.
+
+ False by default, meaning both RGB and alpha blending factors are defined
+ by srcColor and dstColor. When set to true, the alpha blending factors are
+ taken from srcAlpha and dstAlpha instead, and srcColor and dstColor applies
+ only to RGB.
+ */
+
+/*!
+ \variable QSGMaterialShader::GraphicsPipelineState::srcAlpha
+ \since 6.5
+ \brief Source alpha blending factor.
+
+ Applies only when separateBlendFactors is set to true.
+ */
+
+/*!
+ \variable QSGMaterialShader::GraphicsPipelineState::dstAlpha
+ \since 6.5
+ \brief Destination alpha blending factor.
+
+ Applies only when separateBlendFactors is set to true.
+ */
+
+/*!
Returns the accumulated opacity to be used for rendering.
*/
float QSGMaterialShader::RenderState::opacity() const
@@ -656,7 +795,16 @@ float QSGMaterialShader::RenderState::determinant() const
QMatrix4x4 QSGMaterialShader::RenderState::combinedMatrix() const
{
Q_ASSERT(m_data);
- return static_cast<const QSGRenderer *>(m_data)->currentCombinedMatrix();
+ return static_cast<const QSGRenderer *>(m_data)->currentCombinedMatrix(0);
+}
+
+/*!
+ \internal
+ */
+QMatrix4x4 QSGMaterialShader::RenderState::combinedMatrix(int index) const
+{
+ Q_ASSERT(m_data);
+ return static_cast<const QSGRenderer *>(m_data)->currentCombinedMatrix(index);
}
/*!
@@ -695,7 +843,25 @@ QMatrix4x4 QSGMaterialShader::RenderState::modelViewMatrix() const
QMatrix4x4 QSGMaterialShader::RenderState::projectionMatrix() const
{
Q_ASSERT(m_data);
- return static_cast<const QSGRenderer *>(m_data)->currentProjectionMatrix();
+ return static_cast<const QSGRenderer *>(m_data)->currentProjectionMatrix(0);
+}
+
+/*!
+ \internal
+ */
+QMatrix4x4 QSGMaterialShader::RenderState::projectionMatrix(int index) const
+{
+ Q_ASSERT(m_data);
+ return static_cast<const QSGRenderer *>(m_data)->currentProjectionMatrix(index);
+}
+
+/*!
+ \internal
+ */
+int QSGMaterialShader::RenderState::projectionMatrixCount() const
+{
+ Q_ASSERT(m_data);
+ return static_cast<const QSGRenderer *>(m_data)->projectionMatrixCount();
}
/*!
diff --git a/src/quick/scenegraph/coreapi/qsgmaterialshader.h b/src/quick/scenegraph/coreapi/qsgmaterialshader.h
index bde210bef8..795da77477 100644
--- a/src/quick/scenegraph/coreapi/qsgmaterialshader.h
+++ b/src/quick/scenegraph/coreapi/qsgmaterialshader.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 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$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSGMATERIALSHADER_H
#define QSGMATERIALSHADER_H
@@ -71,13 +35,16 @@ public:
inline DirtyStates dirtyStates() const { return m_dirty; }
- inline bool isMatrixDirty() const { return m_dirty & QSGMaterialShader::RenderState::DirtyMatrix; }
- inline bool isOpacityDirty() const { return m_dirty & QSGMaterialShader::RenderState::DirtyOpacity; }
+ inline bool isMatrixDirty() const { return bool(m_dirty & QSGMaterialShader::RenderState::DirtyMatrix); }
+ inline bool isOpacityDirty() const { return bool(m_dirty & QSGMaterialShader::RenderState::DirtyOpacity); }
float opacity() const;
QMatrix4x4 combinedMatrix() const;
+ QMatrix4x4 combinedMatrix(int index) const;
QMatrix4x4 modelViewMatrix() const;
QMatrix4x4 projectionMatrix() const;
+ QMatrix4x4 projectionMatrix(int index) const;
+ int projectionMatrixCount() const;
QRect viewportRect() const;
QRect deviceRect() const;
float determinant() const;
@@ -93,7 +60,7 @@ public:
const void *m_data;
};
- struct Q_QUICK_EXPORT GraphicsPipelineState {
+ struct GraphicsPipelineState {
enum BlendFactor {
Zero,
One,
@@ -130,12 +97,21 @@ public:
CullBack
};
+ enum PolygonMode {
+ Fill,
+ Line,
+ };
+
bool blendEnable;
BlendFactor srcColor;
BlendFactor dstColor;
ColorMask colorWrite;
QColor blendConstant;
CullMode cullMode;
+ PolygonMode polygonMode;
+ bool separateBlendFactors;
+ BlendFactor srcAlpha;
+ BlendFactor dstAlpha;
// This struct is extensible while keeping BC since apps only ever get
// a ptr to the struct, it is not created by them.
};
@@ -166,12 +142,15 @@ public:
void setFlag(Flags flags, bool on = true);
void setFlags(Flags flags);
+ int combinedImageSamplerCount(int binding) const;
+
protected:
Q_DECLARE_PRIVATE(QSGMaterialShader)
QSGMaterialShader(QSGMaterialShaderPrivate &dd);
// filename is for a file containing a serialized QShader.
void setShaderFileName(Stage stage, const QString &filename);
+ void setShaderFileName(Stage stage, const QString &filename, int viewCount);
void setShader(Stage stage, const QShader &shader);
diff --git a/src/quick/scenegraph/coreapi/qsgmaterialshader_p.h b/src/quick/scenegraph/coreapi/qsgmaterialshader_p.h
index 42d1635c84..8b4a4c0b2f 100644
--- a/src/quick/scenegraph/coreapi/qsgmaterialshader_p.h
+++ b/src/quick/scenegraph/coreapi/qsgmaterialshader_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 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$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSGMATERIALSHADER_P_H
#define QSGMATERIALSHADER_P_H
@@ -54,14 +18,14 @@
#include <private/qtquickglobal_p.h>
#include "qsgmaterialshader.h"
#include "qsgmaterial.h"
-#include <QtGui/private/qrhi_p.h>
-#include <QtGui/private/qshader_p.h>
+#include <rhi/qrhi.h>
+#include <rhi/qshader.h>
QT_BEGIN_NAMESPACE
class QRhiSampler;
-class Q_QUICK_PRIVATE_EXPORT QSGMaterialShaderPrivate
+class Q_QUICK_EXPORT QSGMaterialShaderPrivate
{
public:
Q_DECLARE_PUBLIC(QSGMaterialShader)
@@ -97,14 +61,15 @@ public:
int ubufSize = 0;
QRhiShaderResourceBinding::StageFlags ubufStages;
QRhiShaderResourceBinding::StageFlags combinedImageSamplerBindings[MAX_SHADER_RESOURCE_BINDINGS];
+ int combinedImageSamplerCount[MAX_SHADER_RESOURCE_BINDINGS];
ShaderStageData *vertexShader = nullptr;
ShaderStageData *fragmentShader = nullptr;
QByteArray masterUniformData;
- QSGTexture *textureBindingTable[MAX_SHADER_RESOURCE_BINDINGS];
- QRhiSampler *samplerBindingTable[MAX_SHADER_RESOURCE_BINDINGS];
+ QVarLengthArray<QSGTexture *, 4> textureBindingTable[MAX_SHADER_RESOURCE_BINDINGS];
+ QVarLengthArray<QRhiSampler *, 4> samplerBindingTable[MAX_SHADER_RESOURCE_BINDINGS];
};
Q_DECLARE_TYPEINFO(QSGMaterialShaderPrivate::ShaderStageData, Q_RELOCATABLE_TYPE);
diff --git a/src/quick/scenegraph/coreapi/qsgmaterialtype.h b/src/quick/scenegraph/coreapi/qsgmaterialtype.h
index 15141c2d9e..178b4f8a8a 100644
--- a/src/quick/scenegraph/coreapi/qsgmaterialtype.h
+++ b/src/quick/scenegraph/coreapi/qsgmaterialtype.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 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$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSGMATERIALTYPE_H
#define QSGMATERIALTYPE_H
diff --git a/src/quick/scenegraph/coreapi/qsgnode.cpp b/src/quick/scenegraph/coreapi/qsgnode.cpp
index e22ffa10d2..b77f33d6a3 100644
--- a/src/quick/scenegraph/coreapi/qsgnode.cpp
+++ b/src/quick/scenegraph/coreapi/qsgnode.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qsgnode.h"
#include "qsgnode_p.h"
@@ -47,13 +11,14 @@
QT_BEGIN_NAMESPACE
+Q_DECLARE_LOGGING_CATEGORY(lcQsgLeak)
+
#ifndef QT_NO_DEBUG
-static const bool qsg_leak_check = !qEnvironmentVariableIsEmpty("QML_LEAK_CHECK");
static int qt_node_count = 0;
static void qt_print_node_count()
{
- qDebug("Number of leaked nodes: %i", qt_node_count);
+ qCDebug(lcQsgLeak, "Number of leaked nodes: %i", qt_node_count);
qt_node_count = -1;
}
#endif
@@ -78,8 +43,8 @@ static void qt_print_node_count()
insertChildNodeAfter(). The order of nodes is important as geometry nodes
are rendered according to their ordering in the scene graph.
- The scene graph nodes contains a mechanism to describe which
- parts of the scene has changed. This includes the combined matrices,
+ The scene graph nodes contain a mechanism that describes which
+ parts of the scene have changed. This includes the combined matrices,
accumulated opacity, changes to the node hierarchy, and so on. This
information can be used for optimizations inside the scene graph renderer.
For the renderer to properly render the nodes, it is important that users
@@ -292,7 +257,7 @@ QSGNode::QSGNode(QSGNodePrivate &dd, NodeType type)
void QSGNode::init()
{
#ifndef QT_NO_DEBUG
- if (qsg_leak_check) {
+ if (lcQsgLeak().isDebugEnabled()) {
++qt_node_count;
static bool atexit_registered = false;
if (!atexit_registered) {
@@ -317,10 +282,10 @@ void QSGNode::init()
QSGNode::~QSGNode()
{
#ifndef QT_NO_DEBUG
- if (qsg_leak_check) {
+ if (lcQsgLeak().isDebugEnabled()) {
--qt_node_count;
if (qt_node_count < 0)
- qDebug("Node destroyed after qt_print_node_count() was called.");
+ qCDebug(lcQsgLeak, "Node destroyed after qt_print_node_count() was called.");
}
#endif
destroy();
diff --git a/src/quick/scenegraph/coreapi/qsgnode.h b/src/quick/scenegraph/coreapi/qsgnode.h
index 19b8cf9354..50dc6021ea 100644
--- a/src/quick/scenegraph/coreapi/qsgnode.h
+++ b/src/quick/scenegraph/coreapi/qsgnode.h
@@ -1,45 +1,10 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSGNODE_H
#define QSGNODE_H
+#include <QtCore/qlist.h>
#include <QtQuick/qsggeometry.h>
#include <QtGui/QMatrix4x4>
@@ -95,7 +60,7 @@ public:
// Uppermost 8 bits are reserved for internal use.
IsVisitableNode = 0x01000000
-#ifdef Q_CLANG_QDOC
+#ifdef Q_QDOC
, InternalReserved = 0x01000000
#endif
};
@@ -210,8 +175,8 @@ private:
QSGGeometry *m_geometry;
- int m_reserved_start_index;
- int m_reserved_end_index;
+ Q_DECL_UNUSED_MEMBER int m_reserved_start_index;
+ Q_DECL_UNUSED_MEMBER int m_reserved_end_index;
const QMatrix4x4 *m_matrix;
const QSGClipNode *m_clip_list;
diff --git a/src/quick/scenegraph/coreapi/qsgnode_p.h b/src/quick/scenegraph/coreapi/qsgnode_p.h
index f81128f51a..78d0bf2ca5 100644
--- a/src/quick/scenegraph/coreapi/qsgnode_p.h
+++ b/src/quick/scenegraph/coreapi/qsgnode_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB)
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB)
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSGNODE_P_H
#define QSGNODE_P_H
@@ -51,7 +15,7 @@
// We mean it.
//
-#include <qglobal.h>
+#include <private/qglobal_p.h>
#include "qsgnode.h"
diff --git a/src/quick/scenegraph/coreapi/qsgnodeupdater.cpp b/src/quick/scenegraph/coreapi/qsgnodeupdater.cpp
index 57faf0faad..cb1023a87a 100644
--- a/src/quick/scenegraph/coreapi/qsgnodeupdater.cpp
+++ b/src/quick/scenegraph/coreapi/qsgnodeupdater.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qsgnodeupdater_p.h"
#include "qsgnode.h"
diff --git a/src/quick/scenegraph/coreapi/qsgnodeupdater_p.h b/src/quick/scenegraph/coreapi/qsgnodeupdater_p.h
index 67d916ed28..a2bf37b538 100644
--- a/src/quick/scenegraph/coreapi/qsgnodeupdater_p.h
+++ b/src/quick/scenegraph/coreapi/qsgnodeupdater_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSGNODEUPDATER_P_H
#define QSGNODEUPDATER_P_H
@@ -64,7 +28,7 @@ class QSGGeometryNode;
class QMatrix4x4;
class QSGRenderNode;
-class Q_QUICK_PRIVATE_EXPORT QSGNodeUpdater
+class Q_QUICK_EXPORT QSGNodeUpdater
{
public:
QSGNodeUpdater();
diff --git a/src/quick/scenegraph/coreapi/qsgrenderer.cpp b/src/quick/scenegraph/coreapi/qsgrenderer.cpp
index 4b3cd9f2c1..ffa3047850 100644
--- a/src/quick/scenegraph/coreapi/qsgrenderer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgrenderer.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qsgrenderer_p.h"
#include "qsgnodeupdater_p.h"
@@ -50,12 +14,19 @@ static QElapsedTimer frameTimer;
static qint64 preprocessTime;
static qint64 updatePassTime;
+Q_TRACE_POINT(qtquick, QSG_preprocess_entry)
+Q_TRACE_POINT(qtquick, QSG_preprocess_exit)
+Q_TRACE_POINT(qtquick, QSG_update_entry)
+Q_TRACE_POINT(qtquick, QSG_update_exit)
+Q_TRACE_POINT(qtquick, QSG_renderScene_entry)
+Q_TRACE_POINT(qtquick, QSG_renderScene_exit)
+
int qt_sg_envInt(const char *name, int defaultValue)
{
if (Q_LIKELY(!qEnvironmentVariableIsSet(name)))
return defaultValue;
bool ok = false;
- int value = qgetenv(name).toInt(&ok);
+ int value = qEnvironmentVariableIntValue(name, &ok);
return ok ? value : defaultValue;
}
@@ -95,15 +66,13 @@ QSGRenderer::QSGRenderer(QSGRenderContext *context)
, m_current_uniform_data(nullptr)
, m_current_resource_update_batch(nullptr)
, m_rhi(nullptr)
- , m_rt(nullptr)
- , m_cb(nullptr)
- , m_rp_desc(nullptr)
- , m_external_rp_desc(nullptr)
, m_node_updater(nullptr)
, m_changed_emitted(false)
, m_is_rendering(false)
, m_is_preprocessing(false)
{
+ m_current_projection_matrix.resize(1);
+ m_current_projection_matrix_native_ndc.resize(1);
}
@@ -143,7 +112,7 @@ void QSGRenderer::setNodeUpdater(QSGNodeUpdater *updater)
bool QSGRenderer::isMirrored() const
{
- QMatrix4x4 matrix = projectionMatrix();
+ QMatrix4x4 matrix = projectionMatrix(0);
// Mirrored relative to the usual Qt coordinate system with origin in the top left corner.
return matrix(0, 0) * matrix(1, 1) - matrix(0, 1) * matrix(1, 0) > 0;
}
diff --git a/src/quick/scenegraph/coreapi/qsgrenderer_p.h b/src/quick/scenegraph/coreapi/qsgrenderer_p.h
index 31f00dc738..28654521c9 100644
--- a/src/quick/scenegraph/coreapi/qsgrenderer_p.h
+++ b/src/quick/scenegraph/coreapi/qsgrenderer_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSGRENDERER_P_H
#define QSGRENDERER_P_H
@@ -65,19 +29,44 @@ class QRhiCommandBuffer;
class QRhiRenderPassDescriptor;
class QRhiResourceUpdateBatch;
-Q_QUICK_PRIVATE_EXPORT bool qsg_test_and_clear_fatal_render_error();
-Q_QUICK_PRIVATE_EXPORT void qsg_set_fatal_renderer_error();
+Q_QUICK_EXPORT bool qsg_test_and_clear_fatal_render_error();
+Q_QUICK_EXPORT void qsg_set_fatal_renderer_error();
-class Q_QUICK_PRIVATE_EXPORT QSGRenderer : public QSGAbstractRenderer
+class Q_QUICK_EXPORT QSGRenderTarget
+{
+public:
+ QSGRenderTarget() { }
+
+ QSGRenderTarget(QRhiRenderTarget *rt,
+ QRhiRenderPassDescriptor *rpDesc,
+ QRhiCommandBuffer *cb)
+ : rt(rt), rpDesc(rpDesc), cb(cb) { }
+
+ explicit QSGRenderTarget(QPaintDevice *paintDevice)
+ : paintDevice(paintDevice) { }
+
+ QRhiRenderTarget *rt = nullptr;
+ // Store the rp descriptor obj separately, it can (even if often it won't)
+ // be different from rt->renderPassDescriptor(); e.g. one user is the 2D
+ // integration in Quick 3D which will use a different, but compatible rp.
+ QRhiRenderPassDescriptor *rpDesc = nullptr;
+ QRhiCommandBuffer *cb = nullptr;
+
+ QPaintDevice *paintDevice = nullptr;
+
+ int multiViewCount = 0;
+};
+
+class Q_QUICK_EXPORT QSGRenderer : public QSGAbstractRenderer
{
public:
QSGRenderer(QSGRenderContext *context);
virtual ~QSGRenderer();
// Accessed by QSGMaterial[Rhi]Shader::RenderState.
- QMatrix4x4 currentProjectionMatrix() const { return m_current_projection_matrix; }
+ QMatrix4x4 currentProjectionMatrix(int index) const { return m_current_projection_matrix[index]; }
QMatrix4x4 currentModelViewMatrix() const { return m_current_model_view_matrix; }
- QMatrix4x4 currentCombinedMatrix() const { return m_current_projection_matrix * m_current_model_view_matrix; }
+ QMatrix4x4 currentCombinedMatrix(int index) const { return m_current_projection_matrix[index] * m_current_model_view_matrix; }
qreal currentOpacity() const { return m_current_opacity; }
qreal determinant() const { return m_current_determinant; }
@@ -97,7 +86,6 @@ public:
virtual void setVisualizationMode(const QByteArray &) { }
virtual bool hasVisualizationModeWithContinuousUpdate() const { return false; }
virtual void releaseCachedResources() { }
- virtual void invalidatePipelineCacheDependency(QRhiRenderPassDescriptor *) { }
void clearChangedFlag() { m_changed_emitted = false; }
@@ -106,26 +94,8 @@ public:
QRhiResourceUpdateBatch *currentResourceUpdateBatch() const { return m_current_resource_update_batch; }
QRhi *currentRhi() const { return m_rhi; }
- void setRenderTarget(QRhiRenderTarget *rt) { m_rt = rt; }
- QRhiRenderTarget *renderTarget() const { return m_rt; }
-
- void setCommandBuffer(QRhiCommandBuffer *cb) { m_cb = cb; }
- QRhiCommandBuffer *commandBuffer() const { return m_cb; }
-
- void setRenderPassDescriptor(QRhiRenderPassDescriptor *rpDesc) { m_rp_desc = rpDesc; }
- QRhiRenderPassDescriptor *renderPassDescriptor() const { return m_rp_desc; }
-
- void setExternalRenderPassDescriptor(QRhiRenderPassDescriptor *rpDesc) {
- if (m_external_rp_desc) {
- // Changes will be rare in practice - one has to construct a
- // dynamic Quick 3D scene with reparenting involved for that. Play
- // nice nonetheless and invalidate as soon as possible.
- if (m_external_rp_desc != rpDesc)
- invalidatePipelineCacheDependency(m_external_rp_desc);
- }
- m_rp_desc = rpDesc;
- m_external_rp_desc = rpDesc;
- }
+ void setRenderTarget(const QSGRenderTarget &rt) { m_rt = rt; }
+ const QSGRenderTarget &renderTarget() const { return m_rt; }
void setRenderPassRecordingCallbacks(QSGRenderContext::RenderPassCallback start,
QSGRenderContext::RenderPassCallback end,
@@ -147,8 +117,8 @@ protected:
void addNodesToPreprocess(QSGNode *node);
void removeNodesToPreprocess(QSGNode *node);
- QMatrix4x4 m_current_projection_matrix; // includes adjustment, where applicable, so can be treated as Y up in NDC always
- QMatrix4x4 m_current_projection_matrix_native_ndc; // Vulkan has Y down in normalized device coordinates, others Y up...
+ QVarLengthArray<QMatrix4x4, 1> m_current_projection_matrix; // includes adjustment, where applicable, so can be treated as Y up in NDC always
+ QVarLengthArray<QMatrix4x4, 1> m_current_projection_matrix_native_ndc; // Vulkan has Y down in normalized device coordinates, others Y up...
QMatrix4x4 m_current_model_view_matrix;
qreal m_current_opacity;
qreal m_current_determinant;
@@ -159,10 +129,7 @@ protected:
QByteArray *m_current_uniform_data;
QRhiResourceUpdateBatch *m_current_resource_update_batch;
QRhi *m_rhi;
- QRhiRenderTarget *m_rt;
- QRhiCommandBuffer *m_cb;
- QRhiRenderPassDescriptor *m_rp_desc;
- QRhiRenderPassDescriptor *m_external_rp_desc;
+ QSGRenderTarget m_rt;
struct {
QSGRenderContext::RenderPassCallback start = nullptr;
QSGRenderContext::RenderPassCallback end = nullptr;
@@ -189,7 +156,7 @@ QSGMaterialShader::RenderState QSGRenderer::state(QSGMaterialShader::RenderState
}
-class Q_QUICK_PRIVATE_EXPORT QSGNodeDumper : public QSGNodeVisitor {
+class Q_QUICK_EXPORT QSGNodeDumper : public QSGNodeVisitor {
public:
static void dump(QSGNode *n);
@@ -202,8 +169,6 @@ private:
int m_indent = 0;
};
-
-
QT_END_NAMESPACE
#endif
diff --git a/src/quick/scenegraph/coreapi/qsgrendererinterface.cpp b/src/quick/scenegraph/coreapi/qsgrendererinterface.cpp
index 31067f98bd..b251d13edd 100644
--- a/src/quick/scenegraph/coreapi/qsgrendererinterface.cpp
+++ b/src/quick/scenegraph/coreapi/qsgrendererinterface.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qsgrendererinterface.h"
@@ -76,11 +40,12 @@ QT_BEGIN_NAMESPACE
\value Unknown An unknown graphics API is in use
\value Software The Qt Quick 2D Renderer is in use
\value OpenVG OpenVG via EGL
- \value OpenGL OpenGL ES 2.0 or higher via a graphics abstraction layer. This value was introduced in Qt 5.14.
- \value Direct3D11 Direct3D 11 via a graphics abstraction layer. This value was introduced in Qt 5.14.
- \value Vulkan Vulkan 1.0 via a graphics abstraction layer. This value was introduced in Qt 5.14.
- \value Metal Metal via a graphics abstraction layer. This value was introduced in Qt 5.14.
- \value Null Null (no output) via a graphics abstraction layer. This value was introduced in Qt 5.14.
+ \value [since 5.14] OpenGL OpenGL ES 2.0 or higher via a graphics abstraction layer.
+ \value [since 5.14] Direct3D11 Direct3D 11 via a graphics abstraction layer.
+ \value [since 6.6] Direct3D12 Direct3D 12 via a graphics abstraction layer.
+ \value [since 5.14] Vulkan Vulkan 1.0 via a graphics abstraction layer.
+ \value [since 5.14] Metal Metal via a graphics abstraction layer.
+ \value [since 5.14] Null Null (no output) via a graphics abstraction layer.
\omitvalue OpenGLRhi
\omitvalue Direct3D11Rhi
\omitvalue VulkanRhi
@@ -113,52 +78,69 @@ QT_BEGIN_NAMESPACE
\value PainterResource The resource is a pointer to the active QPainter
used by the scenegraph, when running with the software backend.
- \value RhiResource The resource is a pointer to the QRhi instance used by
- the scenegraph, when applicable. This value was introduced in Qt 5.14.
+ \value [since 5.14] RhiResource The resource is a pointer to the QRhi instance used by
+ the scenegraph, when applicable.
- \value RhiSwapchainResource The resource is a pointer to a QRhiSwapchain
+ \value [since 6.0] RhiSwapchainResource The resource is a pointer to a QRhiSwapchain
instance that is associated with the window. The value is null when the
- window is used in combination with QQuickRenderControl. This value was
- introduced in Qt 6.0.
+ window is used in combination with QQuickRenderControl.
- \value RhiRedirectCommandBuffer The resource is a pointer to a
+ \value [since 6.0] RhiRedirectCommandBuffer The resource is a pointer to a
QRhiCommandBuffer instance that is associated with the window and its
QQuickRenderControl. The value is null when the window is not associated
- with a QQuickRenderControl. This value was introduced in Qt 6.0.
+ with a QQuickRenderControl.
- \value RhiRedirectRenderTarget The resource is a pointer to a
+ \value [since 6.0] RhiRedirectRenderTarget The resource is a pointer to a
QRhiTextureRenderTarget instance that is associated with the window and its
QQuickRenderControl. The value is null when the window is not associated
- with a QQuickRenderControl. This value was introduced in Qt 6.0.
+ with a QQuickRenderControl. Note that the value always reflects the main
+ texture render target and it does not depend on the Qt Quick scene, meaning
+ it does not take any additional texture-targeting render passes generated
+ by ShaderEffect or QQuickItem layers into account.
- \value PhysicalDeviceResource The resource is a pointer to the pysical
+ \value [since 5.14] PhysicalDeviceResource The resource is a pointer to the pysical
device object used by the scenegraph, when applicable. For example, a
\c{VkPhysicalDevice *}. Note that with Vulkan the returned value is a
- pointer to the VkPhysicalDevice, not the handle itself. This value was
- introduced in Qt 5.14.
+ pointer to the VkPhysicalDevice, not the handle itself.
- \value OpenGLContextResource The resource is a pointer to the
+ \value [since 5.14] OpenGLContextResource The resource is a pointer to the
QOpenGLContext used by the scenegraph (on the render thread), when
- applicable. This value was introduced in Qt 5.14.
+ applicable.
- \value DeviceContextResource The resource is a pointer to the device
+ \value [since 5.14] DeviceContextResource The resource is a pointer to the device
context used by the scenegraph, when applicable. For example, a
- \c{ID3D11DeviceContext *}. This value was introduced in Qt 5.14.
+ \c{ID3D11DeviceContext *}.
- \value CommandEncoderResource The resource is a pointer to the currently
+ \value [since 5.14] CommandEncoderResource The resource is a pointer to the currently
active render command encoder object used by the scenegraph, when
applicable. For example, a \c{MTLRenderCommandEncoder *}. This object has
limited validity, and is only valid while the scene graph is recording a
- render pass for the next frame. This value was introduced in Qt 5.14.
-
- \value VulkanInstanceResource The resource is a pointer to the
- QVulkanInstance used by the scenegraph, when applicable. This value was
- introduced in Qt 5.14.
-
- \value RenderPassResource The resource is a pointer to the render pass used
- by the scenegraph, describing the color and depth/stecil attachments and
- how they are used. For example, a \c{VkRenderPass *}. This value was
- introduced in Qt 5.14.
+ render pass for the next frame.
+
+ \value [since 5.14] VulkanInstanceResource The resource is a pointer to the
+ QVulkanInstance used by the scenegraph, when applicable.
+
+ \value [since 5.14] RenderPassResource The resource is a pointer to the main render pass
+ used by the scenegraph, describing the color and depth/stecil attachments
+ and how they are used. For example, a \c{VkRenderPass *}. Note that the
+ value always reflects the main render target (either the on-screen window
+ or the texture QQuickRenderControl redirects to) and it does not depend on
+ the Qt Quick scene, meaning it does not take any additional
+ texture-targeting render passes generated by ShaderEffect or QQuickItem
+ layers into account.
+
+ \value [since 6.4] RedirectPaintDevice The resource is a pointer to QPaintDevice instance
+ that is associated with the window and its QQuickRenderControl. The value is
+ null when the window is not associated with a QQuickRenderControl.
+
+ \value [since 6.6] GraphicsQueueFamilyIndexResource The resource is a pointer to the
+ graphics queue family index used by the scenegraph, when applicable. With
+ Vulkan, this is a pointer to a \c uint32_t index value.
+
+ \value [since 6.6] GraphicsQueueIndexResource The resource is a pointer to the graphics
+ queue index (uint32_t) used by the scenegraph, when applicable. With
+ Vulkan, this is a pointer to a \c uint32_t index value, which in practice
+ is the index of the VkQueue reported for \c CommandQueueResource.
*/
/*!
@@ -166,9 +148,8 @@ QT_BEGIN_NAMESPACE
\value UnknownShadingLanguage Not yet known due to no window and scenegraph associated
\value GLSL GLSL or GLSL ES
\value HLSL HLSL
- \value RhiShader Consumes QShader instances containing shader variants for
- multiple target languages and intermediate formats. This value was introduced in
- Qt 5.14.
+ \value [since 5.14] RhiShader Consumes QShader instances containing shader variants for
+ multiple target languages and intermediate formats.
*/
/*!
@@ -257,15 +238,12 @@ void *QSGRendererInterface::getResource(QQuickWindow *window, const char *resour
bool QSGRendererInterface::isApiRhiBased(GraphicsApi api)
{
switch (api) {
- case OpenGLRhi:
- Q_FALLTHROUGH();
- case Direct3D11Rhi:
- Q_FALLTHROUGH();
- case VulkanRhi:
- Q_FALLTHROUGH();
- case MetalRhi:
- Q_FALLTHROUGH();
- case NullRhi:
+ case OpenGL:
+ case Direct3D11:
+ case Direct3D12:
+ case Vulkan:
+ case Metal:
+ case Null:
return true;
default:
return false;
diff --git a/src/quick/scenegraph/coreapi/qsgrendererinterface.h b/src/quick/scenegraph/coreapi/qsgrendererinterface.h
index ec5172e569..d76bbed5cf 100644
--- a/src/quick/scenegraph/coreapi/qsgrendererinterface.h
+++ b/src/quick/scenegraph/coreapi/qsgrendererinterface.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSGRENDERERINTERFACE_H
#define QSGRENDERERINTERFACE_H
@@ -58,6 +22,7 @@ public:
Vulkan,
Metal,
Null,
+ Direct3D12,
OpenGLRhi = OpenGL,
Direct3D11Rhi = Direct3D11,
@@ -80,7 +45,10 @@ public:
DeviceContextResource,
CommandEncoderResource,
VulkanInstanceResource,
- RenderPassResource
+ RenderPassResource,
+ RedirectPaintDevice,
+ GraphicsQueueFamilyIndexResource,
+ GraphicsQueueIndexResource,
};
enum ShaderType {
diff --git a/src/quick/scenegraph/coreapi/qsgrendernode.cpp b/src/quick/scenegraph/coreapi/qsgrendernode.cpp
index ec8e3dda57..333d62d40b 100644
--- a/src/quick/scenegraph/coreapi/qsgrendernode.cpp
+++ b/src/quick/scenegraph/coreapi/qsgrendernode.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qsgrendernode.h"
#include "qsgrendernode_p.h"
@@ -48,6 +12,23 @@ QT_BEGIN_NAMESPACE
targeting the graphics API that is in use by the scenegraph.
\inmodule QtQuick
\since 5.8
+
+ QSGRenderNode allows creating scene graph nodes that perform their own
+ custom rendering via QRhi (the common approach from Qt 6.6 on), directly
+ via a 3D graphics API such as OpenGL, Vulkan, or Metal, or, when the \c
+ software backend is in use, via QPainter.
+
+ QSGRenderNode is the enabler for one of the three ways to integrate custom
+ 2D/3D rendering into a Qt Quick scene. The other two options are to perform
+ the rendering \c before or \c after the Qt Quick scene's own rendering,
+ or to generate a whole separate render pass targeting a dedicated render
+ target (a texture) and then have an item in the scene display the texture.
+ The QSGRenderNode-based approach is similar to the former, in the sense
+ that no additional render passes or render targets are involved, and allows
+ injecting custom rendering commands "inline" with the Qt Quick scene's
+ own rendering.
+
+ \sa {Scene Graph - Custom QSGRenderNode}
*/
QSGRenderNode::QSGRenderNode()
@@ -66,6 +47,13 @@ QSGRenderNode::QSGRenderNode()
deleted. Therefore there is no need to issue additional waits here, unless
the render() implementation is using additional command queues.
+ With QRhi and resources such as QRhiBuffer, QRhiTexture,
+ QRhiGraphicsPipeline, etc., it is often good practice to use smart
+ pointers, such as std::unique_ptr, which can often avoid the need to
+ implement a destructor, and lead to more compact source code. Keep in mind
+ however that implementing releaseResources(), most likely issuing a number
+ of reset() calls on the unique_ptrs, is still important.
+
\sa releaseResources()
*/
QSGRenderNode::~QSGRenderNode()
@@ -78,6 +66,7 @@ QSGRenderNodePrivate::QSGRenderNodePrivate()
, m_clip_list(nullptr)
, m_opacity(1)
{
+ m_projectionMatrix.resize(1);
}
/*!
@@ -85,17 +74,15 @@ QSGRenderNodePrivate::QSGRenderNodePrivate()
mask where each bit represents graphics states changed by the \l render()
function:
- \list
- \li DepthState - depth write mask, depth test enabled, depth comparison function
- \li StencilState - stencil write masks, stencil test enabled, stencil operations,
- stencil comparison functions
- \li ScissorState - scissor enabled, scissor test enabled
- \li ColorState - clear color, color write mask
- \li BlendState - blend enabled, blend function
- \li CullState - front face, cull face enabled
- \li ViewportState - viewport
- \li RenderTargetState - render target
- \endlist
+ \value DepthState depth write mask, depth test enabled, depth comparison function
+ \value StencilState stencil write masks, stencil test enabled, stencil operations,
+ stencil comparison functions
+ \value ScissorState scissor enabled, scissor test enabled
+ \value ColorState clear color, color write mask
+ \value BlendState blend enabled, blend function
+ \value CullState front face, cull face enabled
+ \value ViewportState viewport
+ \value RenderTargetState render target
With APIs other than OpenGL, the only relevant values are the ones that
correspond to dynamic state changes recorded on the command list/buffer.
@@ -109,16 +96,16 @@ QSGRenderNodePrivate::QSGRenderNodePrivate()
bindings, root signature, descriptor heaps, etc.) are always set again by
the scenegraph so render() can freely change them.
- \note RenderTargetState is no longer supported with APIs like Vulkan. This
+ RenderTargetState is no longer supported with APIs like Vulkan. This
is by nature. render() is invoked while the Qt Quick scenegraph's main
command buffer is recording a renderpass, so there is no possibility of
changing the target and starting another renderpass (on that command buffer
at least). Therefore returning a value with RenderTargetState set is not
sensible.
- The software backend exposes its QPainter and saves and restores before and
- after invoking render(). Therefore reporting any changed states from here
- is not necessary.
+ \note The \c software backend exposes its QPainter and saves and restores
+ before and after invoking render(). Therefore reporting any changed states
+ from here is not necessary.
The function is called by the renderer so it can reset the states after
rendering this node. This makes the implementation of render() simpler
@@ -128,6 +115,10 @@ QSGRenderNodePrivate::QSGRenderNodePrivate()
in render().
\note This function may be called before render().
+
+ \note With Qt 6 and QRhi-based rendering the only relevant values are
+ ViewportState and ScissorState. Other values can be returned but are
+ ignored in practice.
*/
QSGRenderNode::StateFlags QSGRenderNode::changedStates() const
{
@@ -146,6 +137,12 @@ QSGRenderNode::StateFlags QSGRenderNode::changedStates() const
The default implementation is empty.
+ When implementing a QSGRenderNode that uses QRhi to render, query the QRhi
+ object from the QQuickWindow via \l{QQuickWindow::rhi()}. To get a
+ QRhiCommandBuffer for submitting work to, call commandBuffer(). To query
+ information about the active render target, call renderTarget(). See the
+ \l{{Scene Graph - Custom QSGRenderNode}} example for details.
+
\since 6.0
*/
void QSGRenderNode::prepare()
@@ -196,56 +193,33 @@ void QSGRenderNode::prepare()
Some scenegraph backends, software in particular, use no scissor or
stencil. There the clip region is provided as an ordinary QRegion.
- With the legacy, direct OpenGL based renderer, the following states are set
- on the render thread's context before this function is called:
-
- \list
- \li glColorMask(true, true, true, true)
- \li glDepthMask(false)
- \li glDisable(GL_DEPTH_TEST)
- \li glStencilFunc(GL_EQUAL, state.stencilValue, 0xff); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP) depending on clip
- \li glScissor(state.scissorRect.x(), state.scissorRect.y(),
- state.scissorRect.width(), state.scissorRect.height()) depending on clip
- \li glEnable(GL_BLEND)
- \li glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)
- \li glDisable(GL_CULL_FACE)
- \endlist
-
- States that are not listed above, but are covered by \l StateFlags, can
- have arbitrary values.
-
- \note There is no state set with other graphics APIs, considering that many
- of them do not have a concept of the traditional OpenGL state machine.
- Rather, it is up to the implementation to create pipeline state objects
- with the desired blending, scissor, and stencil tests enabled. Note that
- this also includes OpenGL via the RHI. New QSGRenderNode implementations
- are recommended to set all scissor, stencil and blend state explicitly (as
- shown in the above list), even if they are targeting OpenGL.
-
- \l changedStates() should return which states this function changes. If a
- state is not covered by \l StateFlags, the state should be set to the
- default value according to the OpenGL specification. For other APIs, see
- the documentation for changedStates() for more information.
-
- \note Depth writes are disabled when this function is called
- (glDepthMask(false) with OpenGL). Enabling depth writes can lead to
- unexpected results, depending on the scenegraph backend in use and the
- content in the scene, so exercise caution with this.
-
- For APIs other than OpenGL, it will likely be necessary to query certain
- API-specific resources (for example, the graphics device or the command
- list/buffer to add the commands to). This is done via QSGRendererInterface.
-
- Assume nothing about the pipelines and dynamic states bound on the command
- list/buffer when this function is called.
-
- With some graphics APIs it can be necessary to also connect to the
- QQuickWindow::beforeRendering() signal, because that is emitted before
+ When implementing a QSGRenderNode that uses QRhi to render, query the QRhi
+ object from the QQuickWindow via \l{QQuickWindow::rhi()}. To get a
+ QRhiCommandBuffer for submitting work to, call commandBuffer(). To query
+ information about the active render target, call renderTarget(). See the
+ \l{{Scene Graph - Custom QSGRenderNode}} example for details.
+
+ With Qt 6 and its QRhi-based scene graph renderer, no assumptions should be
+ made about the active (OpenGL) state when this function is called, even
+ when OpenGL is in use. Assume nothing about the pipelines and dynamic
+ states bound on the command list/buffer when this function is called.
+
+ \note Depth writes are expected to be disabled. Enabling depth writes can
+ lead to unexpected results, depending on the scenegraph backend in use and
+ the content in the scene, so exercise caution with this.
+
+ \note In Qt 6, \l changedStates() has limited use. See the documentation
+ for changedStates() for more information.
+
+ With some graphics APIs, including when using QRhi directly, it can be
+ necessary to reimplement prepare() in addition, or alternatively connect to
+ the QQuickWindow::beforeRendering() signal. These are called/emitted before
recording the beginning of a renderpass on the command buffer
(vkCmdBeginRenderPass with Vulkan, or starting to encode via
- MTLRenderCommandEncoder in case of Metal). Recording copy operations cannot
- be done inside render() with such APIs. Rather, do it in the slot connected
- (with DirectConnection) to the beforeRendering signal.
+ MTLRenderCommandEncoder in case of Metal. Recording copy operations cannot
+ be done inside render() with such APIs. Rather, do such operations either
+ in prepare() or the slot connected to beforeRendering (with
+ DirectConnection).
\sa QSGRendererInterface, QQuickWindow::rendererInterface()
*/
@@ -298,7 +272,7 @@ void QSGRenderNode::releaseResources()
\value BoundedRectRendering Indicates that the implementation of render()
does not render outside the area reported from rect() in item
coordinates. Such node implementations can lead to more efficient rendering,
- depending on the scenegraph backend. For example, the software backend can
+ depending on the scenegraph backend. For example, the \c software backend can
continue to use the more optimal partial update path when all render nodes
in the scene have this flag set.
@@ -317,9 +291,11 @@ void QSGRenderNode::releaseResources()
transparent pixels. Setting this flag can improve performance in some
cases.
- \omitvalue NoExternalRendering
+ \value NoExternalRendering Indicates that the implementation of prepare()
+ and render() use the QRhi family of APIs, instead of directly calling a 3D
+ API such as OpenGL, Vulkan, or Metal.
- \sa render(), rect()
+ \sa render(), prepare(), rect(), QRhi
*/
/*!
@@ -359,6 +335,35 @@ QRectF QSGRenderNode::rect() const
}
/*!
+ \return pointer to the current projection matrix.
+
+ In render() this is the same matrix that is returned from
+ RenderState::projectionMatrix(). This getter exists so that prepare() also
+ has a way to query the projection matrix.
+
+ When working with a modern graphics API, or Qt's own graphics abstraction
+ layer, it is more than likely that one will want to load
+ \c{*projectionMatrix() * *matrix()} into a uniform buffer. That is however
+ something that needs to be done in prepare(), so outside the recording of a
+ render pass. That is why both matrices are queriable directly from the
+ QSGRenderNode, both in prepare() and render().
+
+ \since 6.5
+ */
+const QMatrix4x4 *QSGRenderNode::projectionMatrix() const
+{
+ return &d->m_projectionMatrix[0];
+}
+
+/*!
+ \internal
+ */
+const QMatrix4x4 *QSGRenderNode::projectionMatrix(int index) const
+{
+ return &d->m_projectionMatrix[index];
+}
+
+/*!
\return pointer to the current model-view matrix.
*/
const QMatrix4x4 *QSGRenderNode::matrix() const
@@ -382,6 +387,59 @@ qreal QSGRenderNode::inheritedOpacity() const
return d->m_opacity;
}
+/*!
+ \return the current render target.
+
+ This is provided mainly to enable prepare() and render() implementations
+ that use QRhi accessing the QRhiRenderTarget's
+ \l{QRhiRenderPassDescriptor}{renderPassDescriptor} or
+ \l{QRhiRenderTarget::pixelSize()}{pixel size}.
+
+ To build a QRhiGraphicsPipeline, which implies having to provide a
+ QRhiRenderPassDescriptor, query the renderPassDescriptor from the render
+ target. Be aware however that the render target may change over the
+ lifetime of the custom QQuickItem and the QSGRenderNode. For example,
+ consider what happens when dynamically setting \c{layer.enabled: true} on
+ the item or an ancestor of it: this triggers rendering into a texture, not
+ directly to the window, which means the QSGRenderNode is going to work with
+ a different render target from then on. The new render target may then have
+ a different pixel format, which can make already built graphics pipelines
+ incompatible. This can be handled with logic such as the following:
+
+ \code
+ if (m_pipeline && renderTarget()->renderPassDescriptor()->serializedFormat() != m_renderPassFormat) {
+ delete m_pipeline;
+ m_pipeline = nullptr;
+ }
+ if (!m_pipeline) {
+ // Build a new QRhiGraphicsPipeline.
+ // ...
+ // Store the serialized format for fast and simple comparisons later on.
+ m_renderPassFormat = renderTarget()->renderPassDescriptor()->serializedFormat();
+ }
+ \endcode
+
+ \since 6.6
+
+ \sa commandBuffer()
+ */
+QRhiRenderTarget *QSGRenderNode::renderTarget() const
+{
+ return d->m_rt.rt;
+}
+
+/*!
+ \return the current command buffer.
+
+ \since 6.6
+
+ \sa renderTarget()
+ */
+QRhiCommandBuffer *QSGRenderNode::commandBuffer() const
+{
+ return d->m_rt.cb;
+}
+
QSGRenderNode::RenderState::~RenderState()
{
}
@@ -435,7 +493,7 @@ QSGRenderNode::RenderState::~RenderState()
\return the current clip region or null for backends where clipping is
implemented via stencil or scissoring.
- The software backend uses no projection, scissor or stencil, meaning most
+ The \c software backend uses no projection, scissor or stencil, meaning most
of the render state is not in use. However, the clip region that can be set
on the QPainter still has to be communicated since reconstructing this
manually in render() is not reasonable. It can therefore be queried via
diff --git a/src/quick/scenegraph/coreapi/qsgrendernode.h b/src/quick/scenegraph/coreapi/qsgrendernode.h
index 2a5a5ce106..927a8dee59 100644
--- a/src/quick/scenegraph/coreapi/qsgrendernode.h
+++ b/src/quick/scenegraph/coreapi/qsgrendernode.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSGRENDERNODE_H
#define QSGRENDERNODE_H
@@ -45,6 +9,8 @@
QT_BEGIN_NAMESPACE
class QSGRenderNodePrivate;
+class QRhiRenderTarget;
+class QRhiCommandBuffer;
class Q_QUICK_EXPORT QSGRenderNode : public QSGNode
{
@@ -90,9 +56,13 @@ public:
virtual RenderingFlags flags() const;
virtual QRectF rect() const;
+ const QMatrix4x4 *projectionMatrix() const;
+ const QMatrix4x4 *projectionMatrix(int index) const;
const QMatrix4x4 *matrix() const;
const QSGClipNode *clipList() const;
qreal inheritedOpacity() const;
+ QRhiRenderTarget *renderTarget() const;
+ QRhiCommandBuffer *commandBuffer() const;
private:
QSGRenderNodePrivate *d;
diff --git a/src/quick/scenegraph/coreapi/qsgrendernode_p.h b/src/quick/scenegraph/coreapi/qsgrendernode_p.h
index ca38f344ef..8bdd457b95 100644
--- a/src/quick/scenegraph/coreapi/qsgrendernode_p.h
+++ b/src/quick/scenegraph/coreapi/qsgrendernode_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSGRENDERNODE_P_H
#define QSGRENDERNODE_P_H
@@ -52,12 +16,12 @@
//
#include <QtQuick/private/qtquickglobal_p.h>
-#include <QtQuick/qsgnode.h>
#include <QtQuick/qsgrendernode.h>
+#include <QtQuick/private/qsgrenderer_p.h>
QT_BEGIN_NAMESPACE
-class Q_QUICK_PRIVATE_EXPORT QSGRenderNodePrivate
+class Q_QUICK_EXPORT QSGRenderNodePrivate
{
public:
QSGRenderNodePrivate();
@@ -67,6 +31,9 @@ public:
const QMatrix4x4 *m_matrix;
const QSGClipNode *m_clip_list;
qreal m_opacity;
+ QSGRenderTarget m_rt;
+ QVarLengthArray<QMatrix4x4, 1> m_projectionMatrix;
+ QMatrix4x4 m_localMatrix; // ### Qt 7 m_matrix should not be a pointer
};
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/coreapi/qsgrhivisualizer.cpp b/src/quick/scenegraph/coreapi/qsgrhivisualizer.cpp
index 3c83f3aa4b..d1f4e46ed0 100644
--- a/src/quick/scenegraph/coreapi/qsgrhivisualizer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgrhivisualizer.cpp
@@ -1,43 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Copyright (C) 2016 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
-** Copyright (C) 2016 Robin Burchell <robin.burchell@viroteck.net>
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// Copyright (C) 2016 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
+// Copyright (C) 2016 Robin Burchell <robin.burchell@viroteck.net>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qsgrhivisualizer_p.h"
#include <qmath.h>
@@ -98,7 +62,7 @@ void RhiVisualizer::prepareVisualize()
QLatin1String(":/qt-project.org/scenegraph/shaders_ng/visualization.frag.qsb"));
}
- m_fade.prepare(this, m_renderer->m_rhi, m_renderer->m_resourceUpdates, m_renderer->renderPassDescriptor());
+ m_fade.prepare(this, m_renderer->m_rhi, m_renderer->m_resourceUpdates, m_renderer->renderTarget().rpDesc);
const bool forceUintIndex = m_renderer->m_uint32IndexForRhi;
@@ -135,7 +99,7 @@ void RhiVisualizer::visualize()
if (m_visualizeMode == VisualizeNothing)
return;
- QRhiCommandBuffer *cb = m_renderer->commandBuffer();
+ QRhiCommandBuffer *cb = m_renderer->renderTarget().cb;
m_fade.render(cb);
switch (m_visualizeMode) {
@@ -163,7 +127,7 @@ void RhiVisualizer::recordDrawCalls(const QVector<DrawCall> &drawCalls,
bool blendOneOne)
{
for (const DrawCall &dc : drawCalls) {
- QRhiGraphicsPipeline *ps = m_pipelines.pipeline(this, m_renderer->m_rhi, srb, m_renderer->renderPassDescriptor(),
+ QRhiGraphicsPipeline *ps = m_pipelines.pipeline(this, m_renderer->m_rhi, srb, m_renderer->renderTarget().rpDesc,
dc.vertex.topology, dc.vertex.format, dc.vertex.stride,
blendOneOne);
if (!ps)
@@ -288,7 +252,7 @@ static inline uint aligned(uint v, uint byteAlign)
return (v + byteAlign - 1) & ~(byteAlign - 1);
}
-static bool ensureBuffer(QRhi *rhi, QRhiBuffer **buf, QRhiBuffer::UsageFlags usage, int newSize)
+static bool ensureBuffer(QRhi *rhi, QRhiBuffer **buf, QRhiBuffer::UsageFlags usage, quint32 newSize)
{
if (!*buf) {
*buf = rhi->newBuffer(QRhiBuffer::Dynamic, usage, newSize);
@@ -311,7 +275,7 @@ QRhiGraphicsPipeline *RhiVisualizer::PipelineCache::pipeline(RhiVisualizer *visu
quint32 vertexStride,
bool blendOneOne)
{
- for (int i = 0, ie = pipelines.count(); i != ie; ++i) {
+ for (int i = 0, ie = pipelines.size(); i != ie; ++i) {
const Pipeline &p(pipelines.at(i));
if (p.topology == topology && p.format == vertexFormat && p.stride == vertexStride)
return p.ps;
@@ -352,7 +316,7 @@ QRhiGraphicsPipeline *RhiVisualizer::PipelineCache::pipeline(RhiVisualizer *visu
void RhiVisualizer::PipelineCache::releaseResources()
{
- for (int i = 0, ie = pipelines.count(); i != ie; ++i)
+ for (int i = 0, ie = pipelines.size(); i != ie; ++i)
delete pipelines.at(i).ps;
pipelines.clear();
@@ -363,10 +327,10 @@ void RhiVisualizer::ChangeVis::gather(Node *n)
if (n->type() == QSGNode::GeometryNodeType && n->element()->batch && visualizer->m_visualizeChangeSet.contains(n)) {
const uint dirty = visualizer->m_visualizeChangeSet.value(n);
const bool tinted = (dirty & QSGNODE_DIRTY_PARENT) != 0;
- const QColor color = QColor::fromHsvF((rand() & 1023) / 1023.0f, 0.3f, 1.0f);
+ const QColor color = QColor::fromHsvF((visualizer->m_randomGenerator.generate() & 1023) / 1023.0f, 0.3f, 1.0f).toRgb();
const float alpha = 0.5f;
- QMatrix4x4 matrix = visualizer->m_renderer->m_current_projection_matrix;
+ QMatrix4x4 matrix = visualizer->m_renderer->m_current_projection_matrix[0];
if (n->element()->batch->root)
matrix = matrix * qsg_matrixForRoot(n->element()->batch->root);
@@ -481,7 +445,7 @@ void RhiVisualizer::BatchVis::gather(Batch *b)
if (b->positionAttribute != 0)
return;
- QMatrix4x4 matrix(visualizer->m_renderer->m_current_projection_matrix);
+ QMatrix4x4 matrix(visualizer->m_renderer->m_current_projection_matrix[0]);
if (b->root)
matrix = matrix * qsg_matrixForRoot(b->root);
@@ -490,7 +454,7 @@ void RhiVisualizer::BatchVis::gather(Batch *b)
QMatrix4x4 rotation;
memcpy(dc.uniforms.data + 64, rotation.constData(), 64);
- QColor color = QColor::fromHsvF((rand() & 1023) / 1023.0, 1.0, 1.0);
+ const QColor color = QColor::fromHsvF((visualizer->m_randomGenerator.generate() & 1023) / 1023.0, 1.0, 1.0).toRgb();
float c[4] = {
float(color.redF()),
@@ -564,7 +528,6 @@ void RhiVisualizer::BatchVis::prepare(const QDataBuffer<Batch *> &opaqueBatches,
drawCalls.clear();
- srand(0); // To force random colors to be roughly the same every time..
for (int i = 0; i < opaqueBatches.size(); ++i)
gather(opaqueBatches.at(i));
for (int i = 0; i < alphaBatches.size(); ++i)
@@ -612,7 +575,7 @@ void RhiVisualizer::ClipVis::gather(QSGNode *node)
{
if (node->type() == QSGNode::ClipNodeType) {
QSGClipNode *clipNode = static_cast<QSGClipNode *>(node);
- QMatrix4x4 matrix = visualizer->m_renderer->m_current_projection_matrix;
+ QMatrix4x4 matrix = visualizer->m_renderer->m_current_projection_matrix[0];
if (clipNode->matrix())
matrix = matrix * *clipNode->matrix();
@@ -711,7 +674,7 @@ void RhiVisualizer::ClipVis::render(QRhiCommandBuffer *cb)
void RhiVisualizer::OverdrawVis::gather(Node *n)
{
if (n->type() == QSGNode::GeometryNodeType && n->element()->batch) {
- QMatrix4x4 matrix = visualizer->m_renderer->m_current_projection_matrix;
+ QMatrix4x4 matrix = visualizer->m_renderer->m_current_projection_matrix[0];
matrix(2, 2) = visualizer->m_renderer->m_zRange;
matrix(2, 3) = 1.0f - n->element()->order * visualizer->m_renderer->m_zRange;
@@ -837,7 +800,7 @@ void RhiVisualizer::OverdrawVis::prepare(Node *n, RhiVisualizer *visualizer,
inputLayout.setAttributes({ { 0, 0, QRhiVertexInputAttribute::Float3, 0 } });
box.ps->setVertexInputLayout(inputLayout);
box.ps->setShaderResourceBindings(box.srb);
- box.ps->setRenderPassDescriptor(visualizer->m_renderer->renderPassDescriptor());
+ box.ps->setRenderPassDescriptor(visualizer->m_renderer->renderTarget().rpDesc);
if (!box.ps->create())
return;
}
diff --git a/src/quick/scenegraph/coreapi/qsgrhivisualizer_p.h b/src/quick/scenegraph/coreapi/qsgrhivisualizer_p.h
index 1ce52a81f1..1ed37d87bc 100644
--- a/src/quick/scenegraph/coreapi/qsgrhivisualizer_p.h
+++ b/src/quick/scenegraph/coreapi/qsgrhivisualizer_p.h
@@ -1,43 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
-** Copyright (C) 2016 Robin Burchell <robin.burchell@viroteck.net>
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2016 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
+// Copyright (C) 2016 Robin Burchell <robin.burchell@viroteck.net>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSGRHIVISUALIZER_P_H
#define QSGRHIVISUALIZER_P_H
@@ -55,6 +19,8 @@
#include "qsgbatchrenderer_p.h"
+#include <QtCore/qrandom.h>
+
QT_BEGIN_NAMESPACE
namespace QSGBatchRenderer
@@ -219,6 +185,8 @@ private:
} box;
} m_overdrawVis;
+ QRandomGenerator m_randomGenerator;
+
friend class Fade;
friend class PipelineCache;
friend class ChangeVis;
diff --git a/src/quick/scenegraph/coreapi/qsgtexture.cpp b/src/quick/scenegraph/coreapi/qsgtexture.cpp
index f09ff9ad85..57111e9e5f 100644
--- a/src/quick/scenegraph/coreapi/qsgtexture.cpp
+++ b/src/quick/scenegraph/coreapi/qsgtexture.cpp
@@ -1,49 +1,15 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 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$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qsgtexture_p.h"
#include "qsgtexture_platform.h"
#include <private/qqmlglobal_p.h>
#include <private/qsgmaterialshader_p.h>
+#include <private/qsgrenderer_p.h>
#include <private/qquickitem_p.h> // qquickwindow_p.h cannot be included on its own due to template nonsense
#include <private/qquickwindow_p.h>
-#include <QtGui/private/qrhi_p.h>
+#include <QtCore/private/qnativeinterface_p.h>
+#include <rhi/qrhi.h>
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID) && defined(__GLIBC__)
#define CAN_BACKTRACE_EXECINFO
@@ -65,11 +31,12 @@
#ifndef QT_NO_DEBUG
Q_GLOBAL_STATIC(QSet<QSGTexture *>, qsg_valid_texture_set)
Q_GLOBAL_STATIC(QMutex, qsg_valid_texture_mutex)
-static const bool qsg_leak_check = !qEnvironmentVariableIsEmpty("QML_LEAK_CHECK");
#endif
QT_BEGIN_NAMESPACE
+Q_DECLARE_LOGGING_CATEGORY(lcQsgLeak)
+
bool operator==(const QSGSamplerDescription &a, const QSGSamplerDescription &b) noexcept
{
return a.filtering == b.filtering
@@ -118,8 +85,9 @@ QSGTexturePrivate::QSGTexturePrivate(QSGTexture *t)
#endif
#ifdef Q_OS_WIN
, m_d3d11TextureAccessor(t)
+ , m_d3d12TextureAccessor(t)
#endif
-#if defined(__OBJC__)
+#if QT_CONFIG(metal)
, m_metalTextureAccessor(t)
#endif
#if QT_CONFIG(vulkan)
@@ -151,7 +119,7 @@ static QHash<QSGTexture*, SGTextureTraceItem*> qt_debug_allocated_textures;
inline static void qt_debug_print_texture_count()
{
- qDebug("Number of leaked textures: %i", qt_debug_texture_count);
+ qCDebug(lcQsgLeak, "Number of leaked textures: %i", qt_debug_texture_count);
qt_debug_texture_count = -1;
#if defined(CAN_BACKTRACE_EXECINFO)
@@ -278,8 +246,6 @@ static void qt_debug_remove_texture(QSGTexture* texture)
\note All classes with QSG prefix should be used solely on the scene graph's
rendering thread. See \l {Scene Graph and Rendering} for more information.
-
- \sa {Scene Graph - Rendering FBOs}
*/
/*!
@@ -339,7 +305,7 @@ QSGTexture::QSGTexture()
: QObject(*(new QSGTexturePrivate(this)))
{
#ifndef QT_NO_DEBUG
- if (qsg_leak_check)
+ if (lcQsgLeak().isDebugEnabled())
qt_debug_add_texture(this);
QMutexLocker locker(qsg_valid_texture_mutex());
@@ -354,7 +320,7 @@ QSGTexture::QSGTexture(QSGTexturePrivate &dd)
: QObject(dd)
{
#ifndef QT_NO_DEBUG
- if (qsg_leak_check)
+ if (lcQsgLeak().isDebugEnabled())
qt_debug_add_texture(this);
QMutexLocker locker(qsg_valid_texture_mutex());
@@ -368,7 +334,7 @@ QSGTexture::QSGTexture(QSGTexturePrivate &dd)
QSGTexture::~QSGTexture()
{
#ifndef QT_NO_DEBUG
- if (qsg_leak_check)
+ if (lcQsgLeak().isDebugEnabled())
qt_debug_remove_texture(this);
QMutexLocker locker(qsg_valid_texture_mutex());
@@ -455,7 +421,7 @@ bool QSGTexture::isAtlasTexture() const
/*!
\fn QSize QSGTexture::textureSize() const
- Returns the size of the texture.
+ Returns the size of the texture in pixels.
*/
/*!
@@ -615,8 +581,6 @@ QSGTexture::WrapMode QSGTexture::verticalWrapMode() const
\warning This function can only be called from the rendering thread.
\since 6.0
-
- \internal
*/
QRhiTexture *QSGTexture::rhiTexture() const
{
@@ -637,8 +601,6 @@ QRhiTexture *QSGTexture::rhiTexture() const
\warning This function can only be called from the rendering thread.
\since 6.0
-
- \internal
*/
void QSGTexture::commitTextureOperations(QRhi *rhi, QRhiResourceUpdateBatch *resourceUpdates)
{
@@ -692,6 +654,12 @@ QSGDynamicTexture::QSGDynamicTexture(QSGTexturePrivate &dd)
}
/*!
+ \internal
+ */
+QSGDynamicTexture::~QSGDynamicTexture()
+ = default;
+
+/*!
\fn template <typename QNativeInterface> NativeInterface *QSGTexture::nativeInterface() const
Returns a native interface of the given type for the texture.
@@ -708,13 +676,14 @@ QSGDynamicTexture::QSGDynamicTexture(QSGTexturePrivate &dd)
*/
-#if QT_CONFIG(opengl) || defined(Q_CLANG_QDOC)
+#if QT_CONFIG(opengl) || defined(Q_QDOC)
namespace QNativeInterface {
/*!
\class QNativeInterface::QSGOpenGLTexture
\inmodule QtQuick
\ingroup native-interfaces
\ingroup native-interfaces-qsgtexture
+ \inheaderfile QSGTexture
\brief Provides access to and enables adopting OpenGL texture objects.
\since 6.0
*/
@@ -761,7 +730,7 @@ QSGTexture *QSGOpenGLTexture::fromNative(GLuint textureId,
}
/*!
- Creates a new QSGTexture wrapping an existing OpenGL texture object for
+ Creates a new QSGTexture wrapping an existing OpenGL ES texture object for
\a window.
The native object specified in \a textureId is wrapped, but not owned, by
@@ -770,7 +739,8 @@ QSGTexture *QSGOpenGLTexture::fromNative(GLuint textureId,
native object.
This function is suitable only for textures that are meant to be
- used with the \c{GL_TEXTURE_EXTERNAL_OES} target.
+ used with the \c{GL_TEXTURE_EXTERNAL_OES} target: usually textures
+ to which another device (such as a camera) writes data.
\warning This function will return null if the scenegraph has not yet been
initialized.
@@ -805,22 +775,16 @@ GLuint QSGTexturePlatformOpenGL::nativeTexture() const
return GLuint(tex->nativeTexture().object);
return 0;
}
-
-template<> Q_QUICK_EXPORT
-QNativeInterface::QSGOpenGLTexture *QSGTexture::nativeInterface<QNativeInterface::QSGOpenGLTexture>() const
-{
- Q_D(const QSGTexture);
- return &const_cast<QSGTexturePrivate*>(d)->m_openglTextureAccessor;
-}
#endif // opengl
-#if defined(Q_OS_WIN) || defined(Q_CLANG_QDOC)
+#if defined(Q_OS_WIN) || defined(Q_QDOC)
namespace QNativeInterface {
/*!
\class QNativeInterface::QSGD3D11Texture
\inmodule QtQuick
\ingroup native-interfaces
\ingroup native-interfaces-qsgtexture
+ \inheaderfile QSGTexture
\brief Provides access to and enables adopting Direct3D 11 texture objects.
\since 6.0
*/
@@ -873,21 +837,87 @@ void *QSGTexturePlatformD3D11::nativeTexture() const
return 0;
}
-template<> Q_QUICK_EXPORT
-QNativeInterface::QSGD3D11Texture *QSGTexture::nativeInterface<QNativeInterface::QSGD3D11Texture>() const
+namespace QNativeInterface {
+/*!
+ \class QNativeInterface::QSGD3D12Texture
+ \inmodule QtQuick
+ \ingroup native-interfaces
+ \ingroup native-interfaces-qsgtexture
+ \inheaderfile QSGTexture
+ \brief Provides access to and enables adopting Direct3D 12 texture objects.
+ \since 6.6
+*/
+
+/*!
+ \fn void *QNativeInterface::QSGD3D12Texture::nativeTexture() const
+ \return the ID3D12Texture object.
+ */
+
+QT_DEFINE_NATIVE_INTERFACE(QSGD3D12Texture);
+
+/*!
+ Creates a new QSGTexture wrapping an existing Direct 3D 12 \a texture object
+ for \a window.
+
+ The native object is wrapped, but not owned, by the resulting QSGTexture.
+ The caller of the function is responsible for deleting the returned
+ QSGTexture, but that will not destroy the underlying native object.
+
+ This function is currently suitable for 2D RGBA textures only.
+
+ \warning This function will return null if the scene graph has not yet been
+ initialized.
+
+ Use \a options to customize the texture attributes. Only the
+ TextureHasAlphaChannel and TextureHasMipmaps are taken into account here.
+
+ \a size specifies the size in pixels.
+
+ \a resourceState must specify the
+ \l{https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_resource_states}{current state}
+ of the texture resource.
+
+ \note This function must be called on the scene graph rendering thread.
+
+ \sa QQuickWindow::sceneGraphInitialized(), QSGTexture,
+ {Scene Graph - Metal Texture Import}, {Scene Graph - Vulkan Texture Import}
+
+ \since 6.6
+ */
+QSGTexture *QSGD3D12Texture::fromNative(void *texture,
+ int resourceState,
+ QQuickWindow *window,
+ const QSize &size,
+ QQuickWindow::CreateTextureOptions options)
+{
+ return QQuickWindowPrivate::get(window)->createTextureFromNativeTexture(quint64(texture), resourceState, size, options);
+}
+} // QNativeInterface
+
+int QSGTexturePlatformD3D12::nativeResourceState() const
+{
+ if (auto *tex = m_texture->rhiTexture())
+ return tex->nativeTexture().layout;
+ return 0;
+}
+
+void *QSGTexturePlatformD3D12::nativeTexture() const
{
- Q_D(const QSGTexture);
- return &const_cast<QSGTexturePrivate*>(d)->m_d3d11TextureAccessor;
+ if (auto *tex = m_texture->rhiTexture())
+ return reinterpret_cast<void *>(quintptr(tex->nativeTexture().object));
+ return 0;
}
+
#endif // win
-#if defined(__OBJC__) || defined(Q_CLANG_QDOC)
+#if defined(__OBJC__) || defined(Q_QDOC)
namespace QNativeInterface {
/*!
\class QNativeInterface::QSGMetalTexture
\inmodule QtQuick
\ingroup native-interfaces
\ingroup native-interfaces-qsgtexture
+ \inheaderfile QSGTexture
\brief Provides access to and enables adopting Metal texture objects.
\since 6.0
*/
@@ -926,22 +956,16 @@ namespace QNativeInterface {
*/
} // QNativeInterface
+#endif // OBJC
-template<> Q_QUICK_EXPORT
-QNativeInterface::QSGMetalTexture *QSGTexture::nativeInterface<QNativeInterface::QSGMetalTexture>() const
-{
- Q_D(const QSGTexture);
- return &const_cast<QSGTexturePrivate*>(d)->m_metalTextureAccessor;
-}
-#endif // win
-
-#if QT_CONFIG(vulkan) || defined(Q_CLANG_QDOC)
+#if QT_CONFIG(vulkan) || defined(Q_QDOC)
namespace QNativeInterface {
/*!
\class QNativeInterface::QSGVulkanTexture
\inmodule QtQuick
\ingroup native-interfaces
\ingroup native-interfaces-qsgtexture
+ \inheaderfile QSGTexture
\brief Provides access to and enables adopting Vulkan image objects.
\since 6.0
*/
@@ -1008,14 +1032,34 @@ VkImageLayout QSGTexturePlatformVulkan::nativeImageLayout() const
return VkImageLayout(tex->nativeTexture().layout);
return VK_IMAGE_LAYOUT_UNDEFINED;
}
+#endif // vulkan
-template<> Q_QUICK_EXPORT
-QNativeInterface::QSGVulkanTexture *QSGTexture::nativeInterface<QNativeInterface::QSGVulkanTexture>() const
+void *QSGTexture::resolveInterface(const char *name, int revision) const
{
+ using namespace QNativeInterface;
+ Q_UNUSED(name);
+ Q_UNUSED(revision);
+
Q_D(const QSGTexture);
- return &const_cast<QSGTexturePrivate*>(d)->m_vulkanTextureAccessor;
+ auto *dd = const_cast<QSGTexturePrivate *>(d);
+ Q_UNUSED(dd);
+
+#if QT_CONFIG(vulkan)
+ QT_NATIVE_INTERFACE_RETURN_IF(QSGVulkanTexture, &dd->m_vulkanTextureAccessor);
+#endif
+#if QT_CONFIG(metal)
+ QT_NATIVE_INTERFACE_RETURN_IF(QSGMetalTexture, &dd->m_metalTextureAccessor);
+#endif
+#if defined(Q_OS_WIN)
+ QT_NATIVE_INTERFACE_RETURN_IF(QSGD3D11Texture, &dd->m_d3d11TextureAccessor);
+ QT_NATIVE_INTERFACE_RETURN_IF(QSGD3D12Texture, &dd->m_d3d12TextureAccessor);
+#endif
+#if QT_CONFIG(opengl)
+ QT_NATIVE_INTERFACE_RETURN_IF(QSGOpenGLTexture, &dd->m_openglTextureAccessor);
+#endif
+
+ return nullptr;
}
-#endif // vulkan
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/coreapi/qsgtexture.h b/src/quick/scenegraph/coreapi/qsgtexture.h
index 5492b04e11..fec3baa3f3 100644
--- a/src/quick/scenegraph/coreapi/qsgtexture.h
+++ b/src/quick/scenegraph/coreapi/qsgtexture.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 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$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSGTEXTURE_H
#define QSGTEXTURE_H
@@ -112,7 +76,7 @@ public:
inline QRectF convertToNormalizedSourceRect(const QRectF &rect) const;
- QT_DECLARE_NATIVE_INTERFACE_ACCESSOR
+ QT_DECLARE_NATIVE_INTERFACE_ACCESSOR(QSGTexture)
protected:
QSGTexture(QSGTexturePrivate &dd);
@@ -138,6 +102,8 @@ class Q_QUICK_EXPORT QSGDynamicTexture : public QSGTexture
public:
QSGDynamicTexture() = default;
+ ~QSGDynamicTexture() override;
+
virtual bool updateTexture() = 0;
protected:
diff --git a/src/quick/scenegraph/coreapi/qsgtexture_mac.mm b/src/quick/scenegraph/coreapi/qsgtexture_mac.mm
index 9d009eb5cb..c68a1b732f 100644
--- a/src/quick/scenegraph/coreapi/qsgtexture_mac.mm
+++ b/src/quick/scenegraph/coreapi/qsgtexture_mac.mm
@@ -1,47 +1,12 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qsgtexture_p.h"
#include "qsgtexture_platform.h"
#include <private/qquickitem_p.h>
#include <private/qquickwindow_p.h>
-#include <QtGui/private/qrhi_p.h>
+#include <QtCore/private/qnativeinterface_p.h>
+#include <rhi/qrhi.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick/scenegraph/coreapi/qsgtexture_p.h b/src/quick/scenegraph/coreapi/qsgtexture_p.h
index 740dc1f3ac..178bd23265 100644
--- a/src/quick/scenegraph/coreapi/qsgtexture_p.h
+++ b/src/quick/scenegraph/coreapi/qsgtexture_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSGTEXTURE_P_H
#define QSGTEXTURE_P_H
@@ -75,7 +39,7 @@ bool operator!=(const QSGSamplerDescription &a, const QSGSamplerDescription &b)
size_t qHash(const QSGSamplerDescription &s, size_t seed = 0) noexcept;
#if QT_CONFIG(opengl)
-class Q_QUICK_PRIVATE_EXPORT QSGTexturePlatformOpenGL : public QNativeInterface::QSGOpenGLTexture
+class Q_QUICK_EXPORT QSGTexturePlatformOpenGL : public QNativeInterface::QSGOpenGLTexture
{
public:
QSGTexturePlatformOpenGL(QSGTexture *t) : m_texture(t) { }
@@ -86,7 +50,7 @@ public:
#endif
#ifdef Q_OS_WIN
-class Q_QUICK_PRIVATE_EXPORT QSGTexturePlatformD3D11 : public QNativeInterface::QSGD3D11Texture
+class Q_QUICK_EXPORT QSGTexturePlatformD3D11 : public QNativeInterface::QSGD3D11Texture
{
public:
QSGTexturePlatformD3D11(QSGTexture *t) : m_texture(t) { }
@@ -94,21 +58,30 @@ public:
void *nativeTexture() const override;
};
+class Q_QUICK_EXPORT QSGTexturePlatformD3D12 : public QNativeInterface::QSGD3D12Texture
+{
+public:
+ QSGTexturePlatformD3D12(QSGTexture *t) : m_texture(t) { }
+ QSGTexture *m_texture;
+
+ int nativeResourceState() const override;
+ void *nativeTexture() const override;
+};
#endif
-#if defined(__OBJC__)
-class Q_QUICK_PRIVATE_EXPORT QSGTexturePlatformMetal : public QNativeInterface::QSGMetalTexture
+#if QT_CONFIG(metal)
+class Q_QUICK_EXPORT QSGTexturePlatformMetal : public QNativeInterface::QSGMetalTexture
{
public:
QSGTexturePlatformMetal(QSGTexture *t) : m_texture(t) { }
QSGTexture *m_texture;
- id<MTLTexture> nativeTexture() const override;
+ QT_OBJC_PROTOCOL(MTLTexture) nativeTexture() const override;
};
#endif
#if QT_CONFIG(vulkan)
-class Q_QUICK_PRIVATE_EXPORT QSGTexturePlatformVulkan : public QNativeInterface::QSGVulkanTexture
+class Q_QUICK_EXPORT QSGTexturePlatformVulkan : public QNativeInterface::QSGVulkanTexture
{
public:
QSGTexturePlatformVulkan(QSGTexture *t) : m_texture(t) { }
@@ -119,7 +92,7 @@ public:
};
#endif
-class Q_QUICK_PRIVATE_EXPORT QSGTexturePrivate : public QObjectPrivate
+class Q_QUICK_EXPORT QSGTexturePrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QSGTexture)
public:
@@ -146,8 +119,9 @@ public:
#endif
#ifdef Q_OS_WIN
QSGTexturePlatformD3D11 m_d3d11TextureAccessor;
+ QSGTexturePlatformD3D12 m_d3d12TextureAccessor;
#endif
-#if defined(__OBJC__)
+#if QT_CONFIG(metal)
QSGTexturePlatformMetal m_metalTextureAccessor;
#endif
#if QT_CONFIG(vulkan)
@@ -155,7 +129,7 @@ public:
#endif
};
-Q_QUICK_PRIVATE_EXPORT bool qsg_safeguard_texture(QSGTexture *);
+Q_QUICK_EXPORT bool qsg_safeguard_texture(QSGTexture *);
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/coreapi/qsgtexture_platform.h b/src/quick/scenegraph/coreapi/qsgtexture_platform.h
index d4d9ad50ed..63c35c381d 100644
--- a/src/quick/scenegraph/coreapi/qsgtexture_platform.h
+++ b/src/quick/scenegraph/coreapi/qsgtexture_platform.h
@@ -1,45 +1,10 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSGTEXTURE_PLATFORM_H
#define QSGTEXTURE_PLATFORM_H
+#include <QtCore/qnativeinterface.h>
#include <QtQuick/qquickwindow.h>
#if QT_CONFIG(opengl)
@@ -50,18 +15,24 @@
#include <QtGui/qvulkaninstance.h>
#endif
-#if defined(__OBJC__) || defined(Q_CLANG_QDOC)
-@protocol MTLTexture;
+#if QT_CONFIG(metal) || defined(Q_QDOC)
+# if defined(__OBJC__) || defined(Q_QDOC)
+ @protocol MTLTexture;
+# define QT_OBJC_PROTOCOL(protocol) id<protocol>
+# else
+ typedef struct objc_object *id;
+# define QT_OBJC_PROTOCOL(protocol) id
+# endif
#endif
QT_BEGIN_NAMESPACE
namespace QNativeInterface {
-#if QT_CONFIG(opengl) || defined(Q_CLANG_QDOC)
+#if QT_CONFIG(opengl) || defined(Q_QDOC)
struct Q_QUICK_EXPORT QSGOpenGLTexture
{
- QT_DECLARE_NATIVE_INTERFACE(QSGOpenGLTexture)
+ QT_DECLARE_NATIVE_INTERFACE(QSGOpenGLTexture, 1, QSGTexture)
virtual GLuint nativeTexture() const = 0;
static QSGTexture *fromNative(GLuint textureId,
QQuickWindow *window,
@@ -74,34 +45,45 @@ struct Q_QUICK_EXPORT QSGOpenGLTexture
};
#endif
-#if defined(Q_OS_WIN) || defined(Q_CLANG_QDOC)
+#if defined(Q_OS_WIN) || defined(Q_QDOC)
struct Q_QUICK_EXPORT QSGD3D11Texture
{
- QT_DECLARE_NATIVE_INTERFACE(QSGD3D11Texture)
+ QT_DECLARE_NATIVE_INTERFACE(QSGD3D11Texture, 1, QSGTexture)
virtual void *nativeTexture() const = 0;
static QSGTexture *fromNative(void *texture,
QQuickWindow *window,
const QSize &size,
QQuickWindow::CreateTextureOptions options = {});
};
+struct Q_QUICK_EXPORT QSGD3D12Texture
+{
+ QT_DECLARE_NATIVE_INTERFACE(QSGD3D12Texture, 1, QSGTexture)
+ virtual void *nativeTexture() const = 0;
+ virtual int nativeResourceState() const = 0;
+ static QSGTexture *fromNative(void *texture,
+ int resourceState,
+ QQuickWindow *window,
+ const QSize &size,
+ QQuickWindow::CreateTextureOptions options = {});
+};
#endif
-#if defined(__OBJC__) || defined(Q_CLANG_QDOC)
+#if QT_CONFIG(metal) || defined(Q_QDOC)
struct Q_QUICK_EXPORT QSGMetalTexture
{
- QT_DECLARE_NATIVE_INTERFACE(QSGMetalTexture)
- virtual id<MTLTexture> nativeTexture() const = 0;
- static QSGTexture *fromNative(id<MTLTexture> texture,
+ QT_DECLARE_NATIVE_INTERFACE(QSGMetalTexture, 1, QSGTexture)
+ virtual QT_OBJC_PROTOCOL(MTLTexture) nativeTexture() const = 0;
+ static QSGTexture *fromNative(QT_OBJC_PROTOCOL(MTLTexture) texture,
QQuickWindow *window,
const QSize &size,
QQuickWindow::CreateTextureOptions options = {});
};
#endif
-#if QT_CONFIG(vulkan) || defined(Q_CLANG_QDOC)
+#if QT_CONFIG(vulkan) || defined(Q_QDOC)
struct Q_QUICK_EXPORT QSGVulkanTexture
{
- QT_DECLARE_NATIVE_INTERFACE(QSGVulkanTexture)
+ QT_DECLARE_NATIVE_INTERFACE(QSGVulkanTexture, 1, QSGTexture)
virtual VkImage nativeImage() const = 0;
virtual VkImageLayout nativeImageLayout() const = 0;
static QSGTexture *fromNative(VkImage image,