From 0b9fcb829313d0eaf2b496bf3ad44e5628fa43b2 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 6 Jan 2020 12:24:59 +0100 Subject: Remove D3D12 scenegraph backend Task-number: QTBUG-79925 Change-Id: Id3f0a688f47efaf1653c85d23ef49618ed09c931 Reviewed-by: Paul Olav Tvete --- src/plugins/scenegraph/d3d12/d3d12.json | 3 - src/plugins/scenegraph/d3d12/d3d12.pro | 73 - src/plugins/scenegraph/d3d12/d3d12.tracepoints | 0 .../scenegraph/d3d12/qsgd3d12adaptation.cpp | 87 - .../scenegraph/d3d12/qsgd3d12adaptation_p.h | 81 - .../scenegraph/d3d12/qsgd3d12builtinmaterials.cpp | 737 ----- .../scenegraph/d3d12/qsgd3d12builtinmaterials_p.h | 253 -- src/plugins/scenegraph/d3d12/qsgd3d12context.cpp | 143 - src/plugins/scenegraph/d3d12/qsgd3d12context_p.h | 84 - src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp | 3280 -------------------- src/plugins/scenegraph/d3d12/qsgd3d12engine_p.h | 394 --- src/plugins/scenegraph/d3d12/qsgd3d12engine_p_p.h | 455 --- .../scenegraph/d3d12/qsgd3d12glyphcache.cpp | 197 -- .../scenegraph/d3d12/qsgd3d12glyphcache_p.h | 88 - src/plugins/scenegraph/d3d12/qsgd3d12glyphnode.cpp | 90 - src/plugins/scenegraph/d3d12/qsgd3d12glyphnode_p.h | 74 - .../scenegraph/d3d12/qsgd3d12internalimagenode.cpp | 123 - .../scenegraph/d3d12/qsgd3d12internalimagenode_p.h | 82 - .../d3d12/qsgd3d12internalrectanglenode.cpp | 72 - .../d3d12/qsgd3d12internalrectanglenode_p.h | 74 - src/plugins/scenegraph/d3d12/qsgd3d12layer.cpp | 370 --- src/plugins/scenegraph/d3d12/qsgd3d12layer_p.h | 129 - src/plugins/scenegraph/d3d12/qsgd3d12material.cpp | 49 - src/plugins/scenegraph/d3d12/qsgd3d12material_p.h | 96 - .../scenegraph/d3d12/qsgd3d12painternode.cpp | 255 -- .../scenegraph/d3d12/qsgd3d12painternode_p.h | 120 - .../scenegraph/d3d12/qsgd3d12publicnodes.cpp | 250 -- .../scenegraph/d3d12/qsgd3d12publicnodes_p.h | 136 - .../scenegraph/d3d12/qsgd3d12rendercontext.cpp | 169 - .../scenegraph/d3d12/qsgd3d12rendercontext_p.h | 90 - src/plugins/scenegraph/d3d12/qsgd3d12renderer.cpp | 785 ----- src/plugins/scenegraph/d3d12/qsgd3d12renderer_p.h | 137 - .../scenegraph/d3d12/qsgd3d12renderloop.cpp | 548 ---- .../scenegraph/d3d12/qsgd3d12renderloop_p.h | 130 - .../scenegraph/d3d12/qsgd3d12shadereffectnode.cpp | 995 ------ .../scenegraph/d3d12/qsgd3d12shadereffectnode_p.h | 176 -- .../scenegraph/d3d12/qsgd3d12spritenode.cpp | 314 -- .../scenegraph/d3d12/qsgd3d12spritenode_p.h | 90 - src/plugins/scenegraph/d3d12/qsgd3d12texture.cpp | 157 - src/plugins/scenegraph/d3d12/qsgd3d12texture_p.h | 96 - .../d3d12/qsgd3d12threadedrenderloop.cpp | 1208 ------- .../d3d12/qsgd3d12threadedrenderloop_p.h | 129 - .../scenegraph/d3d12/shaders/flatcolor.hlsl | 27 - .../scenegraph/d3d12/shaders/mipmapgen.hlsl | 60 - .../d3d12/shaders/shadereffectdefault.hlsl | 27 - src/plugins/scenegraph/d3d12/shaders/shaders.pri | 141 - .../scenegraph/d3d12/shaders/smoothcolor.hlsl | 64 - .../scenegraph/d3d12/shaders/smoothtexture.hlsl | 77 - src/plugins/scenegraph/d3d12/shaders/sprite.hlsl | 43 - .../scenegraph/d3d12/shaders/stencilclip.hlsl | 26 - src/plugins/scenegraph/d3d12/shaders/tdr.hlsl | 11 - src/plugins/scenegraph/d3d12/shaders/textmask.hlsl | 104 - src/plugins/scenegraph/d3d12/shaders/texture.hlsl | 33 - .../scenegraph/d3d12/shaders/vertexcolor.hlsl | 32 - src/plugins/scenegraph/scenegraph.pro | 1 - 55 files changed, 13465 deletions(-) delete mode 100644 src/plugins/scenegraph/d3d12/d3d12.json delete mode 100644 src/plugins/scenegraph/d3d12/d3d12.pro delete mode 100644 src/plugins/scenegraph/d3d12/d3d12.tracepoints delete mode 100644 src/plugins/scenegraph/d3d12/qsgd3d12adaptation.cpp delete mode 100644 src/plugins/scenegraph/d3d12/qsgd3d12adaptation_p.h delete mode 100644 src/plugins/scenegraph/d3d12/qsgd3d12builtinmaterials.cpp delete mode 100644 src/plugins/scenegraph/d3d12/qsgd3d12builtinmaterials_p.h delete mode 100644 src/plugins/scenegraph/d3d12/qsgd3d12context.cpp delete mode 100644 src/plugins/scenegraph/d3d12/qsgd3d12context_p.h delete mode 100644 src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp delete mode 100644 src/plugins/scenegraph/d3d12/qsgd3d12engine_p.h delete mode 100644 src/plugins/scenegraph/d3d12/qsgd3d12engine_p_p.h delete mode 100644 src/plugins/scenegraph/d3d12/qsgd3d12glyphcache.cpp delete mode 100644 src/plugins/scenegraph/d3d12/qsgd3d12glyphcache_p.h delete mode 100644 src/plugins/scenegraph/d3d12/qsgd3d12glyphnode.cpp delete mode 100644 src/plugins/scenegraph/d3d12/qsgd3d12glyphnode_p.h delete mode 100644 src/plugins/scenegraph/d3d12/qsgd3d12internalimagenode.cpp delete mode 100644 src/plugins/scenegraph/d3d12/qsgd3d12internalimagenode_p.h delete mode 100644 src/plugins/scenegraph/d3d12/qsgd3d12internalrectanglenode.cpp delete mode 100644 src/plugins/scenegraph/d3d12/qsgd3d12internalrectanglenode_p.h delete mode 100644 src/plugins/scenegraph/d3d12/qsgd3d12layer.cpp delete mode 100644 src/plugins/scenegraph/d3d12/qsgd3d12layer_p.h delete mode 100644 src/plugins/scenegraph/d3d12/qsgd3d12material.cpp delete mode 100644 src/plugins/scenegraph/d3d12/qsgd3d12material_p.h delete mode 100644 src/plugins/scenegraph/d3d12/qsgd3d12painternode.cpp delete mode 100644 src/plugins/scenegraph/d3d12/qsgd3d12painternode_p.h delete mode 100644 src/plugins/scenegraph/d3d12/qsgd3d12publicnodes.cpp delete mode 100644 src/plugins/scenegraph/d3d12/qsgd3d12publicnodes_p.h delete mode 100644 src/plugins/scenegraph/d3d12/qsgd3d12rendercontext.cpp delete mode 100644 src/plugins/scenegraph/d3d12/qsgd3d12rendercontext_p.h delete mode 100644 src/plugins/scenegraph/d3d12/qsgd3d12renderer.cpp delete mode 100644 src/plugins/scenegraph/d3d12/qsgd3d12renderer_p.h delete mode 100644 src/plugins/scenegraph/d3d12/qsgd3d12renderloop.cpp delete mode 100644 src/plugins/scenegraph/d3d12/qsgd3d12renderloop_p.h delete mode 100644 src/plugins/scenegraph/d3d12/qsgd3d12shadereffectnode.cpp delete mode 100644 src/plugins/scenegraph/d3d12/qsgd3d12shadereffectnode_p.h delete mode 100644 src/plugins/scenegraph/d3d12/qsgd3d12spritenode.cpp delete mode 100644 src/plugins/scenegraph/d3d12/qsgd3d12spritenode_p.h delete mode 100644 src/plugins/scenegraph/d3d12/qsgd3d12texture.cpp delete mode 100644 src/plugins/scenegraph/d3d12/qsgd3d12texture_p.h delete mode 100644 src/plugins/scenegraph/d3d12/qsgd3d12threadedrenderloop.cpp delete mode 100644 src/plugins/scenegraph/d3d12/qsgd3d12threadedrenderloop_p.h delete mode 100644 src/plugins/scenegraph/d3d12/shaders/flatcolor.hlsl delete mode 100644 src/plugins/scenegraph/d3d12/shaders/mipmapgen.hlsl delete mode 100644 src/plugins/scenegraph/d3d12/shaders/shadereffectdefault.hlsl delete mode 100644 src/plugins/scenegraph/d3d12/shaders/shaders.pri delete mode 100644 src/plugins/scenegraph/d3d12/shaders/smoothcolor.hlsl delete mode 100644 src/plugins/scenegraph/d3d12/shaders/smoothtexture.hlsl delete mode 100644 src/plugins/scenegraph/d3d12/shaders/sprite.hlsl delete mode 100644 src/plugins/scenegraph/d3d12/shaders/stencilclip.hlsl delete mode 100644 src/plugins/scenegraph/d3d12/shaders/tdr.hlsl delete mode 100644 src/plugins/scenegraph/d3d12/shaders/textmask.hlsl delete mode 100644 src/plugins/scenegraph/d3d12/shaders/texture.hlsl delete mode 100644 src/plugins/scenegraph/d3d12/shaders/vertexcolor.hlsl (limited to 'src/plugins') diff --git a/src/plugins/scenegraph/d3d12/d3d12.json b/src/plugins/scenegraph/d3d12/d3d12.json deleted file mode 100644 index c450a38556..0000000000 --- a/src/plugins/scenegraph/d3d12/d3d12.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "Keys": ["d3d12"] -} diff --git a/src/plugins/scenegraph/d3d12/d3d12.pro b/src/plugins/scenegraph/d3d12/d3d12.pro deleted file mode 100644 index 7192efe449..0000000000 --- a/src/plugins/scenegraph/d3d12/d3d12.pro +++ /dev/null @@ -1,73 +0,0 @@ -TARGET = qsgd3d12backend - -QT += core-private gui-private qml-private quick-private - -PLUGIN_TYPE = scenegraph -PLUGIN_CLASS_NAME = QSGD3D12Adaptation -load(qt_plugin) - -TRACEPOINT_PROVIDER = $$PWD/d3d12.tracepoints -CONFIG += qt_tracepoints -debug_and_release { - CONFIG(debug, debug|release) { - INCLUDEPATH += $$OUT_PWD/../../../quick/.tracegen/debug - } else { - INCLUDEPATH += $$OUT_PWD/../../../quick/.tracegen/release - } -} else { - INCLUDEPATH += $$OUT_PWD/../../../quick/.tracegen/ -} - -QMAKE_TARGET_PRODUCT = "Qt Quick D3D12 Renderer (Qt $$QT_VERSION)" -QMAKE_TARGET_DESCRIPTION = "Quick D3D12 Renderer for Qt." - -SOURCES += \ - $$PWD/qsgd3d12adaptation.cpp \ - $$PWD/qsgd3d12renderloop.cpp \ - $$PWD/qsgd3d12threadedrenderloop.cpp \ - $$PWD/qsgd3d12renderer.cpp \ - $$PWD/qsgd3d12context.cpp \ - $$PWD/qsgd3d12rendercontext.cpp \ - $$PWD/qsgd3d12internalrectanglenode.cpp \ - $$PWD/qsgd3d12material.cpp \ - $$PWD/qsgd3d12builtinmaterials.cpp \ - $$PWD/qsgd3d12texture.cpp \ - $$PWD/qsgd3d12internalimagenode.cpp \ - $$PWD/qsgd3d12glyphnode.cpp \ - $$PWD/qsgd3d12glyphcache.cpp \ - $$PWD/qsgd3d12layer.cpp \ - $$PWD/qsgd3d12shadereffectnode.cpp \ - $$PWD/qsgd3d12painternode.cpp \ - $$PWD/qsgd3d12publicnodes.cpp \ - $$PWD/qsgd3d12spritenode.cpp - -NO_PCH_SOURCES += \ - $$PWD/qsgd3d12engine.cpp - -HEADERS += \ - $$PWD/qsgd3d12adaptation_p.h \ - $$PWD/qsgd3d12renderloop_p.h \ - $$PWD/qsgd3d12threadedrenderloop_p.h \ - $$PWD/qsgd3d12renderer_p.h \ - $$PWD/qsgd3d12context_p.h \ - $$PWD/qsgd3d12rendercontext_p.h \ - $$PWD/qsgd3d12engine_p.h \ - $$PWD/qsgd3d12engine_p_p.h \ - $$PWD/qsgd3d12internalrectanglenode_p.h \ - $$PWD/qsgd3d12material_p.h \ - $$PWD/qsgd3d12builtinmaterials_p.h \ - $$PWD/qsgd3d12texture_p.h \ - $$PWD/qsgd3d12internalimagenode_p.h \ - $$PWD/qsgd3d12glyphnode_p.h \ - $$PWD/qsgd3d12glyphcache_p.h \ - $$PWD/qsgd3d12layer_p.h \ - $$PWD/qsgd3d12shadereffectnode_p.h \ - $$PWD/qsgd3d12painternode_p.h \ - $$PWD/qsgd3d12publicnodes_p.h \ - $$PWD/qsgd3d12spritenode_p.h - -LIBS += -ldxgi -ld3d12 -ld3dcompiler -ldcomp - -include($$PWD/shaders/shaders.pri) - -OTHER_FILES += $$PWD/d3d12.json diff --git a/src/plugins/scenegraph/d3d12/d3d12.tracepoints b/src/plugins/scenegraph/d3d12/d3d12.tracepoints deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12adaptation.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12adaptation.cpp deleted file mode 100644 index b93da0ae01..0000000000 --- a/src/plugins/scenegraph/d3d12/qsgd3d12adaptation.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include "qsgd3d12adaptation_p.h" -#include "qsgd3d12renderloop_p.h" -#include "qsgd3d12threadedrenderloop_p.h" -#include "qsgd3d12context_p.h" - -QT_BEGIN_NAMESPACE - -QSGD3D12Adaptation::QSGD3D12Adaptation(QObject *parent) - : QSGContextPlugin(parent) -{ -} - -QStringList QSGD3D12Adaptation::keys() const -{ - return QStringList() << QLatin1String("d3d12"); -} - -QSGContext *QSGD3D12Adaptation::create(const QString &) const -{ - if (!contextInstance) - contextInstance = new QSGD3D12Context; - - return contextInstance; -} - -QSGContextFactoryInterface::Flags QSGD3D12Adaptation::flags(const QString &) const -{ - return QSGContextFactoryInterface::SupportsShaderEffectNode; -} - -QSGRenderLoop *QSGD3D12Adaptation::createWindowManager() -{ - static bool threaded = false; - static bool envChecked = false; - if (!envChecked) { - envChecked = true; - threaded = qgetenv("QSG_RENDER_LOOP") == QByteArrayLiteral("threaded"); - } - - if (threaded) - return new QSGD3D12ThreadedRenderLoop; - - return new QSGD3D12RenderLoop; -} - -QSGD3D12Context *QSGD3D12Adaptation::contextInstance = nullptr; - -QT_END_NAMESPACE diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12adaptation_p.h b/src/plugins/scenegraph/d3d12/qsgd3d12adaptation_p.h deleted file mode 100644 index 035c3408ff..0000000000 --- a/src/plugins/scenegraph/d3d12/qsgd3d12adaptation_p.h +++ /dev/null @@ -1,81 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#ifndef QSGD3D12ADAPTATION_P_H -#define QSGD3D12ADAPTATION_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include - -QT_BEGIN_NAMESPACE - -class QSGD3D12Context; -class QSGContext; -class QSGRenderLoop; - -class QSGD3D12Adaptation : public QSGContextPlugin -{ - Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QSGContextFactoryInterface" FILE "d3d12.json") - -public: - QSGD3D12Adaptation(QObject *parent = 0); - - QStringList keys() const override; - QSGContext *create(const QString &key) const override; - QSGContextFactoryInterface::Flags flags(const QString &key) const override; - QSGRenderLoop *createWindowManager() override; - -private: - static QSGD3D12Context *contextInstance; -}; - -QT_END_NAMESPACE - -#endif // QSGD3D12ADAPTATION_P_H diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12builtinmaterials.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12builtinmaterials.cpp deleted file mode 100644 index 312e8c19cd..0000000000 --- a/src/plugins/scenegraph/d3d12/qsgd3d12builtinmaterials.cpp +++ /dev/null @@ -1,737 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include "qsgd3d12builtinmaterials_p.h" -#include "qsgd3d12rendercontext_p.h" -#include -#include -#include - -#include "vs_vertexcolor.hlslh" -#include "ps_vertexcolor.hlslh" -#include "vs_flatcolor.hlslh" -#include "ps_flatcolor.hlslh" -#include "vs_smoothcolor.hlslh" -#include "ps_smoothcolor.hlslh" -#include "vs_texture.hlslh" -#include "ps_texture.hlslh" -#include "vs_smoothtexture.hlslh" -#include "ps_smoothtexture.hlslh" -#include "vs_textmask.hlslh" -#include "ps_textmask24.hlslh" -#include "ps_textmask32.hlslh" -#include "ps_textmask8.hlslh" -#include "vs_styledtext.hlslh" -#include "ps_styledtext.hlslh" -#include "vs_outlinedtext.hlslh" -#include "ps_outlinedtext.hlslh" - -QT_BEGIN_NAMESPACE - -// NB! In HLSL constant buffer data is packed into 4-byte boundaries and, more -// importantly, it is packed so that it does not cross a 16-byte (float4) -// boundary. Hence the need for padding in some cases. - -static inline QVector4D qsg_premultiply(const QVector4D &c, float globalOpacity) -{ - const float o = c.w() * globalOpacity; - return QVector4D(c.x() * o, c.y() * o, c.z() * o, o); -} - -static inline QVector4D qsg_premultiply(const QColor &c, float globalOpacity) -{ - const float o = c.alphaF() * globalOpacity; - return QVector4D(c.redF() * o, c.greenF() * o, c.blueF() * o, o); -} - -static inline int qsg_colorDiff(const QVector4D &a, const QVector4D &b) -{ - if (a.x() != b.x()) - return a.x() > b.x() ? 1 : -1; - if (a.y() != b.y()) - return a.y() > b.y() ? 1 : -1; - if (a.z() != b.z()) - return a.z() > b.z() ? 1 : -1; - if (a.w() != b.w()) - return a.w() > b.w() ? 1 : -1; - return 0; -} - -QSGMaterialType QSGD3D12VertexColorMaterial::mtype; - -QSGMaterialType *QSGD3D12VertexColorMaterial::type() const -{ - return &QSGD3D12VertexColorMaterial::mtype; -} - -int QSGD3D12VertexColorMaterial::compare(const QSGMaterial *other) const -{ - Q_UNUSED(other); - Q_ASSERT(other && type() == other->type()); - // As the vertex color material has all its state in the vertex attributes - // defined by the geometry, all such materials will be equal. - return 0; -} - -static const int VERTEX_COLOR_CB_SIZE_0 = 16 * sizeof(float); // float4x4 -static const int VERTEX_COLOR_CB_SIZE_1 = sizeof(float); // float -static const int VERTEX_COLOR_CB_SIZE = VERTEX_COLOR_CB_SIZE_0 + VERTEX_COLOR_CB_SIZE_1; - -int QSGD3D12VertexColorMaterial::constantBufferSize() const -{ - return QSGD3D12Engine::alignedConstantBufferSize(VERTEX_COLOR_CB_SIZE); -} - -void QSGD3D12VertexColorMaterial::preparePipeline(QSGD3D12PipelineState *pipelineState) -{ - pipelineState->shaders.vs = g_VS_VertexColor; - pipelineState->shaders.vsSize = sizeof(g_VS_VertexColor); - pipelineState->shaders.ps = g_PS_VertexColor; - pipelineState->shaders.psSize = sizeof(g_PS_VertexColor); -} - -QSGD3D12Material::UpdateResults QSGD3D12VertexColorMaterial::updatePipeline(const QSGD3D12MaterialRenderState &state, - QSGD3D12PipelineState *, - ExtraState *, - quint8 *constantBuffer) -{ - QSGD3D12Material::UpdateResults r = 0; - quint8 *p = constantBuffer; - - if (state.isMatrixDirty()) { - memcpy(p, state.combinedMatrix().constData(), VERTEX_COLOR_CB_SIZE_0); - r |= UpdatedConstantBuffer; - } - p += VERTEX_COLOR_CB_SIZE_0; - - if (state.isOpacityDirty()) { - const float opacity = state.opacity(); - memcpy(p, &opacity, VERTEX_COLOR_CB_SIZE_1); - r |= UpdatedConstantBuffer; - } - - return r; -} - -QSGD3D12FlatColorMaterial::QSGD3D12FlatColorMaterial() - : m_color(QColor(255, 255, 255)) -{ -} - -QSGMaterialType QSGD3D12FlatColorMaterial::mtype; - -QSGMaterialType *QSGD3D12FlatColorMaterial::type() const -{ - return &QSGD3D12FlatColorMaterial::mtype; -} - -int QSGD3D12FlatColorMaterial::compare(const QSGMaterial *other) const -{ - Q_ASSERT(other && type() == other->type()); - const QSGD3D12FlatColorMaterial *o = static_cast(other); - return m_color.rgba() - o->color().rgba(); -} - -static const int FLAT_COLOR_CB_SIZE_0 = 16 * sizeof(float); // float4x4 -static const int FLAT_COLOR_CB_SIZE_1 = 4 * sizeof(float); // float4 -static const int FLAT_COLOR_CB_SIZE = FLAT_COLOR_CB_SIZE_0 + FLAT_COLOR_CB_SIZE_1; - -int QSGD3D12FlatColorMaterial::constantBufferSize() const -{ - return QSGD3D12Engine::alignedConstantBufferSize(FLAT_COLOR_CB_SIZE); -} - -void QSGD3D12FlatColorMaterial::preparePipeline(QSGD3D12PipelineState *pipelineState) -{ - pipelineState->shaders.vs = g_VS_FlatColor; - pipelineState->shaders.vsSize = sizeof(g_VS_FlatColor); - pipelineState->shaders.ps = g_PS_FlatColor; - pipelineState->shaders.psSize = sizeof(g_PS_FlatColor); -} - -QSGD3D12Material::UpdateResults QSGD3D12FlatColorMaterial::updatePipeline(const QSGD3D12MaterialRenderState &state, - QSGD3D12PipelineState *, - ExtraState *, - quint8 *constantBuffer) -{ - QSGD3D12Material::UpdateResults r = 0; - quint8 *p = constantBuffer; - - if (state.isMatrixDirty()) { - memcpy(p, state.combinedMatrix().constData(), FLAT_COLOR_CB_SIZE_0); - r |= UpdatedConstantBuffer; - } - p += FLAT_COLOR_CB_SIZE_0; - - const QVector4D color = qsg_premultiply(m_color, state.opacity()); - const float f[] = { color.x(), color.y(), color.z(), color.w() }; - if (state.isOpacityDirty() || memcmp(p, f, FLAT_COLOR_CB_SIZE_1)) { - memcpy(p, f, FLAT_COLOR_CB_SIZE_1); - r |= UpdatedConstantBuffer; - } - - return r; -} - -void QSGD3D12FlatColorMaterial::setColor(const QColor &color) -{ - m_color = color; - setFlag(Blending, m_color.alpha() != 0xFF); -} - -QSGD3D12SmoothColorMaterial::QSGD3D12SmoothColorMaterial() -{ - setFlag(RequiresFullMatrixExceptTranslate, true); - setFlag(Blending, true); -} - -QSGMaterialType QSGD3D12SmoothColorMaterial::mtype; - -QSGMaterialType *QSGD3D12SmoothColorMaterial::type() const -{ - return &QSGD3D12SmoothColorMaterial::mtype; -} - -int QSGD3D12SmoothColorMaterial::compare(const QSGMaterial *other) const -{ - Q_UNUSED(other); - Q_ASSERT(other && type() == other->type()); - return 0; -} - -static const int SMOOTH_COLOR_CB_SIZE_0 = 16 * sizeof(float); // float4x4 -static const int SMOOTH_COLOR_CB_SIZE_1 = sizeof(float); // float -static const int SMOOTH_COLOR_CB_SIZE_2 = 2 * sizeof(float); // float2 -static const int SMOOTH_COLOR_CB_SIZE = SMOOTH_COLOR_CB_SIZE_0 + SMOOTH_COLOR_CB_SIZE_1 + SMOOTH_COLOR_CB_SIZE_2; - -int QSGD3D12SmoothColorMaterial::constantBufferSize() const -{ - return QSGD3D12Engine::alignedConstantBufferSize(SMOOTH_COLOR_CB_SIZE); -} - -void QSGD3D12SmoothColorMaterial::preparePipeline(QSGD3D12PipelineState *pipelineState) -{ - pipelineState->shaders.vs = g_VS_SmoothColor; - pipelineState->shaders.vsSize = sizeof(g_VS_SmoothColor); - pipelineState->shaders.ps = g_PS_SmoothColor; - pipelineState->shaders.psSize = sizeof(g_PS_SmoothColor); -} - -QSGD3D12Material::UpdateResults QSGD3D12SmoothColorMaterial::updatePipeline(const QSGD3D12MaterialRenderState &state, - QSGD3D12PipelineState *, - ExtraState *, - quint8 *constantBuffer) -{ - QSGD3D12Material::UpdateResults r = 0; - quint8 *p = constantBuffer; - - if (state.isMatrixDirty()) { - memcpy(p, state.combinedMatrix().constData(), SMOOTH_COLOR_CB_SIZE_0); - r |= UpdatedConstantBuffer; - } - p += SMOOTH_COLOR_CB_SIZE_0; - - if (state.isOpacityDirty()) { - const float opacity = state.opacity(); - memcpy(p, &opacity, SMOOTH_COLOR_CB_SIZE_1); - r |= UpdatedConstantBuffer; - } - p += SMOOTH_COLOR_CB_SIZE_1; - - if (state.isMatrixDirty()) { - const QRect viewport = state.viewportRect(); - const float v[] = { 2.0f / viewport.width(), 2.0f / viewport.height() }; - memcpy(p, v, SMOOTH_COLOR_CB_SIZE_2); - r |= UpdatedConstantBuffer; - } - - return r; -} - -QSGMaterialType QSGD3D12TextureMaterial::mtype; - -QSGMaterialType *QSGD3D12TextureMaterial::type() const -{ - return &QSGD3D12TextureMaterial::mtype; -} - -int QSGD3D12TextureMaterial::compare(const QSGMaterial *other) const -{ - Q_ASSERT(other && type() == other->type()); - const QSGD3D12TextureMaterial *o = static_cast(other); - if (int diff = m_texture->textureId() - o->texture()->textureId()) - return diff; - return int(m_filtering) - int(o->m_filtering); -} - -static const int TEXTURE_CB_SIZE_0 = 16 * sizeof(float); // float4x4 -static const int TEXTURE_CB_SIZE_1 = sizeof(float); // float -static const int TEXTURE_CB_SIZE = TEXTURE_CB_SIZE_0 + TEXTURE_CB_SIZE_1; - -int QSGD3D12TextureMaterial::constantBufferSize() const -{ - return QSGD3D12Engine::alignedConstantBufferSize(TEXTURE_CB_SIZE); -} - -void QSGD3D12TextureMaterial::preparePipeline(QSGD3D12PipelineState *pipelineState) -{ - pipelineState->shaders.vs = g_VS_Texture; - pipelineState->shaders.vsSize = sizeof(g_VS_Texture); - pipelineState->shaders.ps = g_PS_Texture; - pipelineState->shaders.psSize = sizeof(g_PS_Texture); - - pipelineState->shaders.rootSig.textureViewCount = 1; -} - -QSGD3D12Material::UpdateResults QSGD3D12TextureMaterial::updatePipeline(const QSGD3D12MaterialRenderState &state, - QSGD3D12PipelineState *pipelineState, - ExtraState *, - quint8 *constantBuffer) -{ - QSGD3D12Material::UpdateResults r = 0; - quint8 *p = constantBuffer; - - if (state.isMatrixDirty()) { - memcpy(p, state.combinedMatrix().constData(), TEXTURE_CB_SIZE_0); - r |= UpdatedConstantBuffer; - } - p += TEXTURE_CB_SIZE_0; - - if (state.isOpacityDirty()) { - const float opacity = state.opacity(); - memcpy(p, &opacity, TEXTURE_CB_SIZE_1); - r |= UpdatedConstantBuffer; - } - - Q_ASSERT(m_texture); - m_texture->setFiltering(m_filtering); - m_texture->setMipmapFiltering(m_mipmap_filtering); - m_texture->setHorizontalWrapMode(m_horizontal_wrap); - m_texture->setVerticalWrapMode(m_vertical_wrap); - - QSGD3D12TextureView &tv(pipelineState->shaders.rootSig.textureViews[0]); - if (m_filtering == QSGTexture::Linear) - tv.filter = m_mipmap_filtering == QSGTexture::Linear - ? QSGD3D12TextureView::FilterLinear : QSGD3D12TextureView::FilterMinMagLinearMipNearest; - else - tv.filter = m_mipmap_filtering == QSGTexture::Linear - ? QSGD3D12TextureView::FilterMinMagNearestMipLinear : QSGD3D12TextureView::FilterNearest; - tv.addressModeHoriz = m_horizontal_wrap == QSGTexture::ClampToEdge ? QSGD3D12TextureView::AddressClamp : QSGD3D12TextureView::AddressWrap; - tv.addressModeVert = m_vertical_wrap == QSGTexture::ClampToEdge ? QSGD3D12TextureView::AddressClamp : QSGD3D12TextureView::AddressWrap; - - m_texture->bind(); - - return r; -} - -void QSGD3D12TextureMaterial::setTexture(QSGTexture *texture) -{ - m_texture = texture; - setFlag(Blending, m_texture ? m_texture->hasAlphaChannel() : false); -} - -QSGD3D12SmoothTextureMaterial::QSGD3D12SmoothTextureMaterial() -{ - setFlag(RequiresFullMatrixExceptTranslate, true); - setFlag(Blending, true); -} - -QSGMaterialType QSGD3D12SmoothTextureMaterial::mtype; - -QSGMaterialType *QSGD3D12SmoothTextureMaterial::type() const -{ - return &QSGD3D12SmoothTextureMaterial::mtype; -} - -int QSGD3D12SmoothTextureMaterial::compare(const QSGMaterial *other) const -{ - Q_ASSERT(other && type() == other->type()); - const QSGD3D12SmoothTextureMaterial *o = static_cast(other); - if (int diff = m_texture->textureId() - o->texture()->textureId()) - return diff; - return int(m_filtering) - int(o->m_filtering); -} - -static const int SMOOTH_TEXTURE_CB_SIZE_0 = 16 * sizeof(float); // float4x4 -static const int SMOOTH_TEXTURE_CB_SIZE_1 = sizeof(float); // float -static const int SMOOTH_TEXTURE_CB_SIZE_2 = 2 * sizeof(float); // float2 -static const int SMOOTH_TEXTURE_CB_SIZE = SMOOTH_TEXTURE_CB_SIZE_0 + SMOOTH_TEXTURE_CB_SIZE_1 + SMOOTH_TEXTURE_CB_SIZE_2; - -int QSGD3D12SmoothTextureMaterial::constantBufferSize() const -{ - return QSGD3D12Engine::alignedConstantBufferSize(SMOOTH_TEXTURE_CB_SIZE); -} - -void QSGD3D12SmoothTextureMaterial::preparePipeline(QSGD3D12PipelineState *pipelineState) -{ - pipelineState->shaders.vs = g_VS_SmoothTexture; - pipelineState->shaders.vsSize = sizeof(g_VS_SmoothTexture); - pipelineState->shaders.ps = g_PS_SmoothTexture; - pipelineState->shaders.psSize = sizeof(g_PS_SmoothTexture); - - pipelineState->shaders.rootSig.textureViewCount = 1; -} - -QSGD3D12Material::UpdateResults QSGD3D12SmoothTextureMaterial::updatePipeline(const QSGD3D12MaterialRenderState &state, - QSGD3D12PipelineState *pipelineState, - ExtraState *, - quint8 *constantBuffer) -{ - QSGD3D12Material::UpdateResults r = 0; - quint8 *p = constantBuffer; - - if (state.isMatrixDirty()) { - memcpy(p, state.combinedMatrix().constData(), SMOOTH_TEXTURE_CB_SIZE_0); - r |= UpdatedConstantBuffer; - } - p += SMOOTH_TEXTURE_CB_SIZE_0; - - if (state.isOpacityDirty()) { - const float opacity = state.opacity(); - memcpy(p, &opacity, SMOOTH_TEXTURE_CB_SIZE_1); - r |= UpdatedConstantBuffer; - } - p += SMOOTH_TEXTURE_CB_SIZE_1; - - if (state.isMatrixDirty()) { - const QRect viewport = state.viewportRect(); - const float v[] = { 2.0f / viewport.width(), 2.0f / viewport.height() }; - memcpy(p, v, SMOOTH_TEXTURE_CB_SIZE_2); - r |= UpdatedConstantBuffer; - } - - Q_ASSERT(m_texture); - m_texture->setFiltering(m_filtering); - m_texture->setMipmapFiltering(m_mipmap_filtering); - m_texture->setHorizontalWrapMode(m_horizontal_wrap); - m_texture->setVerticalWrapMode(m_vertical_wrap); - - QSGD3D12TextureView &tv(pipelineState->shaders.rootSig.textureViews[0]); - if (m_filtering == QSGTexture::Linear) - tv.filter = m_mipmap_filtering == QSGTexture::Linear - ? QSGD3D12TextureView::FilterLinear : QSGD3D12TextureView::FilterMinMagLinearMipNearest; - else - tv.filter = m_mipmap_filtering == QSGTexture::Linear - ? QSGD3D12TextureView::FilterMinMagNearestMipLinear : QSGD3D12TextureView::FilterNearest; - tv.addressModeHoriz = m_horizontal_wrap == QSGTexture::ClampToEdge ? QSGD3D12TextureView::AddressClamp : QSGD3D12TextureView::AddressWrap; - tv.addressModeVert = m_vertical_wrap == QSGTexture::ClampToEdge ? QSGD3D12TextureView::AddressClamp : QSGD3D12TextureView::AddressWrap; - - m_texture->bind(); - - return r; -} - -QSGD3D12TextMaterial::QSGD3D12TextMaterial(StyleType styleType, QSGD3D12RenderContext *rc, - const QRawFont &font, QFontEngine::GlyphFormat glyphFormat) - : m_styleType(styleType), - m_rc(rc), - m_font(font) -{ - setFlag(Blending, true); - - QRawFontPrivate *fontD = QRawFontPrivate::get(m_font); - if (QFontEngine *fontEngine = fontD->fontEngine) { - if (glyphFormat == QFontEngine::Format_None) - glyphFormat = fontEngine->glyphFormat != QFontEngine::Format_None - ? fontEngine->glyphFormat : QFontEngine::Format_A32; - - QSGD3D12Engine *d3dengine = rc->engine(); - const float devicePixelRatio = d3dengine->windowDevicePixelRatio(); - QTransform glyphCacheTransform = QTransform::fromScale(devicePixelRatio, devicePixelRatio); - if (!fontEngine->supportsTransformation(glyphCacheTransform)) - glyphCacheTransform = QTransform(); - - m_glyphCache = fontEngine->glyphCache(d3dengine, glyphFormat, glyphCacheTransform); - if (!m_glyphCache || int(m_glyphCache->glyphFormat()) != glyphFormat) { - m_glyphCache = new QSGD3D12GlyphCache(d3dengine, glyphFormat, glyphCacheTransform); - fontEngine->setGlyphCache(d3dengine, m_glyphCache.data()); - rc->registerFontengineForCleanup(fontEngine); - } - } -} - -QSGMaterialType QSGD3D12TextMaterial::mtype[QSGD3D12TextMaterial::NTextMaterialTypes]; - -QSGMaterialType *QSGD3D12TextMaterial::type() const -{ - // Format_A32 has special blend settings and therefore two materials with - // the same style but different formats where one is A32 are treated as - // different. This way the renderer can manage the pipeline state properly. - const int matStyle = m_styleType * 2; - const int matFormat = glyphCache()->glyphFormat() != QFontEngine::Format_A32 ? 0 : 1; - return &QSGD3D12TextMaterial::mtype[matStyle + matFormat]; -} - -int QSGD3D12TextMaterial::compare(const QSGMaterial *other) const -{ - Q_ASSERT(other && type() == other->type()); - const QSGD3D12TextMaterial *o = static_cast(other); - if (m_styleType != o->m_styleType) - return m_styleType - o->m_styleType; - if (m_glyphCache != o->m_glyphCache) - return m_glyphCache.data() < o->m_glyphCache.data() ? -1 : 1; - if (m_styleShift != o->m_styleShift) - return m_styleShift.y() - o->m_styleShift.y(); - int styleColorDiff = qsg_colorDiff(m_styleColor, o->m_styleColor); - if (styleColorDiff) - return styleColorDiff; - return qsg_colorDiff(m_color, o->m_color); -} - -static const int TEXT_CB_SIZE_0 = 16 * sizeof(float); // float4x4 mvp -static const int TEXT_CB_SIZE_1 = 2 * sizeof(float); // float2 textureScale -static const int TEXT_CB_SIZE_2 = sizeof(float); // float dpr -static const int TEXT_CB_SIZE_3 = sizeof(float); // float color -static const int TEXT_CB_SIZE_4 = 4 * sizeof(float); // float4 colorVec -static const int TEXT_CB_SIZE_5 = 2 * sizeof(float); // float2 shift -static const int TEXT_CB_SIZE_5_PADDING = 2 * sizeof(float); // float2 padding (the next float4 would cross the 16-byte boundary) -static const int TEXT_CB_SIZE_6 = 4 * sizeof(float); // float4 styleColor -static const int TEXT_CB_SIZE = TEXT_CB_SIZE_0 + TEXT_CB_SIZE_1 + TEXT_CB_SIZE_2 + TEXT_CB_SIZE_3 - + TEXT_CB_SIZE_4 + TEXT_CB_SIZE_5 + TEXT_CB_SIZE_5_PADDING + TEXT_CB_SIZE_6; - -int QSGD3D12TextMaterial::constantBufferSize() const -{ - return QSGD3D12Engine::alignedConstantBufferSize(TEXT_CB_SIZE); -} - -void QSGD3D12TextMaterial::preparePipeline(QSGD3D12PipelineState *pipelineState) -{ - if (m_styleType == Normal) { - pipelineState->shaders.vs = g_VS_TextMask; - pipelineState->shaders.vsSize = sizeof(g_VS_TextMask); - switch (glyphCache()->glyphFormat()) { - case QFontEngine::Format_A32: - pipelineState->shaders.ps = g_PS_TextMask24; - pipelineState->shaders.psSize = sizeof(g_PS_TextMask24); - break; - case QFontEngine::Format_ARGB: - pipelineState->shaders.ps = g_PS_TextMask32; - pipelineState->shaders.psSize = sizeof(g_PS_TextMask32); - break; - default: - pipelineState->shaders.ps = g_PS_TextMask8; - pipelineState->shaders.psSize = sizeof(g_PS_TextMask8); - break; - } - } else if (m_styleType == Outlined) { - pipelineState->shaders.vs = g_VS_OutlinedText; - pipelineState->shaders.vsSize = sizeof(g_VS_OutlinedText); - pipelineState->shaders.ps = g_PS_OutlinedText; - pipelineState->shaders.psSize = sizeof(g_PS_OutlinedText); - } else { - pipelineState->shaders.vs = g_VS_StyledText; - pipelineState->shaders.vsSize = sizeof(g_VS_StyledText); - pipelineState->shaders.ps = g_PS_StyledText; - pipelineState->shaders.psSize = sizeof(g_PS_StyledText); - } - - pipelineState->shaders.rootSig.textureViewCount = 1; -} - -QSGD3D12Material::UpdateResults QSGD3D12TextMaterial::updatePipeline(const QSGD3D12MaterialRenderState &state, - QSGD3D12PipelineState *pipelineState, - ExtraState *extraState, - quint8 *constantBuffer) -{ - QSGD3D12Material::UpdateResults r = 0; - quint8 *p = constantBuffer; - - if (glyphCache()->glyphFormat() == QFontEngine::Format_A32) { - // can freely change the state due to the way type() works - pipelineState->blend = QSGD3D12PipelineState::BlendColor; - extraState->blendFactor = m_color; - r |= UpdatedBlendFactor; // must be set always as this affects the command list - } - - if (state.isMatrixDirty()) { - memcpy(p, state.combinedMatrix().constData(), TEXT_CB_SIZE_0); - r |= UpdatedConstantBuffer; - } - p += TEXT_CB_SIZE_0; - - const QSize sz = glyphCache()->currentSize(); - const float textureScale[] = { 1.0f / sz.width(), 1.0f / sz.height() }; - if (state.isCachedMaterialDataDirty() || memcmp(p, textureScale, TEXT_CB_SIZE_1)) { - memcpy(p, textureScale, TEXT_CB_SIZE_1); - r |= UpdatedConstantBuffer; - } - p += TEXT_CB_SIZE_1; - - const float dpr = m_rc->engine()->windowDevicePixelRatio(); - if (state.isCachedMaterialDataDirty() || memcmp(p, &dpr, TEXT_CB_SIZE_2)) { - memcpy(p, &dpr, TEXT_CB_SIZE_2); - r |= UpdatedConstantBuffer; - } - p += TEXT_CB_SIZE_2; - - if (glyphCache()->glyphFormat() == QFontEngine::Format_A32) { - const QVector4D color = qsg_premultiply(m_color, state.opacity()); - const float alpha = color.w(); - if (state.isOpacityDirty() || memcmp(p, &alpha, TEXT_CB_SIZE_3)) { - memcpy(p, &alpha, TEXT_CB_SIZE_3); - r |= UpdatedConstantBuffer; - } - } else if (glyphCache()->glyphFormat() == QFontEngine::Format_ARGB) { - const float opacity = m_color.w() * state.opacity(); - if (state.isOpacityDirty() || memcmp(p, &opacity, TEXT_CB_SIZE_3)) { - memcpy(p, &opacity, TEXT_CB_SIZE_3); - r |= UpdatedConstantBuffer; - } - } else { - const QVector4D color = qsg_premultiply(m_color, state.opacity()); - const float f[] = { color.x(), color.y(), color.z(), color.w() }; - if (state.isOpacityDirty() || memcmp(p, f, TEXT_CB_SIZE_4)) { - memcpy(p + TEXT_CB_SIZE_3, f, TEXT_CB_SIZE_4); - r |= UpdatedConstantBuffer; - } - } - p += TEXT_CB_SIZE_3 + TEXT_CB_SIZE_4; - - if (m_styleType == Styled) { - const float f[] = { m_styleShift.x(), m_styleShift.y() }; - if (state.isCachedMaterialDataDirty() || memcmp(p, f, TEXT_CB_SIZE_5)) { - memcpy(p, f, TEXT_CB_SIZE_5); - r |= UpdatedConstantBuffer; - } - } - p += TEXT_CB_SIZE_5 + TEXT_CB_SIZE_5_PADDING; - - if (m_styleType == Styled || m_styleType == Outlined) { - const QVector4D color = qsg_premultiply(m_styleColor, state.opacity()); - const float f[] = { color.x(), color.y(), color.z(), color.w() }; - if (state.isOpacityDirty() || memcmp(p, f, TEXT_CB_SIZE_6)) { - memcpy(p, f, TEXT_CB_SIZE_6); - r |= UpdatedConstantBuffer; - } - } - - QSGD3D12TextureView &tv(pipelineState->shaders.rootSig.textureViews[0]); - tv.filter = QSGD3D12TextureView::FilterNearest; - tv.addressModeHoriz = QSGD3D12TextureView::AddressClamp; - tv.addressModeVert = QSGD3D12TextureView::AddressClamp; - - glyphCache()->useTexture(); - - return r; -} - -void QSGD3D12TextMaterial::populate(const QPointF &p, - const QVector &glyphIndexes, - const QVector &glyphPositions, - QSGGeometry *geometry, - QRectF *boundingRect, - QPointF *baseLine, - const QMargins &margins) -{ - Q_ASSERT(m_font.isValid()); - QVector fixedPointPositions; - const int glyphPositionsSize = glyphPositions.size(); - fixedPointPositions.reserve(glyphPositionsSize); - for (int i=0; i < glyphPositionsSize; ++i) - fixedPointPositions.append(QFixedPoint::fromPointF(glyphPositions.at(i))); - - QSGD3D12GlyphCache *cache = glyphCache(); - QRawFontPrivate *fontD = QRawFontPrivate::get(m_font); - cache->populate(fontD->fontEngine, glyphIndexes.size(), glyphIndexes.constData(), - fixedPointPositions.data()); - cache->fillInPendingGlyphs(); - - int margin = fontD->fontEngine->glyphMargin(cache->glyphFormat()); - - float glyphCacheScaleX = cache->transform().m11(); - float glyphCacheScaleY = cache->transform().m22(); - float glyphCacheInverseScaleX = 1.0 / glyphCacheScaleX; - float glyphCacheInverseScaleY = 1.0 / glyphCacheScaleY; - - Q_ASSERT(geometry->indexType() == QSGGeometry::UnsignedShortType); - geometry->allocate(glyphIndexes.size() * 4, glyphIndexes.size() * 6); - QVector4D *vp = reinterpret_cast(geometry->vertexDataAsTexturedPoint2D()); - Q_ASSERT(geometry->sizeOfVertex() == sizeof(QVector4D)); - ushort *ip = geometry->indexDataAsUShort(); - - QPointF position(p.x(), p.y() - m_font.ascent()); - bool supportsSubPixelPositions = fontD->fontEngine->supportsSubPixelPositions(); - for (int i = 0; i < glyphIndexes.size(); ++i) { - QFixed subPixelPosition; - if (supportsSubPixelPositions) - subPixelPosition = fontD->fontEngine->subPixelPositionForX(QFixed::fromReal(glyphPositions.at(i).x())); - - QTextureGlyphCache::GlyphAndSubPixelPosition glyph(glyphIndexes.at(i), subPixelPosition); - const QTextureGlyphCache::Coord &c = cache->coords.value(glyph); - - QPointF glyphPosition = glyphPositions.at(i) + position; - float x = (qFloor(glyphPosition.x() * glyphCacheScaleX) * glyphCacheInverseScaleX) - + (c.baseLineX * glyphCacheInverseScaleX) - margin; - float y = (qRound(glyphPosition.y() * glyphCacheScaleY) * glyphCacheInverseScaleY) - - (c.baseLineY * glyphCacheInverseScaleY) - margin; - - float w = c.w * glyphCacheInverseScaleX; - float h = c.h * glyphCacheInverseScaleY; - - *boundingRect |= QRectF(x + margin, y + margin, w, h); - - float cx1 = x - margins.left(); - float cx2 = x + w + margins.right(); - float cy1 = y - margins.top(); - float cy2 = y + h + margins.bottom(); - - float tx1 = c.x - margins.left(); - float tx2 = c.x + c.w + margins.right(); - float ty1 = c.y - margins.top(); - float ty2 = c.y + c.h + margins.bottom(); - - if (baseLine->isNull()) - *baseLine = glyphPosition; - - vp[4 * i + 0] = QVector4D(cx1, cy1, tx1, ty1); - vp[4 * i + 1] = QVector4D(cx2, cy1, tx2, ty1); - vp[4 * i + 2] = QVector4D(cx1, cy2, tx1, ty2); - vp[4 * i + 3] = QVector4D(cx2, cy2, tx2, ty2); - - int o = i * 4; - ip[6 * i + 0] = o + 0; - ip[6 * i + 1] = o + 2; - ip[6 * i + 2] = o + 3; - ip[6 * i + 3] = o + 3; - ip[6 * i + 4] = o + 1; - ip[6 * i + 5] = o + 0; - } -} - -QT_END_NAMESPACE diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12builtinmaterials_p.h b/src/plugins/scenegraph/d3d12/qsgd3d12builtinmaterials_p.h deleted file mode 100644 index 8e488f8cd1..0000000000 --- a/src/plugins/scenegraph/d3d12/qsgd3d12builtinmaterials_p.h +++ /dev/null @@ -1,253 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#ifndef QSGD3D12BUILTINMATERIALS_P_H -#define QSGD3D12BUILTINMATERIALS_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qsgd3d12material_p.h" -#include "qsgd3d12glyphcache_p.h" -#include -#include - -QT_BEGIN_NAMESPACE - -class QSGD3D12RenderContext; - -class QSGD3D12VertexColorMaterial : public QSGD3D12Material -{ -public: - QSGMaterialType *type() const override; - int compare(const QSGMaterial *other) const override; - - int constantBufferSize() const override; - void preparePipeline(QSGD3D12PipelineState *pipelineState) override; - UpdateResults updatePipeline(const QSGD3D12MaterialRenderState &state, - QSGD3D12PipelineState *pipelineState, - ExtraState *extraState, - quint8 *constantBuffer) override; - -private: - static QSGMaterialType mtype; -}; - -class QSGD3D12FlatColorMaterial : public QSGD3D12Material -{ -public: - QSGD3D12FlatColorMaterial(); - QSGMaterialType *type() const override; - int compare(const QSGMaterial *other) const override; - - int constantBufferSize() const override; - void preparePipeline(QSGD3D12PipelineState *pipelineState) override; - UpdateResults updatePipeline(const QSGD3D12MaterialRenderState &state, - QSGD3D12PipelineState *pipelineState, - ExtraState *extraState, - quint8 *constantBuffer) override; - - void setColor(const QColor &color); - QColor color() const { return m_color; } - -private: - static QSGMaterialType mtype; - QColor m_color; -}; - -class QSGD3D12SmoothColorMaterial : public QSGD3D12Material -{ -public: - QSGD3D12SmoothColorMaterial(); - QSGMaterialType *type() const override; - int compare(const QSGMaterial *other) const override; - - int constantBufferSize() const override; - void preparePipeline(QSGD3D12PipelineState *pipelineState) override; - UpdateResults updatePipeline(const QSGD3D12MaterialRenderState &state, - QSGD3D12PipelineState *pipelineState, - ExtraState *extraState, - quint8 *constantBuffer) override; - -private: - static QSGMaterialType mtype; -}; - -class QSGD3D12TextureMaterial : public QSGD3D12Material -{ -public: - QSGMaterialType *type() const override; - int compare(const QSGMaterial *other) const override; - - int constantBufferSize() const override; - void preparePipeline(QSGD3D12PipelineState *pipelineState) override; - UpdateResults updatePipeline(const QSGD3D12MaterialRenderState &state, - QSGD3D12PipelineState *pipelineState, - ExtraState *extraState, - quint8 *constantBuffer) override; - - void setTexture(QSGTexture *texture); - QSGTexture *texture() const { return m_texture; } - - void setMipmapFiltering(QSGTexture::Filtering filter) { m_mipmap_filtering = filter; } - QSGTexture::Filtering mipmapFiltering() const { return m_mipmap_filtering; } - - void setFiltering(QSGTexture::Filtering filter) { m_filtering = filter; } - QSGTexture::Filtering filtering() const { return m_filtering; } - - void setHorizontalWrapMode(QSGTexture::WrapMode hwrap) { m_horizontal_wrap = hwrap; } - QSGTexture::WrapMode horizontalWrapMode() const { return m_horizontal_wrap; } - - void setVerticalWrapMode(QSGTexture::WrapMode vwrap) { m_vertical_wrap = vwrap; } - QSGTexture::WrapMode verticalWrapMode() const { return m_vertical_wrap; } - -private: - static QSGMaterialType mtype; - - QSGTexture *m_texture = nullptr; - QSGTexture::Filtering m_filtering = QSGTexture::Nearest; - QSGTexture::Filtering m_mipmap_filtering = QSGTexture::None; - QSGTexture::WrapMode m_horizontal_wrap = QSGTexture::ClampToEdge; - QSGTexture::WrapMode m_vertical_wrap = QSGTexture::ClampToEdge; -}; - -class QSGD3D12SmoothTextureMaterial : public QSGD3D12Material -{ -public: - QSGD3D12SmoothTextureMaterial(); - - QSGMaterialType *type() const override; - int compare(const QSGMaterial *other) const override; - - int constantBufferSize() const override; - void preparePipeline(QSGD3D12PipelineState *pipelineState) override; - UpdateResults updatePipeline(const QSGD3D12MaterialRenderState &state, - QSGD3D12PipelineState *pipelineState, - ExtraState *extraState, - quint8 *constantBuffer) override; - - void setTexture(QSGTexture *texture) { m_texture = texture; } - QSGTexture *texture() const { return m_texture; } - - void setMipmapFiltering(QSGTexture::Filtering filter) { m_mipmap_filtering = filter; } - QSGTexture::Filtering mipmapFiltering() const { return m_mipmap_filtering; } - - void setFiltering(QSGTexture::Filtering filter) { m_filtering = filter; } - QSGTexture::Filtering filtering() const { return m_filtering; } - - void setHorizontalWrapMode(QSGTexture::WrapMode hwrap) { m_horizontal_wrap = hwrap; } - QSGTexture::WrapMode horizontalWrapMode() const { return m_horizontal_wrap; } - - void setVerticalWrapMode(QSGTexture::WrapMode vwrap) { m_vertical_wrap = vwrap; } - QSGTexture::WrapMode verticalWrapMode() const { return m_vertical_wrap; } - -private: - static QSGMaterialType mtype; - - QSGTexture *m_texture = nullptr; - QSGTexture::Filtering m_filtering = QSGTexture::Nearest; - QSGTexture::Filtering m_mipmap_filtering = QSGTexture::None; - QSGTexture::WrapMode m_horizontal_wrap = QSGTexture::ClampToEdge; - QSGTexture::WrapMode m_vertical_wrap = QSGTexture::ClampToEdge; -}; - -class QSGD3D12TextMaterial : public QSGD3D12Material -{ -public: - enum StyleType { - Normal, - Styled, - Outlined, - - NStyleTypes - }; - QSGD3D12TextMaterial(StyleType styleType, QSGD3D12RenderContext *rc, const QRawFont &font, - QFontEngine::GlyphFormat glyphFormat = QFontEngine::Format_None); - - QSGMaterialType *type() const override; - int compare(const QSGMaterial *other) const override; - - int constantBufferSize() const override; - void preparePipeline(QSGD3D12PipelineState *pipelineState) override; - UpdateResults updatePipeline(const QSGD3D12MaterialRenderState &state, - QSGD3D12PipelineState *pipelineState, - ExtraState *extraState, - quint8 *constantBuffer) override; - - void setColor(const QColor &c) { m_color = QVector4D(c.redF(), c.greenF(), c.blueF(), c.alphaF()); } - void setColor(const QVector4D &color) { m_color = color; } - const QVector4D &color() const { return m_color; } - - void setStyleShift(const QVector2D &shift) { m_styleShift = shift; } - const QVector2D &styleShift() const { return m_styleShift; } - - void setStyleColor(const QColor &c) { m_styleColor = QVector4D(c.redF(), c.greenF(), c.blueF(), c.alphaF()); } - void setStyleColor(const QVector4D &color) { m_styleColor = color; } - const QVector4D &styleColor() const { return m_styleColor; } - - void populate(const QPointF &position, - const QVector &glyphIndexes, const QVector &glyphPositions, - QSGGeometry *geometry, QRectF *boundingRect, QPointF *baseLine, - const QMargins &margins = QMargins(0, 0, 0, 0)); - - QSGD3D12GlyphCache *glyphCache() const { return static_cast(m_glyphCache.data()); } - -private: - static const int NTextMaterialTypes = NStyleTypes * 2; - static QSGMaterialType mtype[NTextMaterialTypes]; - StyleType m_styleType; - QSGD3D12RenderContext *m_rc; - QVector4D m_color; - QVector2D m_styleShift; - QVector4D m_styleColor; - QRawFont m_font; - QExplicitlySharedDataPointer m_glyphCache; -}; - -QT_END_NAMESPACE - -#endif // QSGD3D12BUILTINMATERIALS_P_H diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12context.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12context.cpp deleted file mode 100644 index f9bd04aa54..0000000000 --- a/src/plugins/scenegraph/d3d12/qsgd3d12context.cpp +++ /dev/null @@ -1,143 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include "qsgd3d12context_p.h" -#include "qsgd3d12rendercontext_p.h" -#include "qsgd3d12internalrectanglenode_p.h" -#include "qsgd3d12internalimagenode_p.h" -#include "qsgd3d12glyphnode_p.h" -#include "qsgd3d12layer_p.h" -#include "qsgd3d12shadereffectnode_p.h" -#include "qsgd3d12painternode_p.h" -#include "qsgd3d12publicnodes_p.h" -#include "qsgd3d12spritenode_p.h" -#include - -QT_BEGIN_NAMESPACE - -QSGRenderContext *QSGD3D12Context::createRenderContext() -{ - return new QSGD3D12RenderContext(this); -} - -QSGInternalRectangleNode *QSGD3D12Context::createInternalRectangleNode() -{ - return new QSGD3D12InternalRectangleNode; -} - -QSGInternalImageNode *QSGD3D12Context::createInternalImageNode(QSGRenderContext *renderContext) -{ - Q_UNUSED(renderContext); - return new QSGD3D12InternalImageNode; -} - -QSGPainterNode *QSGD3D12Context::createPainterNode(QQuickPaintedItem *item) -{ - return new QSGD3D12PainterNode(item); -} - -QSGGlyphNode *QSGD3D12Context::createGlyphNode(QSGRenderContext *renderContext, bool preferNativeGlyphNode) -{ - Q_UNUSED(preferNativeGlyphNode); - // ### distance field text rendering is not supported atm - - QSGD3D12RenderContext *rc = static_cast(renderContext); - return new QSGD3D12GlyphNode(rc); -} - -QSGLayer *QSGD3D12Context::createLayer(QSGRenderContext *renderContext) -{ - QSGD3D12RenderContext *rc = static_cast(renderContext); - return new QSGD3D12Layer(rc); -} - -QSGGuiThreadShaderEffectManager *QSGD3D12Context::createGuiThreadShaderEffectManager() -{ - return new QSGD3D12GuiThreadShaderEffectManager; -} - -QSGShaderEffectNode *QSGD3D12Context::createShaderEffectNode(QSGRenderContext *renderContext, - QSGGuiThreadShaderEffectManager *mgr) -{ - QSGD3D12RenderContext *rc = static_cast(renderContext); - QSGD3D12GuiThreadShaderEffectManager *dmgr = static_cast(mgr); - return new QSGD3D12ShaderEffectNode(rc, dmgr); -} - -QSize QSGD3D12Context::minimumFBOSize() const -{ - return QSize(16, 16); -} - -QSurfaceFormat QSGD3D12Context::defaultSurfaceFormat() const -{ - QSurfaceFormat format = QSurfaceFormat::defaultFormat(); - - if (QQuickWindow::hasDefaultAlphaBuffer()) - format.setAlphaBufferSize(8); - - return format; -} - -QSGRendererInterface *QSGD3D12Context::rendererInterface(QSGRenderContext *renderContext) -{ - return static_cast(renderContext); -} - -QSGRectangleNode *QSGD3D12Context::createRectangleNode() -{ - return new QSGD3D12RectangleNode; -} - -QSGImageNode *QSGD3D12Context::createImageNode() -{ - return new QSGD3D12ImageNode; -} - -QSGNinePatchNode *QSGD3D12Context::createNinePatchNode() -{ - return new QSGD3D12NinePatchNode; -} - -QSGSpriteNode *QSGD3D12Context::createSpriteNode() -{ - return new QSGD3D12SpriteNode; -} - -QT_END_NAMESPACE diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12context_p.h b/src/plugins/scenegraph/d3d12/qsgd3d12context_p.h deleted file mode 100644 index 382183fef6..0000000000 --- a/src/plugins/scenegraph/d3d12/qsgd3d12context_p.h +++ /dev/null @@ -1,84 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#ifndef QSGD3D12CONTEXT_P_H -#define QSGD3D12CONTEXT_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include - -QT_BEGIN_NAMESPACE - -class QSGD3D12Context : public QSGContext -{ -public: - QSGD3D12Context(QObject *parent = 0) : QSGContext(parent) { } - - QSGRenderContext *createRenderContext() override; - QSGInternalRectangleNode *createInternalRectangleNode() override; - QSGInternalImageNode *createInternalImageNode(QSGRenderContext *renderContext) override; - QSGPainterNode *createPainterNode(QQuickPaintedItem *item) override; - QSGGlyphNode *createGlyphNode(QSGRenderContext *renderContext, bool preferNativeGlyphNode) override; - QSGLayer *createLayer(QSGRenderContext *renderContext) override; - QSGGuiThreadShaderEffectManager *createGuiThreadShaderEffectManager() override; - QSGShaderEffectNode *createShaderEffectNode(QSGRenderContext *renderContext, - QSGGuiThreadShaderEffectManager *mgr) override; - QSize minimumFBOSize() const override; - QSurfaceFormat defaultSurfaceFormat() const override; - QSGRendererInterface *rendererInterface(QSGRenderContext *renderContext) override; - QSGRectangleNode *createRectangleNode() override; - QSGImageNode *createImageNode() override; - QSGNinePatchNode *createNinePatchNode() override; - QSGSpriteNode *createSpriteNode() override; - -}; - -QT_END_NAMESPACE - -#endif // QSGD3D12CONTEXT_P_H diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp deleted file mode 100644 index 75bde2c66b..0000000000 --- a/src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp +++ /dev/null @@ -1,3280 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include "qsgd3d12engine_p.h" -#include "qsgd3d12engine_p_p.h" -#include "cs_mipmapgen.hlslh" -#include -#include -#include -#include -#include - -// Comment out to disable DeviceLossTester functionality in order to reduce -// code size and improve startup perf a tiny bit. -#define DEVLOSS_TEST - -#ifdef DEVLOSS_TEST -#include "cs_tdr.hlslh" -#endif - -#ifdef Q_OS_WINRT -#include -#include -#include -#include -#endif - -#include - -QT_BEGIN_NAMESPACE - -// NOTE: Avoid categorized logging. It is slow. - -#define DECLARE_DEBUG_VAR(variable) \ - static bool debug_ ## variable() \ - { static bool value = qgetenv("QSG_RENDERER_DEBUG").contains(QT_STRINGIFY(variable)); return value; } - -DECLARE_DEBUG_VAR(render) -DECLARE_DEBUG_VAR(descheap) -DECLARE_DEBUG_VAR(buffer) -DECLARE_DEBUG_VAR(texture) - -// Except for system info on startup. -Q_LOGGING_CATEGORY(QSG_LOG_INFO_GENERAL, "qt.scenegraph.general") - - -// Any changes to the defaults below must be reflected in adaptations.qdoc as -// well and proven by qmlbench or similar. - -static const int DEFAULT_SWAP_CHAIN_BUFFER_COUNT = 3; -static const int DEFAULT_FRAME_IN_FLIGHT_COUNT = 2; -static const int DEFAULT_WAITABLE_SWAP_CHAIN_MAX_LATENCY = 0; - -static const int MAX_DRAW_CALLS_PER_LIST = 4096; - -static const int MAX_CACHED_ROOTSIG = 16; -static const int MAX_CACHED_PSO = 64; - -static const int GPU_CBVSRVUAV_DESCRIPTORS = 512; - -static const DXGI_FORMAT RT_COLOR_FORMAT = DXGI_FORMAT_R8G8B8A8_UNORM; - -static const int BUCKETS_PER_HEAP = 8; // must match freeMap -static const int DESCRIPTORS_PER_BUCKET = 32; // the bit map (freeMap) is quint32 -static const int MAX_DESCRIPTORS_PER_HEAP = BUCKETS_PER_HEAP * DESCRIPTORS_PER_BUCKET; - -static QString comErrorMessage(HRESULT hr) -{ -#ifndef Q_OS_WINRT - const _com_error comError(hr); -#else - const _com_error comError(hr, nullptr); -#endif - QString result = QLatin1String("Error 0x") + QString::number(ulong(hr), 16); - if (const wchar_t *msg = comError.ErrorMessage()) - result += QLatin1String(": ") + QString::fromWCharArray(msg); - return result; -} - -D3D12_CPU_DESCRIPTOR_HANDLE QSGD3D12CPUDescriptorHeapManager::allocate(D3D12_DESCRIPTOR_HEAP_TYPE type) -{ - D3D12_CPU_DESCRIPTOR_HANDLE h = {}; - for (Heap &heap : m_heaps) { - if (heap.type == type) { - for (int bucket = 0; bucket < _countof(heap.freeMap); ++bucket) - if (heap.freeMap[bucket]) { - uint freePos = qCountTrailingZeroBits(heap.freeMap[bucket]); - heap.freeMap[bucket] &= ~(1UL << freePos); - if (Q_UNLIKELY(debug_descheap())) - qDebug("descriptor handle heap %p type %x reserve in bucket %d index %d", &heap, type, bucket, freePos); - freePos += bucket * DESCRIPTORS_PER_BUCKET; - h = heap.start; - h.ptr += freePos * heap.handleSize; - return h; - } - } - } - - Heap heap; - heap.type = type; - heap.handleSize = m_handleSizes[type]; - - D3D12_DESCRIPTOR_HEAP_DESC heapDesc = {}; - heapDesc.NumDescriptors = MAX_DESCRIPTORS_PER_HEAP; - heapDesc.Type = type; - // The heaps created here are _never_ shader-visible. - - HRESULT hr = m_device->CreateDescriptorHeap(&heapDesc, IID_PPV_ARGS(&heap.heap)); - if (FAILED(hr)) { - qWarning("Failed to create heap with type 0x%x: %s", - type, qPrintable(comErrorMessage(hr))); - return h; - } - - heap.start = heap.heap->GetCPUDescriptorHandleForHeapStart(); - - if (Q_UNLIKELY(debug_descheap())) - qDebug("new descriptor heap, type %x, start %llu", type, heap.start.ptr); - - heap.freeMap[0] = 0xFFFFFFFE; - for (int i = 1; i < _countof(heap.freeMap); ++i) - heap.freeMap[i] = 0xFFFFFFFF; - - h = heap.start; - - m_heaps.append(heap); - - return h; -} - -void QSGD3D12CPUDescriptorHeapManager::release(D3D12_CPU_DESCRIPTOR_HANDLE handle, D3D12_DESCRIPTOR_HEAP_TYPE type) -{ - for (Heap &heap : m_heaps) { - if (heap.type == type - && handle.ptr >= heap.start.ptr - && handle.ptr < heap.start.ptr + heap.handleSize * MAX_DESCRIPTORS_PER_HEAP) { - unsigned long pos = (handle.ptr - heap.start.ptr) / heap.handleSize; - const int bucket = pos / DESCRIPTORS_PER_BUCKET; - const int indexInBucket = pos - bucket * DESCRIPTORS_PER_BUCKET; - heap.freeMap[bucket] |= 1UL << indexInBucket; - if (Q_UNLIKELY(debug_descheap())) - qDebug("free descriptor handle heap %p type %x bucket %d index %d", &heap, type, bucket, indexInBucket); - return; - } - } - qWarning("QSGD3D12CPUDescriptorHeapManager: Attempted to release untracked descriptor handle %llu of type %d", handle.ptr, type); -} - -void QSGD3D12CPUDescriptorHeapManager::initialize(ID3D12Device *device) -{ - m_device = device; - - for (int i = 0; i < D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES; ++i) - m_handleSizes[i] = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE(i)); -} - -void QSGD3D12CPUDescriptorHeapManager::releaseResources() -{ - for (Heap &heap : m_heaps) - heap.heap = nullptr; - - m_heaps.clear(); - - m_device = nullptr; -} - -// One device per process, one everything else (engine) per window. -Q_GLOBAL_STATIC(QSGD3D12DeviceManager, deviceManager) - -static void getHardwareAdapter(IDXGIFactory1 *factory, IDXGIAdapter1 **outAdapter) -{ - const D3D_FEATURE_LEVEL fl = D3D_FEATURE_LEVEL_11_0; - ComPtr adapter; - DXGI_ADAPTER_DESC1 desc; - - for (int adapterIndex = 0; factory->EnumAdapters1(adapterIndex, &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) { - DXGI_ADAPTER_DESC1 desc; - adapter->GetDesc1(&desc); - const QString name = QString::fromUtf16((char16_t *) desc.Description); - qCDebug(QSG_LOG_INFO_GENERAL, "Adapter %d: '%s' (flags 0x%x)", adapterIndex, qPrintable(name), desc.Flags); - } - - if (qEnvironmentVariableIsSet("QT_D3D_ADAPTER_INDEX")) { - const int adapterIndex = qEnvironmentVariableIntValue("QT_D3D_ADAPTER_INDEX"); - if (SUCCEEDED(factory->EnumAdapters1(adapterIndex, &adapter))) { - adapter->GetDesc1(&desc); - const QString name = QString::fromUtf16((char16_t *) desc.Description); - HRESULT hr = D3D12CreateDevice(adapter.Get(), fl, _uuidof(ID3D12Device), nullptr); - if (SUCCEEDED(hr)) { - qCDebug(QSG_LOG_INFO_GENERAL, "Using requested adapter '%s'", qPrintable(name)); - *outAdapter = adapter.Detach(); - return; - } else { - qWarning("Failed to create device for requested adapter '%s': %s", - qPrintable(name), qPrintable(comErrorMessage(hr))); - } - } - } - - for (int adapterIndex = 0; factory->EnumAdapters1(adapterIndex, &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) { - adapter->GetDesc1(&desc); - if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) - continue; - - if (SUCCEEDED(D3D12CreateDevice(adapter.Get(), fl, _uuidof(ID3D12Device), nullptr))) { - const QString name = QString::fromUtf16((char16_t *) desc.Description); - qCDebug(QSG_LOG_INFO_GENERAL, "Using adapter '%s'", qPrintable(name)); - break; - } - } - - *outAdapter = adapter.Detach(); -} - -ID3D12Device *QSGD3D12DeviceManager::ref() -{ - ensureCreated(); - m_ref.ref(); - return m_device.Get(); -} - -void QSGD3D12DeviceManager::unref() -{ - if (!m_ref.deref()) { - if (Q_UNLIKELY(debug_render())) - qDebug("destroying d3d device"); - m_device = nullptr; - m_factory = nullptr; - } -} - -void QSGD3D12DeviceManager::deviceLossDetected() -{ - for (DeviceLossObserver *observer : qAsConst(m_observers)) - observer->deviceLost(); - - // Nothing else to do here. All windows are expected to release their - // resources and call unref() in response immediately. -} - -IDXGIFactory4 *QSGD3D12DeviceManager::dxgi() -{ - ensureCreated(); - return m_factory.Get(); -} - -void QSGD3D12DeviceManager::ensureCreated() -{ - if (m_device) - return; - - HRESULT hr = CreateDXGIFactory2(0, IID_PPV_ARGS(&m_factory)); - if (FAILED(hr)) { - qWarning("Failed to create DXGI: %s", qPrintable(comErrorMessage(hr))); - return; - } - - ComPtr adapter; - getHardwareAdapter(m_factory.Get(), &adapter); - - bool warp = true; - if (adapter) { - HRESULT hr = D3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device)); - if (SUCCEEDED(hr)) - warp = false; - else - qWarning("Failed to create device: %s", qPrintable(comErrorMessage(hr))); - } - - if (warp) { - qCDebug(QSG_LOG_INFO_GENERAL, "Using WARP"); - m_factory->EnumWarpAdapter(IID_PPV_ARGS(&adapter)); - HRESULT hr = D3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device)); - if (FAILED(hr)) { - qWarning("Failed to create WARP device: %s", qPrintable(comErrorMessage(hr))); - return; - } - } - - ComPtr adapter3; - if (SUCCEEDED(adapter.As(&adapter3))) { - DXGI_QUERY_VIDEO_MEMORY_INFO vidMemInfo; - if (SUCCEEDED(adapter3->QueryVideoMemoryInfo(0, DXGI_MEMORY_SEGMENT_GROUP_LOCAL, &vidMemInfo))) { - qCDebug(QSG_LOG_INFO_GENERAL, "Video memory info: LOCAL: Budget %llu KB CurrentUsage %llu KB AvailableForReservation %llu KB CurrentReservation %llu KB", - vidMemInfo.Budget / 1024, vidMemInfo.CurrentUsage / 1024, - vidMemInfo.AvailableForReservation / 1024, vidMemInfo.CurrentReservation / 1024); - } - if (SUCCEEDED(adapter3->QueryVideoMemoryInfo(0, DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL, &vidMemInfo))) { - qCDebug(QSG_LOG_INFO_GENERAL, "Video memory info: NON-LOCAL: Budget %llu KB CurrentUsage %llu KB AvailableForReservation %llu KB CurrentReservation %llu KB", - vidMemInfo.Budget / 1024, vidMemInfo.CurrentUsage / 1024, - vidMemInfo.AvailableForReservation / 1024, vidMemInfo.CurrentReservation / 1024); - } - } -} - -void QSGD3D12DeviceManager::registerDeviceLossObserver(DeviceLossObserver *observer) -{ - if (!m_observers.contains(observer)) - m_observers.append(observer); -} - -QSGD3D12Engine::QSGD3D12Engine() -{ - d = new QSGD3D12EnginePrivate; -} - -QSGD3D12Engine::~QSGD3D12Engine() -{ - d->waitGPU(); - d->releaseResources(); - delete d; -} - -bool QSGD3D12Engine::attachToWindow(WId window, const QSize &size, float dpr, int surfaceFormatSamples, bool alpha) -{ - if (d->isInitialized()) { - qWarning("QSGD3D12Engine: Cannot attach active engine to window"); - return false; - } - - d->initialize(window, size, dpr, surfaceFormatSamples, alpha); - return d->isInitialized(); -} - -void QSGD3D12Engine::releaseResources() -{ - d->releaseResources(); -} - -bool QSGD3D12Engine::hasResources() const -{ - // An explicit releaseResources() or a device loss results in initialized == false. - return d->isInitialized(); -} - -void QSGD3D12Engine::setWindowSize(const QSize &size, float dpr) -{ - d->setWindowSize(size, dpr); -} - -WId QSGD3D12Engine::window() const -{ - return d->currentWindow(); -} - -QSize QSGD3D12Engine::windowSize() const -{ - return d->currentWindowSize(); -} - -float QSGD3D12Engine::windowDevicePixelRatio() const -{ - return d->currentWindowDpr(); -} - -uint QSGD3D12Engine::windowSamples() const -{ - return d->currentWindowSamples(); -} - -void QSGD3D12Engine::beginFrame() -{ - d->beginFrame(); -} - -void QSGD3D12Engine::endFrame() -{ - d->endFrame(); -} - -void QSGD3D12Engine::beginLayer() -{ - d->beginLayer(); -} - -void QSGD3D12Engine::endLayer() -{ - d->endLayer(); -} - -void QSGD3D12Engine::invalidateCachedFrameState() -{ - d->invalidateCachedFrameState(); -} - -void QSGD3D12Engine::restoreFrameState(bool minimal) -{ - d->restoreFrameState(minimal); -} - -void QSGD3D12Engine::finalizePipeline(const QSGD3D12PipelineState &pipelineState) -{ - d->finalizePipeline(pipelineState); -} - -uint QSGD3D12Engine::genBuffer() -{ - return d->genBuffer(); -} - -void QSGD3D12Engine::releaseBuffer(uint id) -{ - d->releaseBuffer(id); -} - -void QSGD3D12Engine::resetBuffer(uint id, const quint8 *data, int size) -{ - d->resetBuffer(id, data, size); -} - -void QSGD3D12Engine::markBufferDirty(uint id, int offset, int size) -{ - d->markBufferDirty(id, offset, size); -} - -void QSGD3D12Engine::queueViewport(const QRect &rect) -{ - d->queueViewport(rect); -} - -void QSGD3D12Engine::queueScissor(const QRect &rect) -{ - d->queueScissor(rect); -} - -void QSGD3D12Engine::queueSetRenderTarget(uint id) -{ - d->queueSetRenderTarget(id); -} - -void QSGD3D12Engine::queueClearRenderTarget(const QColor &color) -{ - d->queueClearRenderTarget(color); -} - -void QSGD3D12Engine::queueClearDepthStencil(float depthValue, quint8 stencilValue, ClearFlags which) -{ - d->queueClearDepthStencil(depthValue, stencilValue, which); -} - -void QSGD3D12Engine::queueSetBlendFactor(const QVector4D &factor) -{ - d->queueSetBlendFactor(factor); -} - -void QSGD3D12Engine::queueSetStencilRef(quint32 ref) -{ - d->queueSetStencilRef(ref); -} - -void QSGD3D12Engine::queueDraw(const DrawParams ¶ms) -{ - d->queueDraw(params); -} - -void QSGD3D12Engine::present() -{ - d->present(); -} - -void QSGD3D12Engine::waitGPU() -{ - d->waitGPU(); -} - -uint QSGD3D12Engine::genTexture() -{ - return d->genTexture(); -} - -void QSGD3D12Engine::createTexture(uint id, const QSize &size, QImage::Format format, TextureCreateFlags flags) -{ - d->createTexture(id, size, format, flags); -} - -void QSGD3D12Engine::queueTextureResize(uint id, const QSize &size) -{ - d->queueTextureResize(id, size); -} - -void QSGD3D12Engine::queueTextureUpload(uint id, const QImage &image, const QPoint &dstPos, TextureUploadFlags flags) -{ - d->queueTextureUpload(id, QVector() << image, QVector() << dstPos, flags); -} - -void QSGD3D12Engine::queueTextureUpload(uint id, const QVector &images, const QVector &dstPos, - TextureUploadFlags flags) -{ - d->queueTextureUpload(id, images, dstPos, flags); -} - -void QSGD3D12Engine::releaseTexture(uint id) -{ - d->releaseTexture(id); -} - -void QSGD3D12Engine::useTexture(uint id) -{ - d->useTexture(id); -} - -uint QSGD3D12Engine::genRenderTarget() -{ - return d->genRenderTarget(); -} - -void QSGD3D12Engine::createRenderTarget(uint id, const QSize &size, const QVector4D &clearColor, uint samples) -{ - d->createRenderTarget(id, size, clearColor, samples); -} - -void QSGD3D12Engine::releaseRenderTarget(uint id) -{ - d->releaseRenderTarget(id); -} - -void QSGD3D12Engine::useRenderTargetAsTexture(uint id) -{ - d->useRenderTargetAsTexture(id); -} - -uint QSGD3D12Engine::activeRenderTarget() const -{ - return d->activeRenderTarget(); -} - -QImage QSGD3D12Engine::executeAndWaitReadbackRenderTarget(uint id) -{ - return d->executeAndWaitReadbackRenderTarget(id); -} - -void QSGD3D12Engine::simulateDeviceLoss() -{ - d->simulateDeviceLoss(); -} - -void *QSGD3D12Engine::getResource(QQuickWindow *, QSGRendererInterface::Resource resource) const -{ - return d->getResource(resource); -} - -static inline quint32 alignedSize(quint32 size, quint32 byteAlign) -{ - return (size + byteAlign - 1) & ~(byteAlign - 1); -} - -quint32 QSGD3D12Engine::alignedConstantBufferSize(quint32 size) -{ - return alignedSize(size, D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT); -} - -QSGD3D12Format QSGD3D12Engine::toDXGIFormat(QSGGeometry::Type sgtype, int tupleSize, int *size) -{ - QSGD3D12Format format = FmtUnknown; - - static const QSGD3D12Format formatMap_ub[] = { FmtUnknown, - FmtUNormByte, - FmtUNormByte2, - FmtUnknown, - FmtUNormByte4 }; - - static const QSGD3D12Format formatMap_f[] = { FmtUnknown, - FmtFloat, - FmtFloat2, - FmtFloat3, - FmtFloat4 }; - - switch (sgtype) { - case QSGGeometry::UnsignedByteType: - format = formatMap_ub[tupleSize]; - if (size) - *size = tupleSize; - break; - case QSGGeometry::FloatType: - format = formatMap_f[tupleSize]; - if (size) - *size = sizeof(float) * tupleSize; - break; - - case QSGGeometry::UnsignedShortType: - format = FmtUnsignedShort; - if (size) - *size = sizeof(ushort) * tupleSize; - break; - case QSGGeometry::UnsignedIntType: - format = FmtUnsignedInt; - if (size) - *size = sizeof(uint) * tupleSize; - break; - - case QSGGeometry::ByteType: - case QSGGeometry::IntType: - case QSGGeometry::ShortType: - qWarning("no mapping for GL type 0x%x", sgtype); - break; - - default: - qWarning("unknown GL type 0x%x", sgtype); - break; - } - - return format; -} - -int QSGD3D12Engine::mipMapLevels(const QSize &size) -{ - return ceil(log2(qMax(size.width(), size.height()))) + 1; -} - -inline static bool isPowerOfTwo(int x) -{ - // Assumption: x >= 1 - return x == (x & -x); -} - -QSize QSGD3D12Engine::mipMapAdjustedSourceSize(const QSize &size) -{ - if (size.isEmpty()) - return size; - - QSize adjustedSize = size; - - // ### for now only power-of-two sizes are mipmap-capable - if (!isPowerOfTwo(size.width())) - adjustedSize.setWidth(qNextPowerOfTwo(size.width())); - if (!isPowerOfTwo(size.height())) - adjustedSize.setHeight(qNextPowerOfTwo(size.height())); - - return adjustedSize; -} - -void QSGD3D12EnginePrivate::releaseResources() -{ - if (!initialized) - return; - - mipmapper.releaseResources(); - devLossTest.releaseResources(); - - frameCommandList = nullptr; - copyCommandList = nullptr; - - copyCommandAllocator = nullptr; - for (int i = 0; i < frameInFlightCount; ++i) { - frameCommandAllocator[i] = nullptr; - pframeData[i].gpuCbvSrvUavHeap = nullptr; - delete frameFence[i]; - } - - defaultDS = nullptr; - for (int i = 0; i < swapChainBufferCount; ++i) { - backBufferRT[i] = nullptr; - defaultRT[i] = nullptr; - } - - psoCache.clear(); - rootSigCache.clear(); - buffers.clear(); - textures.clear(); - renderTargets.clear(); - - cpuDescHeapManager.releaseResources(); - - commandQueue = nullptr; - copyCommandQueue = nullptr; - -#ifndef Q_OS_WINRT - dcompTarget = nullptr; - dcompVisual = nullptr; - dcompDevice = nullptr; -#endif - - swapChain = nullptr; - - delete presentFence; - textureUploadFence = nullptr; - - deviceManager()->unref(); - - initialized = false; - - // 'window' must be kept, may just be a device loss -} - -void QSGD3D12EnginePrivate::initialize(WId w, const QSize &size, float dpr, int surfaceFormatSamples, bool alpha) -{ - if (initialized) - return; - - window = w; - windowSize = size; - windowDpr = dpr; - windowSamples = qMax(1, surfaceFormatSamples); // may be -1 or 0, whereas windowSamples is uint and >= 1 - windowAlpha = alpha; - - swapChainBufferCount = qMin(qEnvironmentVariableIntValue("QT_D3D_BUFFER_COUNT"), MAX_SWAP_CHAIN_BUFFER_COUNT); - if (swapChainBufferCount < 2) - swapChainBufferCount = DEFAULT_SWAP_CHAIN_BUFFER_COUNT; - - frameInFlightCount = qMin(qEnvironmentVariableIntValue("QT_D3D_FRAME_COUNT"), MAX_FRAME_IN_FLIGHT_COUNT); - if (frameInFlightCount < 1) - frameInFlightCount = DEFAULT_FRAME_IN_FLIGHT_COUNT; - - static const char *latReqEnvVar = "QT_D3D_WAITABLE_SWAP_CHAIN_MAX_LATENCY"; - if (!qEnvironmentVariableIsSet(latReqEnvVar)) - waitableSwapChainMaxLatency = DEFAULT_WAITABLE_SWAP_CHAIN_MAX_LATENCY; - else - waitableSwapChainMaxLatency = qBound(0, qEnvironmentVariableIntValue(latReqEnvVar), 16); - - if (qEnvironmentVariableIsSet("QSG_INFO")) - const_cast(QSG_LOG_INFO_GENERAL()).setEnabled(QtDebugMsg, true); - - qCDebug(QSG_LOG_INFO_GENERAL, "d3d12 engine init. swap chain buffer count %d, max frames prepared without blocking %d", - swapChainBufferCount, frameInFlightCount); - if (waitableSwapChainMaxLatency) - qCDebug(QSG_LOG_INFO_GENERAL, "Swap chain frame latency waitable object enabled. Frame latency is %d", waitableSwapChainMaxLatency); - - const bool debugLayer = qEnvironmentVariableIntValue("QT_D3D_DEBUG") != 0; - if (debugLayer) { - qCDebug(QSG_LOG_INFO_GENERAL, "Enabling debug layer"); -#if !defined(Q_OS_WINRT) || !defined(NDEBUG) - ComPtr debugController; - if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController)))) - debugController->EnableDebugLayer(); -#else - qCDebug(QSG_LOG_INFO_GENERAL, "Using DebugInterface will not allow certification to pass"); -#endif - } - - QSGD3D12DeviceManager *dev = deviceManager(); - device = dev->ref(); - dev->registerDeviceLossObserver(this); - - if (debugLayer) { - ComPtr infoQueue; - if (SUCCEEDED(device->QueryInterface(IID_PPV_ARGS(&infoQueue)))) { - infoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_CORRUPTION, true); - infoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_ERROR, true); - const bool breakOnWarning = qEnvironmentVariableIntValue("QT_D3D_DEBUG_BREAK_ON_WARNING") != 0; - infoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_WARNING, breakOnWarning); - D3D12_INFO_QUEUE_FILTER filter = {}; - D3D12_MESSAGE_ID suppressedMessages[] = { - // When using a render target other than the default one we - // have no way to know the custom clear color, if there is one. - D3D12_MESSAGE_ID_CLEARRENDERTARGETVIEW_MISMATCHINGCLEARVALUE - }; - filter.DenyList.NumIDs = _countof(suppressedMessages); - filter.DenyList.pIDList = suppressedMessages; - // setting the filter would enable Info messages which we don't need - D3D12_MESSAGE_SEVERITY infoSev = D3D12_MESSAGE_SEVERITY_INFO; - filter.DenyList.NumSeverities = 1; - filter.DenyList.pSeverityList = &infoSev; - infoQueue->PushStorageFilter(&filter); - } - } - - D3D12_COMMAND_QUEUE_DESC queueDesc = {}; - queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; - if (FAILED(device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&commandQueue)))) { - qWarning("Failed to create command queue"); - return; - } - - queueDesc.Type = D3D12_COMMAND_LIST_TYPE_COPY; - if (FAILED(device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(©CommandQueue)))) { - qWarning("Failed to create copy command queue"); - return; - } - -#ifndef Q_OS_WINRT - HWND hwnd = reinterpret_cast(w); - - if (windowAlpha) { - // Go through DirectComposition for semi-transparent windows since the - // traditional approaches won't fly with flip model swapchains. - HRESULT hr = DCompositionCreateDevice(nullptr, IID_PPV_ARGS(&dcompDevice)); - if (SUCCEEDED(hr)) { - hr = dcompDevice->CreateTargetForHwnd(hwnd, true, &dcompTarget); - if (SUCCEEDED(hr)) { - hr = dcompDevice->CreateVisual(&dcompVisual); - if (FAILED(hr)) { - qWarning("Failed to create DirectComposition visual: %s", - qPrintable(comErrorMessage(hr))); - windowAlpha = false; - } - } else { - qWarning("Failed to create DirectComposition target: %s", - qPrintable(comErrorMessage(hr))); - windowAlpha = false; - } - } else { - qWarning("Failed to create DirectComposition device: %s", - qPrintable(comErrorMessage(hr))); - windowAlpha = false; - } - } - - if (windowAlpha) { - DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; - swapChainDesc.Width = windowSize.width() * windowDpr; - swapChainDesc.Height = windowSize.height() * windowDpr; - swapChainDesc.Format = RT_COLOR_FORMAT; - swapChainDesc.SampleDesc.Count = 1; - swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; - swapChainDesc.BufferCount = swapChainBufferCount; - swapChainDesc.Scaling = DXGI_SCALING_STRETCH; - swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; - swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED; - if (waitableSwapChainMaxLatency) - swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT; - - ComPtr baseSwapChain; - HRESULT hr = dev->dxgi()->CreateSwapChainForComposition(commandQueue.Get(), &swapChainDesc, nullptr, &baseSwapChain); - if (SUCCEEDED(hr)) { - if (SUCCEEDED(baseSwapChain.As(&swapChain))) { - hr = dcompVisual->SetContent(swapChain.Get()); - if (SUCCEEDED(hr)) { - hr = dcompTarget->SetRoot(dcompVisual.Get()); - if (FAILED(hr)) { - qWarning("SetRoot failed for DirectComposition target: %s", - qPrintable(comErrorMessage(hr))); - windowAlpha = false; - } - } else { - qWarning("SetContent failed for DirectComposition visual: %s", - qPrintable(comErrorMessage(hr))); - windowAlpha = false; - } - } else { - qWarning("Failed to cast swap chain"); - windowAlpha = false; - } - } else { - qWarning("Failed to create swap chain for composition: 0x%x", hr); - windowAlpha = false; - } - } - - if (!windowAlpha) { - DXGI_SWAP_CHAIN_DESC swapChainDesc = {}; - swapChainDesc.BufferCount = swapChainBufferCount; - swapChainDesc.BufferDesc.Width = windowSize.width() * windowDpr; - swapChainDesc.BufferDesc.Height = windowSize.height() * windowDpr; - swapChainDesc.BufferDesc.Format = RT_COLOR_FORMAT; - swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; - swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; // D3D12 requires the flip model - swapChainDesc.OutputWindow = hwnd; - swapChainDesc.SampleDesc.Count = 1; // Flip does not support MSAA so no choice here - swapChainDesc.Windowed = TRUE; - if (waitableSwapChainMaxLatency) - swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT; - - ComPtr baseSwapChain; - HRESULT hr = dev->dxgi()->CreateSwapChain(commandQueue.Get(), &swapChainDesc, &baseSwapChain); - if (FAILED(hr)) { - qWarning("Failed to create swap chain: %s", qPrintable(comErrorMessage(hr))); - return; - } - hr = baseSwapChain.As(&swapChain); - if (FAILED(hr)) { - qWarning("Failed to cast swap chain: %s", qPrintable(comErrorMessage(hr))); - return; - } - } - - dev->dxgi()->MakeWindowAssociation(hwnd, DXGI_MWA_NO_ALT_ENTER); -#else - DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; - swapChainDesc.Width = windowSize.width() * windowDpr; - swapChainDesc.Height = windowSize.height() * windowDpr; - swapChainDesc.Format = RT_COLOR_FORMAT; - swapChainDesc.SampleDesc.Count = 1; - swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; - swapChainDesc.BufferCount = swapChainBufferCount; - swapChainDesc.Scaling = DXGI_SCALING_STRETCH; - swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; - swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED; - if (waitableSwapChainMaxLatency) - swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT; - - ComPtr baseSwapChain; - HRESULT hr = dev->dxgi()->CreateSwapChainForComposition(commandQueue.Get(), &swapChainDesc, nullptr, &baseSwapChain); - if (FAILED(hr)) { - qWarning("Failed to create swap chain for composition: 0x%x", hr); - return; - } - if (FAILED(baseSwapChain.As(&swapChain))) { - qWarning("Failed to cast swap chain"); - return; - } - - // The winrt platform plugin returns an ISwapChainPanel* from winId(). - ComPtr swapChainPanel - = reinterpret_cast(window); - ComPtr swapChainPanelNative; - if (FAILED(swapChainPanel.As(&swapChainPanelNative))) { - qWarning("Failed to cast swap chain panel to native"); - return; - } - hr = QEventDispatcherWinRT::runOnXamlThread([this, &swapChainPanelNative]() { - return swapChainPanelNative->SetSwapChain(swapChain.Get()); - }); - if (FAILED(hr)) { - qWarning("Failed to set swap chain on panel: 0x%x", hr); - return; - } -#endif - - if (waitableSwapChainMaxLatency) { - if (FAILED(swapChain->SetMaximumFrameLatency(waitableSwapChainMaxLatency))) - qWarning("Failed to set maximum frame latency to %d", waitableSwapChainMaxLatency); - swapEvent = swapChain->GetFrameLatencyWaitableObject(); - } - - for (int i = 0; i < frameInFlightCount; ++i) { - if (FAILED(device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&frameCommandAllocator[i])))) { - qWarning("Failed to create command allocator"); - return; - } - } - - if (FAILED(device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_COPY, IID_PPV_ARGS(©CommandAllocator)))) { - qWarning("Failed to create copy command allocator"); - return; - } - - for (int i = 0; i < frameInFlightCount; ++i) { - if (!createCbvSrvUavHeap(i, GPU_CBVSRVUAV_DESCRIPTORS)) - return; - } - - cpuDescHeapManager.initialize(device); - - setupDefaultRenderTargets(); - - if (FAILED(device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, frameCommandAllocator[0].Get(), - nullptr, IID_PPV_ARGS(&frameCommandList)))) { - qWarning("Failed to create command list"); - return; - } - // created in recording state, close it for now - frameCommandList->Close(); - - if (FAILED(device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_COPY, copyCommandAllocator.Get(), - nullptr, IID_PPV_ARGS(©CommandList)))) { - qWarning("Failed to create copy command list"); - return; - } - copyCommandList->Close(); - - frameIndex = 0; - - presentFence = createCPUWaitableFence(); - for (int i = 0; i < frameInFlightCount; ++i) - frameFence[i] = createCPUWaitableFence(); - - if (FAILED(device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&textureUploadFence)))) { - qWarning("Failed to create fence"); - return; - } - - psoCache.setMaxCost(MAX_CACHED_PSO); - rootSigCache.setMaxCost(MAX_CACHED_ROOTSIG); - - if (!mipmapper.initialize(this)) - return; - - if (!devLossTest.initialize(this)) - return; - - currentRenderTarget = 0; - - initialized = true; -} - -bool QSGD3D12EnginePrivate::createCbvSrvUavHeap(int pframeIndex, int descriptorCount) -{ - D3D12_DESCRIPTOR_HEAP_DESC gpuDescHeapDesc = {}; - gpuDescHeapDesc.NumDescriptors = descriptorCount; - gpuDescHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; - gpuDescHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; - - if (FAILED(device->CreateDescriptorHeap(&gpuDescHeapDesc, IID_PPV_ARGS(&pframeData[pframeIndex].gpuCbvSrvUavHeap)))) { - qWarning("Failed to create shader-visible CBV-SRV-UAV heap"); - return false; - } - - pframeData[pframeIndex].gpuCbvSrvUavHeapSize = descriptorCount; - - return true; -} - -DXGI_SAMPLE_DESC QSGD3D12EnginePrivate::makeSampleDesc(DXGI_FORMAT format, uint samples) -{ - DXGI_SAMPLE_DESC sampleDesc; - sampleDesc.Count = 1; - sampleDesc.Quality = 0; - - if (samples > 1) { - D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS msaaInfo = {}; - msaaInfo.Format = format; - msaaInfo.SampleCount = samples; - if (SUCCEEDED(device->CheckFeatureSupport(D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS, &msaaInfo, sizeof(msaaInfo)))) { - if (msaaInfo.NumQualityLevels > 0) { - sampleDesc.Count = samples; - sampleDesc.Quality = msaaInfo.NumQualityLevels - 1; - } else { - qWarning("No quality levels for multisampling with sample count %d", samples); - } - } else { - qWarning("Failed to query multisample quality levels for sample count %d", samples); - } - } - - return sampleDesc; -} - -ID3D12Resource *QSGD3D12EnginePrivate::createColorBuffer(D3D12_CPU_DESCRIPTOR_HANDLE viewHandle, const QSize &size, - const QVector4D &clearColor, uint samples) -{ - D3D12_CLEAR_VALUE clearValue = {}; - clearValue.Format = RT_COLOR_FORMAT; - clearValue.Color[0] = clearColor.x(); - clearValue.Color[1] = clearColor.y(); - clearValue.Color[2] = clearColor.z(); - clearValue.Color[3] = clearColor.w(); - - D3D12_HEAP_PROPERTIES heapProp = {}; - heapProp.Type = D3D12_HEAP_TYPE_DEFAULT; - - D3D12_RESOURCE_DESC rtDesc = {}; - rtDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; - rtDesc.Width = size.width(); - rtDesc.Height = size.height(); - rtDesc.DepthOrArraySize = 1; - rtDesc.MipLevels = 1; - rtDesc.Format = RT_COLOR_FORMAT; - rtDesc.SampleDesc = makeSampleDesc(rtDesc.Format, samples); - rtDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; - - ID3D12Resource *resource = nullptr; - const D3D12_RESOURCE_STATES initialState = samples <= 1 - ? D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE - : D3D12_RESOURCE_STATE_RENDER_TARGET; - if (FAILED(device->CreateCommittedResource(&heapProp, D3D12_HEAP_FLAG_NONE, &rtDesc, - initialState, &clearValue, IID_PPV_ARGS(&resource)))) { - qWarning("Failed to create offscreen render target of size %dx%d", size.width(), size.height()); - return nullptr; - } - - device->CreateRenderTargetView(resource, nullptr, viewHandle); - - return resource; -} - -ID3D12Resource *QSGD3D12EnginePrivate::createDepthStencil(D3D12_CPU_DESCRIPTOR_HANDLE viewHandle, const QSize &size, uint samples) -{ - D3D12_CLEAR_VALUE depthClearValue = {}; - depthClearValue.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; - depthClearValue.DepthStencil.Depth = 1.0f; - depthClearValue.DepthStencil.Stencil = 0; - - D3D12_HEAP_PROPERTIES heapProp = {}; - heapProp.Type = D3D12_HEAP_TYPE_DEFAULT; - - D3D12_RESOURCE_DESC bufDesc = {}; - bufDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; - bufDesc.Width = size.width(); - bufDesc.Height = size.height(); - bufDesc.DepthOrArraySize = 1; - bufDesc.MipLevels = 1; - bufDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; - bufDesc.SampleDesc = makeSampleDesc(bufDesc.Format, samples); - bufDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; - bufDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; - - ID3D12Resource *resource = nullptr; - if (FAILED(device->CreateCommittedResource(&heapProp, D3D12_HEAP_FLAG_NONE, &bufDesc, - D3D12_RESOURCE_STATE_DEPTH_WRITE, &depthClearValue, IID_PPV_ARGS(&resource)))) { - qWarning("Failed to create depth-stencil buffer of size %dx%d", size.width(), size.height()); - return nullptr; - } - - D3D12_DEPTH_STENCIL_VIEW_DESC depthStencilDesc = {}; - depthStencilDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; - depthStencilDesc.ViewDimension = bufDesc.SampleDesc.Count <= 1 ? D3D12_DSV_DIMENSION_TEXTURE2D : D3D12_DSV_DIMENSION_TEXTURE2DMS; - - device->CreateDepthStencilView(resource, &depthStencilDesc, viewHandle); - - return resource; -} - -void QSGD3D12EnginePrivate::setupDefaultRenderTargets() -{ - for (int i = 0; i < swapChainBufferCount; ++i) { - if (FAILED(swapChain->GetBuffer(i, IID_PPV_ARGS(&backBufferRT[i])))) { - qWarning("Failed to get buffer %d from swap chain", i); - return; - } - defaultRTV[i] = cpuDescHeapManager.allocate(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); - if (windowSamples == 1) { - defaultRT[i] = backBufferRT[i]; - device->CreateRenderTargetView(defaultRT[i].Get(), nullptr, defaultRTV[i]); - } else { - const QSize size(windowSize.width() * windowDpr, windowSize.height() * windowDpr); - // Not optimal if the user called setClearColor, but there's so - // much we can do. The debug layer warning is suppressed so we're good to go. - const QColor cc(Qt::white); - const QVector4D clearColor(cc.redF(), cc.greenF(), cc.blueF(), cc.alphaF()); - ID3D12Resource *msaaRT = createColorBuffer(defaultRTV[i], size, clearColor, windowSamples); - if (msaaRT) - defaultRT[i].Attach(msaaRT); - } - } - - defaultDSV = cpuDescHeapManager.allocate(D3D12_DESCRIPTOR_HEAP_TYPE_DSV); - const QSize size(windowSize.width() * windowDpr, windowSize.height() * windowDpr); - ID3D12Resource *ds = createDepthStencil(defaultDSV, size, windowSamples); - if (ds) - defaultDS.Attach(ds); - - presentFrameIndex = 0; -} - -void QSGD3D12EnginePrivate::setWindowSize(const QSize &size, float dpr) -{ - if (!initialized || (windowSize == size && windowDpr == dpr)) - return; - - waitGPU(); - - windowSize = size; - windowDpr = dpr; - - if (Q_UNLIKELY(debug_render())) - qDebug() << "resize" << size << dpr; - - // Clear these, otherwise resizing will fail. - defaultDS = nullptr; - cpuDescHeapManager.release(defaultDSV, D3D12_DESCRIPTOR_HEAP_TYPE_DSV); - for (int i = 0; i < swapChainBufferCount; ++i) { - backBufferRT[i] = nullptr; - defaultRT[i] = nullptr; - cpuDescHeapManager.release(defaultRTV[i], D3D12_DESCRIPTOR_HEAP_TYPE_RTV); - } - - const int w = windowSize.width() * windowDpr; - const int h = windowSize.height() * windowDpr; - HRESULT hr = swapChain->ResizeBuffers(swapChainBufferCount, w, h, RT_COLOR_FORMAT, - waitableSwapChainMaxLatency ? DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT : 0); - if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) { - deviceManager()->deviceLossDetected(); - return; - } else if (FAILED(hr)) { - qWarning("Failed to resize buffers: %s", qPrintable(comErrorMessage(hr))); - return; - } - - setupDefaultRenderTargets(); -} - -void QSGD3D12EnginePrivate::deviceLost() -{ - qWarning("D3D device lost, will attempt to reinitialize"); - - // Release all resources. This is important because otherwise reinitialization may fail. - releaseResources(); - - // Now in uninitialized state (but 'window' is still valid). Will recreate - // all the resources on the next beginFrame(). -} - -QSGD3D12CPUWaitableFence *QSGD3D12EnginePrivate::createCPUWaitableFence() const -{ - QSGD3D12CPUWaitableFence *f = new QSGD3D12CPUWaitableFence; - HRESULT hr = device->CreateFence(f->value, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&f->fence)); - if (FAILED(hr)) { - qWarning("Failed to create fence: %s", qPrintable(comErrorMessage(hr))); - return f; - } - f->event = CreateEvent(nullptr, FALSE, FALSE, nullptr); - return f; -} - -void QSGD3D12EnginePrivate::waitForGPU(QSGD3D12CPUWaitableFence *f) const -{ - const UINT64 newValue = f->value.fetchAndAddAcquire(1) + 1; - commandQueue->Signal(f->fence.Get(), newValue); - if (f->fence->GetCompletedValue() < newValue) { - HRESULT hr = f->fence->SetEventOnCompletion(newValue, f->event); - if (FAILED(hr)) { - qWarning("SetEventOnCompletion failed: %s", qPrintable(comErrorMessage(hr))); - return; - } - WaitForSingleObject(f->event, INFINITE); - } -} - -void QSGD3D12EnginePrivate::transitionResource(ID3D12Resource *resource, ID3D12GraphicsCommandList *commandList, - D3D12_RESOURCE_STATES before, D3D12_RESOURCE_STATES after) const -{ - D3D12_RESOURCE_BARRIER barrier; - barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; - barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; - barrier.Transition.pResource = resource; - barrier.Transition.StateBefore = before; - barrier.Transition.StateAfter = after; - barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; - - commandList->ResourceBarrier(1, &barrier); -} - -void QSGD3D12EnginePrivate::resolveMultisampledTarget(ID3D12Resource *msaa, - ID3D12Resource *resolve, - D3D12_RESOURCE_STATES resolveUsage, - ID3D12GraphicsCommandList *commandList) const -{ - D3D12_RESOURCE_BARRIER barriers[2]; - for (int i = 0; i < _countof(barriers); ++i) { - barriers[i].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; - barriers[i].Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; - barriers[i].Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; - } - - barriers[0].Transition.pResource = msaa; - barriers[0].Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET; - barriers[0].Transition.StateAfter = D3D12_RESOURCE_STATE_RESOLVE_SOURCE; - barriers[1].Transition.pResource = resolve; - barriers[1].Transition.StateBefore = resolveUsage; - barriers[1].Transition.StateAfter = D3D12_RESOURCE_STATE_RESOLVE_DEST; - commandList->ResourceBarrier(2, barriers); - - commandList->ResolveSubresource(resolve, 0, msaa, 0, RT_COLOR_FORMAT); - - barriers[0].Transition.pResource = msaa; - barriers[0].Transition.StateBefore = D3D12_RESOURCE_STATE_RESOLVE_SOURCE; - barriers[0].Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET; - barriers[1].Transition.pResource = resolve; - barriers[1].Transition.StateBefore = D3D12_RESOURCE_STATE_RESOLVE_DEST; - barriers[1].Transition.StateAfter = resolveUsage; - commandList->ResourceBarrier(2, barriers); -} - -void QSGD3D12EnginePrivate::uavBarrier(ID3D12Resource *resource, ID3D12GraphicsCommandList *commandList) const -{ - D3D12_RESOURCE_BARRIER barrier = {}; - barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV; - barrier.UAV.pResource = resource; - - commandList->ResourceBarrier(1, &barrier); -} - -ID3D12Resource *QSGD3D12EnginePrivate::createBuffer(int size) -{ - ID3D12Resource *buf; - - D3D12_HEAP_PROPERTIES uploadHeapProp = {}; - uploadHeapProp.Type = D3D12_HEAP_TYPE_UPLOAD; - - D3D12_RESOURCE_DESC bufDesc = {}; - bufDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; - bufDesc.Width = size; - bufDesc.Height = 1; - bufDesc.DepthOrArraySize = 1; - bufDesc.MipLevels = 1; - bufDesc.Format = DXGI_FORMAT_UNKNOWN; - bufDesc.SampleDesc.Count = 1; - bufDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; - - HRESULT hr = device->CreateCommittedResource(&uploadHeapProp, D3D12_HEAP_FLAG_NONE, &bufDesc, - D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&buf)); - if (FAILED(hr)) - qWarning("Failed to create buffer resource: %s", qPrintable(comErrorMessage(hr))); - - return buf; -} - -void QSGD3D12EnginePrivate::ensureBuffer(Buffer *buf) -{ - Buffer::InFlightData &bfd(buf->d[currentPFrameIndex]); - // Only enlarge, never shrink - const bool newBufferNeeded = bfd.buffer ? (buf->cpuDataRef.size > bfd.resourceSize) : true; - if (newBufferNeeded) { - // Round it up and overallocate a little bit so that a subsequent - // buffer contents rebuild with a slightly larger total size does - // not lead to creating a new buffer. - const quint32 sz = alignedSize(buf->cpuDataRef.size, 4096); - if (Q_UNLIKELY(debug_buffer())) - qDebug("new buffer[pf=%d] of size %d (actual data size %d)", currentPFrameIndex, sz, buf->cpuDataRef.size); - bfd.buffer.Attach(createBuffer(sz)); - bfd.resourceSize = sz; - } - // Cache the actual data size in the per-in-flight-frame data as well. - bfd.dataSize = buf->cpuDataRef.size; -} - -void QSGD3D12EnginePrivate::updateBuffer(Buffer *buf) -{ - if (buf->cpuDataRef.dirty.isEmpty()) - return; - - Buffer::InFlightData &bfd(buf->d[currentPFrameIndex]); - quint8 *p = nullptr; - const D3D12_RANGE readRange = { 0, 0 }; - if (FAILED(bfd.buffer->Map(0, &readRange, reinterpret_cast(&p)))) { - qWarning("Map failed for buffer of size %d", buf->cpuDataRef.size); - return; - } - for (const auto &r : qAsConst(buf->cpuDataRef.dirty)) { - if (Q_UNLIKELY(debug_buffer())) - qDebug("%p o %d s %d", buf, r.first, r.second); - memcpy(p + r.first, buf->cpuDataRef.p + r.first, r.second); - } - bfd.buffer->Unmap(0, nullptr); - buf->cpuDataRef.dirty.clear(); -} - -void QSGD3D12EnginePrivate::ensureDevice() -{ - if (!initialized && window) - initialize(window, windowSize, windowDpr, windowSamples, windowAlpha); -} - -void QSGD3D12EnginePrivate::beginFrame() -{ - if (inFrame && !activeLayers) - qFatal("beginFrame called again without an endFrame, frame index was %d", frameIndex); - - if (Q_UNLIKELY(debug_render())) - qDebug() << "***** begin frame, logical" << frameIndex << "present" << presentFrameIndex << "layer" << activeLayers; - - if (inFrame && activeLayers) { - if (Q_UNLIKELY(debug_render())) - qDebug("frame %d already in progress", frameIndex); - if (!currentLayerDepth) { - // There are layers and the real frame preparation starts now. Prepare for present. - beginFrameDraw(); - } - return; - } - - inFrame = true; - - // The device may have been lost. This is the point to attempt to start - // again from scratch. Except when it is not. Operations that can happen - // out of frame (e.g. textures, render targets) may trigger reinit earlier - // than beginFrame. - ensureDevice(); - - // Wait for a buffer to be available for Present, if the waitable event is in use. - if (waitableSwapChainMaxLatency) - WaitForSingleObject(swapEvent, INFINITE); - - // Block if needed. With 2 frames in flight frame N waits for frame N - 2, but not N - 1, to finish. - currentPFrameIndex = frameIndex % frameInFlightCount; - if (frameIndex >= frameInFlightCount) { - ID3D12Fence *fence = frameFence[currentPFrameIndex]->fence.Get(); - HANDLE event = frameFence[currentPFrameIndex]->event; - // Frame fence values start from 1, hence the +1. - const quint64 inFlightFenceValue = frameIndex - frameInFlightCount + 1; - if (fence->GetCompletedValue() < inFlightFenceValue) { - fence->SetEventOnCompletion(inFlightFenceValue, event); - WaitForSingleObject(event, INFINITE); - } - frameCommandAllocator[currentPFrameIndex]->Reset(); - } - - PersistentFrameData &pfd(pframeData[currentPFrameIndex]); - pfd.cbvSrvUavNextFreeDescriptorIndex = 0; - - for (Buffer &b : buffers) { - if (b.entryInUse()) - b.d[currentPFrameIndex].dirty.clear(); - } - - if (frameIndex >= frameInFlightCount - 1) { - // Now sync the buffer changes from the previous, potentially still in - // flight, frames. This is done by taking the ranges dirtied in those - // frames and adding them to the global CPU-side buffer's dirty list, - // as if this frame changed those ranges. (however, dirty ranges - // inherited this way are not added to this frame's persistent - // per-frame dirty list because the next frame after this one should - // inherit this frame's genuine changes only, the rest will come from - // the earlier ones) - for (int delta = frameInFlightCount - 1; delta >= 1; --delta) { - const int prevPFrameIndex = (frameIndex - delta) % frameInFlightCount; - PersistentFrameData &prevFrameData(pframeData[prevPFrameIndex]); - for (uint id : qAsConst(prevFrameData.buffersUsedInFrame)) { - Buffer &b(buffers[id - 1]); - if (b.d[currentPFrameIndex].buffer && b.d[currentPFrameIndex].dataSize == b.cpuDataRef.size) { - if (Q_UNLIKELY(debug_buffer())) - qDebug() << "frame" << frameIndex << "takes dirty" << b.d[prevPFrameIndex].dirty - << "from frame" << frameIndex - delta << "for buffer" << id; - for (const auto &range : qAsConst(b.d[prevPFrameIndex].dirty)) - addDirtyRange(&b.cpuDataRef.dirty, range.first, range.second, b.cpuDataRef.size); - } else { - if (Q_UNLIKELY(debug_buffer())) - qDebug() << "frame" << frameIndex << "makes all dirty from frame" << frameIndex - delta - << "for buffer" << id; - addDirtyRange(&b.cpuDataRef.dirty, 0, b.cpuDataRef.size, b.cpuDataRef.size); - } - } - } - } - - if (frameIndex >= frameInFlightCount) { - // Do some texture upload bookkeeping. - const quint64 finishedFrameIndex = frameIndex - frameInFlightCount; // we know since we just blocked for this - // pfd conveniently refers to the same slot that was used by that frame - if (!pfd.pendingTextureUploads.isEmpty()) { - if (Q_UNLIKELY(debug_texture())) - qDebug("Removing texture upload data for frame %d", finishedFrameIndex); - for (uint id : qAsConst(pfd.pendingTextureUploads)) { - const int idx = id - 1; - Texture &t(textures[idx]); - // fenceValue is 0 when the previous frame cleared it, skip in - // this case. Skip also when fenceValue > the value it was when - // adding the last GPU wait - this is the case when more - // uploads were queued for the same texture in the meantime. - if (t.fenceValue && t.fenceValue == t.lastWaitFenceValue) { - t.fenceValue = 0; - t.lastWaitFenceValue = 0; - t.stagingBuffers.clear(); - t.stagingHeaps.clear(); - if (Q_UNLIKELY(debug_texture())) - qDebug("Cleaned staging data for texture %u", id); - } - } - pfd.pendingTextureUploads.clear(); - if (!pfd.pendingTextureMipMap.isEmpty()) { - if (Q_UNLIKELY(debug_texture())) - qDebug() << "cleaning mipmap generation data for " << pfd.pendingTextureMipMap; - // no special cleanup is needed as mipmap generation uses the frame's resources - pfd.pendingTextureMipMap.clear(); - } - bool hasPending = false; - for (int delta = 1; delta < frameInFlightCount; ++delta) { - const PersistentFrameData &prevFrameData(pframeData[(frameIndex - delta) % frameInFlightCount]); - if (!prevFrameData.pendingTextureUploads.isEmpty()) { - hasPending = true; - break; - } - } - if (!hasPending) { - if (Q_UNLIKELY(debug_texture())) - qDebug("no more pending textures"); - copyCommandAllocator->Reset(); - } - } - - // Do the deferred deletes. - if (!pfd.deleteQueue.isEmpty()) { - for (PersistentFrameData::DeleteQueueEntry &e : pfd.deleteQueue) { - e.res = nullptr; - e.descHeap = nullptr; - if (e.cpuDescriptorPtr) { - D3D12_CPU_DESCRIPTOR_HANDLE h = { e.cpuDescriptorPtr }; - cpuDescHeapManager.release(h, e.descHeapType); - } - } - pfd.deleteQueue.clear(); - } - // Deferred deletes issued outside a begin-endFrame go to the next - // frame's out-of-frame delete queue as these cannot be executed in the - // next beginFrame, only in next + frameInFlightCount. Move to the - // normal queue if this is the next beginFrame. - if (!pfd.outOfFrameDeleteQueue.isEmpty()) { - pfd.deleteQueue = pfd.outOfFrameDeleteQueue; - pfd.outOfFrameDeleteQueue.clear(); - } - - // Mark released texture, buffer, etc. slots free. - if (!pfd.pendingReleases.isEmpty()) { - for (const auto &pr : qAsConst(pfd.pendingReleases)) { - Q_ASSERT(pr.id); - if (pr.type == PersistentFrameData::PendingRelease::TypeTexture) { - Texture &t(textures[pr.id - 1]); - Q_ASSERT(t.entryInUse()); - t.flags &= ~RenderTarget::EntryInUse; // createTexture() can now reuse this entry - t.texture = nullptr; - } else if (pr.type == PersistentFrameData::PendingRelease::TypeBuffer) { - Buffer &b(buffers[pr.id - 1]); - Q_ASSERT(b.entryInUse()); - b.flags &= ~Buffer::EntryInUse; - for (int i = 0; i < frameInFlightCount; ++i) - b.d[i].buffer = nullptr; - } else { - qFatal("Corrupt pending release list, type %d", pr.type); - } - } - pfd.pendingReleases.clear(); - } - if (!pfd.outOfFramePendingReleases.isEmpty()) { - pfd.pendingReleases = pfd.outOfFramePendingReleases; - pfd.outOfFramePendingReleases.clear(); - } - } - - pfd.buffersUsedInFrame.clear(); - - beginDrawCalls(); - - // Prepare for present if this is a frame without layers. - if (!activeLayers) - beginFrameDraw(); -} - -void QSGD3D12EnginePrivate::beginDrawCalls() -{ - frameCommandList->Reset(frameCommandAllocator[frameIndex % frameInFlightCount].Get(), nullptr); - commandList = frameCommandList.Get(); - invalidateCachedFrameState(); -} - -void QSGD3D12EnginePrivate::invalidateCachedFrameState() -{ - tframeData.drawingMode = QSGGeometry::DrawingMode(-1); - tframeData.currentIndexBuffer = 0; - tframeData.activeTextureCount = 0; - tframeData.drawCount = 0; - tframeData.lastPso = nullptr; - tframeData.lastRootSig = nullptr; - tframeData.descHeapSet = false; -} - -void QSGD3D12EnginePrivate::restoreFrameState(bool minimal) -{ - queueSetRenderTarget(currentRenderTarget); - if (!minimal) { - queueViewport(tframeData.viewport); - queueScissor(tframeData.scissor); - queueSetBlendFactor(tframeData.blendFactor); - queueSetStencilRef(tframeData.stencilRef); - } - finalizePipeline(tframeData.pipelineState); -} - -void QSGD3D12EnginePrivate::beginFrameDraw() -{ - if (windowSamples == 1) - transitionResource(defaultRT[presentFrameIndex % swapChainBufferCount].Get(), commandList, - D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET); -} - -void QSGD3D12EnginePrivate::endFrame() -{ - if (!inFrame) - qFatal("endFrame called without beginFrame, frame index %d", frameIndex); - - if (Q_UNLIKELY(debug_render())) - qDebug("***** end frame"); - - endDrawCalls(true); - - commandQueue->Signal(frameFence[frameIndex % frameInFlightCount]->fence.Get(), frameIndex + 1); - ++frameIndex; - - inFrame = false; -} - -void QSGD3D12EnginePrivate::endDrawCalls(bool lastInFrame) -{ - PersistentFrameData &pfd(pframeData[currentPFrameIndex]); - - // Now is the time to sync all the changed areas in the buffers. - if (Q_UNLIKELY(debug_buffer())) - qDebug() << "buffers used in drawcall set" << pfd.buffersUsedInDrawCallSet; - for (uint id : qAsConst(pfd.buffersUsedInDrawCallSet)) - updateBuffer(&buffers[id - 1]); - - pfd.buffersUsedInFrame += pfd.buffersUsedInDrawCallSet; - pfd.buffersUsedInDrawCallSet.clear(); - - // Add a wait on the 3D queue for the relevant texture uploads on the copy queue. - if (!pfd.pendingTextureUploads.isEmpty()) { - quint64 topFenceValue = 0; - for (uint id : qAsConst(pfd.pendingTextureUploads)) { - const int idx = id - 1; - Texture &t(textures[idx]); - Q_ASSERT(t.fenceValue); - // skip if already added a Wait in the previous frame - if (t.lastWaitFenceValue == t.fenceValue) - continue; - t.lastWaitFenceValue = t.fenceValue; - if (t.fenceValue > topFenceValue) - topFenceValue = t.fenceValue; - if (t.mipmap()) - pfd.pendingTextureMipMap.insert(id); - } - if (topFenceValue) { - if (Q_UNLIKELY(debug_texture())) - qDebug("added wait for texture fence %llu", topFenceValue); - commandQueue->Wait(textureUploadFence.Get(), topFenceValue); - // Generate mipmaps after the wait, when necessary. - if (!pfd.pendingTextureMipMap.isEmpty()) { - if (Q_UNLIKELY(debug_texture())) - qDebug() << "starting mipmap generation for" << pfd.pendingTextureMipMap; - for (uint id : qAsConst(pfd.pendingTextureMipMap)) - mipmapper.queueGenerate(textures[id - 1]); - } - } - } - - if (lastInFrame) { - // Resolve and transition the backbuffer for present, if needed. - const int idx = presentFrameIndex % swapChainBufferCount; - if (windowSamples == 1) { - transitionResource(defaultRT[idx].Get(), commandList, - D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT); - } else { - if (Q_UNLIKELY(debug_render())) { - const D3D12_RESOURCE_DESC desc = defaultRT[idx]->GetDesc(); - qDebug("added resolve for multisampled render target (count %d, quality %d)", - desc.SampleDesc.Count, desc.SampleDesc.Quality); - } - resolveMultisampledTarget(defaultRT[idx].Get(), backBufferRT[idx].Get(), - D3D12_RESOURCE_STATE_PRESENT, commandList); - } - - if (activeLayers) { - if (Q_UNLIKELY(debug_render())) - qDebug("this frame had %d layers", activeLayers); - activeLayers = 0; - } - } - - // Go! - HRESULT hr = frameCommandList->Close(); - if (FAILED(hr)) { - qWarning("Failed to close command list: %s", qPrintable(comErrorMessage(hr))); - if (hr == E_INVALIDARG) - qWarning("Invalid arguments. Some of the commands in the list is invalid in some way."); - } - - ID3D12CommandList *commandLists[] = { frameCommandList.Get() }; - commandQueue->ExecuteCommandLists(_countof(commandLists), commandLists); - - commandList = nullptr; -} - -void QSGD3D12EnginePrivate::beginLayer() -{ - if (inFrame && !activeLayers) - qFatal("Layer rendering cannot be started while a frame is active"); - - if (Q_UNLIKELY(debug_render())) - qDebug("===== beginLayer active %d depth %d (inFrame=%d)", activeLayers, currentLayerDepth, inFrame); - - ++activeLayers; - ++currentLayerDepth; - - // Do an early beginFrame. With multiple layers this results in - // beginLayer - beginFrame - endLayer - beginLayer - beginFrame - endLayer - ... - (*) beginFrame - endFrame - // where (*) denotes the start of the preparation of the actual, non-layer frame. - - if (activeLayers == 1) - beginFrame(); -} - -void QSGD3D12EnginePrivate::endLayer() -{ - if (!inFrame || !activeLayers || !currentLayerDepth) - qFatal("Mismatched endLayer"); - - if (Q_UNLIKELY(debug_render())) - qDebug("===== endLayer active %d depth %d", activeLayers, currentLayerDepth); - - --currentLayerDepth; - - // Do not touch activeLayers. It remains valid until endFrame. -} - -// Root signature: -// [0] CBV - always present -// [1] table with one SRV per texture (must be a table since root descriptor SRVs cannot be textures) - optional -// one static sampler per texture - optional -// -// SRVs can be created freely via QSGD3D12CPUDescriptorHeapManager and stored -// in QSGD3D12TextureView. The engine will copy them onto a dedicated, -// shader-visible CBV-SRV-UAV heap in the correct order. - -void QSGD3D12EnginePrivate::finalizePipeline(const QSGD3D12PipelineState &pipelineState) -{ - if (!inFrame) { - qWarning("%s: Cannot be called outside begin/endFrame", __FUNCTION__); - return; - } - - tframeData.pipelineState = pipelineState; - - RootSigCacheEntry *cachedRootSig = rootSigCache[pipelineState.shaders.rootSig]; - if (!cachedRootSig) { - if (Q_UNLIKELY(debug_render())) - qDebug("NEW ROOTSIG"); - - cachedRootSig = new RootSigCacheEntry; - - D3D12_ROOT_PARAMETER rootParams[4]; - int rootParamCount = 0; - - rootParams[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV; - rootParams[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; - rootParams[0].Descriptor.ShaderRegister = 0; // b0 - rootParams[0].Descriptor.RegisterSpace = 0; - ++rootParamCount; - - D3D12_DESCRIPTOR_RANGE tvDescRange; - if (pipelineState.shaders.rootSig.textureViewCount > 0) { - rootParams[rootParamCount].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; - rootParams[rootParamCount].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; - rootParams[rootParamCount].DescriptorTable.NumDescriptorRanges = 1; - tvDescRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; - tvDescRange.NumDescriptors = pipelineState.shaders.rootSig.textureViewCount; - tvDescRange.BaseShaderRegister = 0; // t0, t1, ... - tvDescRange.RegisterSpace = 0; - tvDescRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; - rootParams[rootParamCount].DescriptorTable.pDescriptorRanges = &tvDescRange; - ++rootParamCount; - } - - Q_ASSERT(rootParamCount <= _countof(rootParams)); - D3D12_ROOT_SIGNATURE_DESC desc; - desc.NumParameters = rootParamCount; - desc.pParameters = rootParams; - // Mixing up samplers and resource views in QSGD3D12TextureView means - // that the number of static samplers has to match the number of - // textures. This is not really ideal in general but works for Quick's use cases. - // The shaders can still choose to declare and use fewer samplers, if they want to. - desc.NumStaticSamplers = pipelineState.shaders.rootSig.textureViewCount; - D3D12_STATIC_SAMPLER_DESC staticSamplers[8]; - int sdIdx = 0; - Q_ASSERT(pipelineState.shaders.rootSig.textureViewCount <= _countof(staticSamplers)); - for (int i = 0; i < pipelineState.shaders.rootSig.textureViewCount; ++i) { - const QSGD3D12TextureView &tv(pipelineState.shaders.rootSig.textureViews[i]); - D3D12_STATIC_SAMPLER_DESC sd = {}; - sd.Filter = D3D12_FILTER(tv.filter); - sd.AddressU = D3D12_TEXTURE_ADDRESS_MODE(tv.addressModeHoriz); - sd.AddressV = D3D12_TEXTURE_ADDRESS_MODE(tv.addressModeVert); - sd.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; - sd.MinLOD = 0.0f; - sd.MaxLOD = D3D12_FLOAT32_MAX; - sd.ShaderRegister = sdIdx; // t0, t1, ... - sd.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; - staticSamplers[sdIdx++] = sd; - } - desc.pStaticSamplers = staticSamplers; - desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT; - - ComPtr signature; - ComPtr error; - if (FAILED(D3D12SerializeRootSignature(&desc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error))) { - QByteArray msg(static_cast(error->GetBufferPointer()), error->GetBufferSize()); - qWarning("Failed to serialize root signature: %s", qPrintable(msg)); - return; - } - if (FAILED(device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), - IID_PPV_ARGS(&cachedRootSig->rootSig)))) { - qWarning("Failed to create root signature"); - return; - } - - rootSigCache.insert(pipelineState.shaders.rootSig, cachedRootSig); - } - - PSOCacheEntry *cachedPso = psoCache[pipelineState]; - if (!cachedPso) { - if (Q_UNLIKELY(debug_render())) - qDebug("NEW PSO"); - - cachedPso = new PSOCacheEntry; - - D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; - - D3D12_INPUT_ELEMENT_DESC inputElements[QSGD3D12_MAX_INPUT_ELEMENTS]; - int ieIdx = 0; - for (int i = 0; i < pipelineState.inputElementCount; ++i) { - const QSGD3D12InputElement &ie(pipelineState.inputElements[i]); - D3D12_INPUT_ELEMENT_DESC ieDesc = {}; - ieDesc.SemanticName = ie.semanticName; - ieDesc.SemanticIndex = ie.semanticIndex; - ieDesc.Format = DXGI_FORMAT(ie.format); - ieDesc.InputSlot = ie.slot; - ieDesc.AlignedByteOffset = ie.offset; - ieDesc.InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA; - if (Q_UNLIKELY(debug_render())) - qDebug("input [%d]: %s %d 0x%x %d", ieIdx, ie.semanticName, ie.offset, ie.format, ie.slot); - inputElements[ieIdx++] = ieDesc; - } - - psoDesc.InputLayout = { inputElements, UINT(ieIdx) }; - - psoDesc.pRootSignature = cachedRootSig->rootSig.Get(); - - D3D12_SHADER_BYTECODE vshader; - vshader.pShaderBytecode = pipelineState.shaders.vs; - vshader.BytecodeLength = pipelineState.shaders.vsSize; - D3D12_SHADER_BYTECODE pshader; - pshader.pShaderBytecode = pipelineState.shaders.ps; - pshader.BytecodeLength = pipelineState.shaders.psSize; - - psoDesc.VS = vshader; - psoDesc.PS = pshader; - - D3D12_RASTERIZER_DESC rastDesc = {}; - rastDesc.FillMode = D3D12_FILL_MODE_SOLID; - rastDesc.CullMode = D3D12_CULL_MODE(pipelineState.cullMode); - rastDesc.FrontCounterClockwise = pipelineState.frontCCW; - rastDesc.DepthBias = D3D12_DEFAULT_DEPTH_BIAS; - rastDesc.DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP; - rastDesc.SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS; - rastDesc.DepthClipEnable = TRUE; - - psoDesc.RasterizerState = rastDesc; - - D3D12_BLEND_DESC blendDesc = {}; - if (pipelineState.blend == QSGD3D12PipelineState::BlendNone) { - D3D12_RENDER_TARGET_BLEND_DESC noBlendDesc = {}; - noBlendDesc.RenderTargetWriteMask = pipelineState.colorWrite ? D3D12_COLOR_WRITE_ENABLE_ALL : 0; - blendDesc.RenderTarget[0] = noBlendDesc; - } else if (pipelineState.blend == QSGD3D12PipelineState::BlendPremul) { - const D3D12_RENDER_TARGET_BLEND_DESC premulBlendDesc = { - TRUE, FALSE, - D3D12_BLEND_ONE, D3D12_BLEND_INV_SRC_ALPHA, D3D12_BLEND_OP_ADD, - D3D12_BLEND_ONE, D3D12_BLEND_INV_SRC_ALPHA, D3D12_BLEND_OP_ADD, - D3D12_LOGIC_OP_NOOP, - UINT8(pipelineState.colorWrite ? D3D12_COLOR_WRITE_ENABLE_ALL : 0) - }; - blendDesc.RenderTarget[0] = premulBlendDesc; - } else if (pipelineState.blend == QSGD3D12PipelineState::BlendColor) { - const D3D12_RENDER_TARGET_BLEND_DESC colorBlendDesc = { - TRUE, FALSE, - D3D12_BLEND_BLEND_FACTOR, D3D12_BLEND_INV_SRC_COLOR, D3D12_BLEND_OP_ADD, - D3D12_BLEND_BLEND_FACTOR, D3D12_BLEND_INV_SRC_ALPHA, D3D12_BLEND_OP_ADD, - D3D12_LOGIC_OP_NOOP, - UINT8(pipelineState.colorWrite ? D3D12_COLOR_WRITE_ENABLE_ALL : 0) - }; - blendDesc.RenderTarget[0] = colorBlendDesc; - } - psoDesc.BlendState = blendDesc; - - psoDesc.DepthStencilState.DepthEnable = pipelineState.depthEnable; - psoDesc.DepthStencilState.DepthWriteMask = pipelineState.depthWrite ? D3D12_DEPTH_WRITE_MASK_ALL : D3D12_DEPTH_WRITE_MASK_ZERO; - psoDesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC(pipelineState.depthFunc); - - psoDesc.DepthStencilState.StencilEnable = pipelineState.stencilEnable; - psoDesc.DepthStencilState.StencilReadMask = psoDesc.DepthStencilState.StencilWriteMask = 0xFF; - D3D12_DEPTH_STENCILOP_DESC stencilOpDesc = { - D3D12_STENCIL_OP(pipelineState.stencilFailOp), - D3D12_STENCIL_OP(pipelineState.stencilDepthFailOp), - D3D12_STENCIL_OP(pipelineState.stencilPassOp), - D3D12_COMPARISON_FUNC(pipelineState.stencilFunc) - }; - psoDesc.DepthStencilState.FrontFace = psoDesc.DepthStencilState.BackFace = stencilOpDesc; - - psoDesc.SampleMask = UINT_MAX; - psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE(pipelineState.topologyType); - psoDesc.NumRenderTargets = 1; - psoDesc.RTVFormats[0] = RT_COLOR_FORMAT; - psoDesc.DSVFormat = DXGI_FORMAT_D24_UNORM_S8_UINT; - psoDesc.SampleDesc = defaultRT[0]->GetDesc().SampleDesc; - - HRESULT hr = device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&cachedPso->pso)); - if (FAILED(hr)) { - qWarning("Failed to create graphics pipeline state: %s", - qPrintable(comErrorMessage(hr))); - return; - } - - psoCache.insert(pipelineState, cachedPso); - } - - if (cachedPso->pso.Get() != tframeData.lastPso) { - tframeData.lastPso = cachedPso->pso.Get(); - commandList->SetPipelineState(tframeData.lastPso); - } - - if (cachedRootSig->rootSig.Get() != tframeData.lastRootSig) { - tframeData.lastRootSig = cachedRootSig->rootSig.Get(); - commandList->SetGraphicsRootSignature(tframeData.lastRootSig); - } - - if (pipelineState.shaders.rootSig.textureViewCount > 0) - setDescriptorHeaps(); -} - -void QSGD3D12EnginePrivate::setDescriptorHeaps(bool force) -{ - if (force || !tframeData.descHeapSet) { - tframeData.descHeapSet = true; - ID3D12DescriptorHeap *heaps[] = { pframeData[currentPFrameIndex].gpuCbvSrvUavHeap.Get() }; - commandList->SetDescriptorHeaps(_countof(heaps), heaps); - } -} - -void QSGD3D12EnginePrivate::queueViewport(const QRect &rect) -{ - if (!inFrame) { - qWarning("%s: Cannot be called outside begin/endFrame", __FUNCTION__); - return; - } - - tframeData.viewport = rect; - const D3D12_VIEWPORT viewport = { float(rect.x()), float(rect.y()), float(rect.width()), float(rect.height()), 0, 1 }; - commandList->RSSetViewports(1, &viewport); -} - -void QSGD3D12EnginePrivate::queueScissor(const QRect &rect) -{ - if (!inFrame) { - qWarning("%s: Cannot be called outside begin/endFrame", __FUNCTION__); - return; - } - - tframeData.scissor = rect; - const D3D12_RECT scissorRect = { rect.x(), rect.y(), rect.x() + rect.width(), rect.y() + rect.height() }; - commandList->RSSetScissorRects(1, &scissorRect); -} - -void QSGD3D12EnginePrivate::queueSetRenderTarget(uint id) -{ - if (!inFrame) { - qWarning("%s: Cannot be called outside begin/endFrame", __FUNCTION__); - return; - } - - D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle; - D3D12_CPU_DESCRIPTOR_HANDLE dsvHandle; - - if (!id) { - rtvHandle = defaultRTV[presentFrameIndex % swapChainBufferCount]; - dsvHandle = defaultDSV; - } else { - const int idx = id - 1; - Q_ASSERT(idx < renderTargets.count() && renderTargets[idx].entryInUse()); - RenderTarget &rt(renderTargets[idx]); - rtvHandle = rt.rtv; - dsvHandle = rt.dsv; - if (!(rt.flags & RenderTarget::NeedsReadBarrier)) { - rt.flags |= RenderTarget::NeedsReadBarrier; - if (!(rt.flags & RenderTarget::Multisample)) - transitionResource(rt.color.Get(), commandList, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, - D3D12_RESOURCE_STATE_RENDER_TARGET); - } - } - - commandList->OMSetRenderTargets(1, &rtvHandle, FALSE, &dsvHandle); - - currentRenderTarget = id; -} - -void QSGD3D12EnginePrivate::queueClearRenderTarget(const QColor &color) -{ - if (!inFrame) { - qWarning("%s: Cannot be called outside begin/endFrame", __FUNCTION__); - return; - } - - const float clearColor[] = { float(color.redF()), float(color.blueF()), float(color.greenF()), float(color.alphaF()) }; - D3D12_CPU_DESCRIPTOR_HANDLE rtv = !currentRenderTarget - ? defaultRTV[presentFrameIndex % swapChainBufferCount] - : renderTargets[currentRenderTarget - 1].rtv; - commandList->ClearRenderTargetView(rtv, clearColor, 0, nullptr); -} - -void QSGD3D12EnginePrivate::queueClearDepthStencil(float depthValue, quint8 stencilValue, QSGD3D12Engine::ClearFlags which) -{ - if (!inFrame) { - qWarning("%s: Cannot be called outside begin/endFrame", __FUNCTION__); - return; - } - - D3D12_CPU_DESCRIPTOR_HANDLE dsv = !currentRenderTarget - ? defaultDSV - : renderTargets[currentRenderTarget - 1].dsv; - commandList->ClearDepthStencilView(dsv, D3D12_CLEAR_FLAGS(int(which)), depthValue, stencilValue, 0, nullptr); -} - -void QSGD3D12EnginePrivate::queueSetBlendFactor(const QVector4D &factor) -{ - if (!inFrame) { - qWarning("%s: Cannot be called outside begin/endFrame", __FUNCTION__); - return; - } - - tframeData.blendFactor = factor; - const float f[4] = { factor.x(), factor.y(), factor.z(), factor.w() }; - commandList->OMSetBlendFactor(f); -} - -void QSGD3D12EnginePrivate::queueSetStencilRef(quint32 ref) -{ - if (!inFrame) { - qWarning("%s: Cannot be called outside begin/endFrame", __FUNCTION__); - return; - } - - tframeData.stencilRef = ref; - commandList->OMSetStencilRef(ref); -} - -void QSGD3D12EnginePrivate::queueDraw(const QSGD3D12Engine::DrawParams ¶ms) -{ - if (!inFrame) { - qWarning("%s: Cannot be called outside begin/endFrame", __FUNCTION__); - return; - } - - const bool skip = tframeData.scissor.isEmpty(); - - PersistentFrameData &pfd(pframeData[currentPFrameIndex]); - - pfd.buffersUsedInDrawCallSet.insert(params.vertexBuf); - const int vertexBufIdx = params.vertexBuf - 1; - Q_ASSERT(params.vertexBuf && vertexBufIdx < buffers.count() && buffers[vertexBufIdx].entryInUse()); - pfd.buffersUsedInDrawCallSet.insert(params.constantBuf); - const int constantBufIdx = params.constantBuf - 1; - Q_ASSERT(params.constantBuf && constantBufIdx < buffers.count() && buffers[constantBufIdx].entryInUse()); - int indexBufIdx = -1; - if (params.indexBuf) { - pfd.buffersUsedInDrawCallSet.insert(params.indexBuf); - indexBufIdx = params.indexBuf - 1; - Q_ASSERT(indexBufIdx < buffers.count() && buffers[indexBufIdx].entryInUse()); - } - - // Ensure buffers are created but do not copy the data here, leave that to endDrawCalls(). - ensureBuffer(&buffers[vertexBufIdx]); - ensureBuffer(&buffers[constantBufIdx]); - if (indexBufIdx >= 0) - ensureBuffer(&buffers[indexBufIdx]); - - // Set the CBV. - if (!skip && params.cboOffset >= 0) { - ID3D12Resource *cbuf = buffers[constantBufIdx].d[currentPFrameIndex].buffer.Get(); - if (cbuf) - commandList->SetGraphicsRootConstantBufferView(0, cbuf->GetGPUVirtualAddress() + params.cboOffset); - } - - // Set up vertex and index buffers. - ID3D12Resource *vbuf = buffers[vertexBufIdx].d[currentPFrameIndex].buffer.Get(); - ID3D12Resource *ibuf = indexBufIdx >= 0 && params.startIndexIndex >= 0 - ? buffers[indexBufIdx].d[currentPFrameIndex].buffer.Get() : nullptr; - - if (!skip && params.mode != tframeData.drawingMode) { - D3D_PRIMITIVE_TOPOLOGY topology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; - switch (params.mode) { - case QSGGeometry::DrawPoints: - topology = D3D_PRIMITIVE_TOPOLOGY_POINTLIST; - break; - case QSGGeometry::DrawLines: - topology = D3D_PRIMITIVE_TOPOLOGY_LINELIST; - break; - case QSGGeometry::DrawLineStrip: - topology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; - break; - case QSGGeometry::DrawTriangles: - topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; - break; - case QSGGeometry::DrawTriangleStrip: - topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; - break; - default: - qFatal("Unsupported drawing mode 0x%x", params.mode); - break; - } - commandList->IASetPrimitiveTopology(topology); - tframeData.drawingMode = params.mode; - } - - if (!skip) { - D3D12_VERTEX_BUFFER_VIEW vbv; - vbv.BufferLocation = vbuf->GetGPUVirtualAddress() + params.vboOffset; - vbv.SizeInBytes = params.vboSize; - vbv.StrideInBytes = params.vboStride; - - // must be set after the topology - commandList->IASetVertexBuffers(0, 1, &vbv); - } - - if (!skip && params.startIndexIndex >= 0 && ibuf && tframeData.currentIndexBuffer != params.indexBuf) { - tframeData.currentIndexBuffer = params.indexBuf; - D3D12_INDEX_BUFFER_VIEW ibv; - ibv.BufferLocation = ibuf->GetGPUVirtualAddress(); - ibv.SizeInBytes = buffers[indexBufIdx].cpuDataRef.size; - ibv.Format = DXGI_FORMAT(params.indexFormat); - commandList->IASetIndexBuffer(&ibv); - } - - // Copy the SRVs to a drawcall-dedicated area of the shader-visible descriptor heap. - Q_ASSERT(tframeData.activeTextureCount == tframeData.pipelineState.shaders.rootSig.textureViewCount); - if (tframeData.activeTextureCount > 0) { - if (!skip) { - ensureGPUDescriptorHeap(tframeData.activeTextureCount); - const uint stride = cpuDescHeapManager.handleSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); - D3D12_CPU_DESCRIPTOR_HANDLE dst = pfd.gpuCbvSrvUavHeap->GetCPUDescriptorHandleForHeapStart(); - dst.ptr += pfd.cbvSrvUavNextFreeDescriptorIndex * stride; - for (int i = 0; i < tframeData.activeTextureCount; ++i) { - const TransientFrameData::ActiveTexture &t(tframeData.activeTextures[i]); - Q_ASSERT(t.id); - const int idx = t.id - 1; - const bool isTex = t.type == TransientFrameData::ActiveTexture::TypeTexture; - device->CopyDescriptorsSimple(1, dst, isTex ? textures[idx].srv : renderTargets[idx].srv, - D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); - dst.ptr += stride; - } - - D3D12_GPU_DESCRIPTOR_HANDLE gpuAddr = pfd.gpuCbvSrvUavHeap->GetGPUDescriptorHandleForHeapStart(); - gpuAddr.ptr += pfd.cbvSrvUavNextFreeDescriptorIndex * stride; - commandList->SetGraphicsRootDescriptorTable(1, gpuAddr); - - pfd.cbvSrvUavNextFreeDescriptorIndex += tframeData.activeTextureCount; - } - tframeData.activeTextureCount = 0; - } - - // Add the draw call. - if (!skip) { - ++tframeData.drawCount; - if (params.startIndexIndex >= 0) - commandList->DrawIndexedInstanced(params.count, 1, params.startIndexIndex, 0, 0); - else - commandList->DrawInstanced(params.count, 1, 0, 0); - } - - if (tframeData.drawCount == MAX_DRAW_CALLS_PER_LIST) { - if (Q_UNLIKELY(debug_render())) - qDebug("Limit of %d draw calls reached, executing command list", MAX_DRAW_CALLS_PER_LIST); - // submit the command list - endDrawCalls(); - // start a new one - beginDrawCalls(); - // prepare for the upcoming drawcalls - restoreFrameState(); - } -} - -void QSGD3D12EnginePrivate::ensureGPUDescriptorHeap(int cbvSrvUavDescriptorCount) -{ - PersistentFrameData &pfd(pframeData[currentPFrameIndex]); - int newSize = pfd.gpuCbvSrvUavHeapSize; - while (pfd.cbvSrvUavNextFreeDescriptorIndex + cbvSrvUavDescriptorCount > newSize) - newSize *= 2; - if (newSize != pfd.gpuCbvSrvUavHeapSize) { - if (Q_UNLIKELY(debug_descheap())) - qDebug("Out of space for SRVs, creating new CBV-SRV-UAV descriptor heap with descriptor count %d", newSize); - deferredDelete(pfd.gpuCbvSrvUavHeap); - createCbvSrvUavHeap(currentPFrameIndex, newSize); - setDescriptorHeaps(true); - pfd.cbvSrvUavNextFreeDescriptorIndex = 0; - } -} - -void QSGD3D12EnginePrivate::present() -{ - if (!initialized) - return; - - if (Q_UNLIKELY(debug_render())) - qDebug("--- present with vsync ---"); - - // This call will not block the CPU unless at least 3 buffers are queued, - // unless the waitable frame latency event is enabled. Then the latency of - // 3 is changed to whatever value desired, and blocking happens in - // beginFrame. If none of these hold, the fence-based wait in beginFrame - // throttles. Vsync (interval 1) is always enabled. - HRESULT hr = swapChain->Present(1, 0); - if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) { - deviceManager()->deviceLossDetected(); - return; - } else if (FAILED(hr)) { - qWarning("Present failed: %s", qPrintable(comErrorMessage(hr))); - return; - } - -#ifndef Q_OS_WINRT - if (dcompDevice) - dcompDevice->Commit(); -#endif - - ++presentFrameIndex; -} - -void QSGD3D12EnginePrivate::waitGPU() -{ - if (!initialized) - return; - - if (Q_UNLIKELY(debug_render())) - qDebug("--- blocking wait for GPU ---"); - - waitForGPU(presentFence); -} - -template uint newId(T *tbl) -{ - uint id = 0; - for (int i = 0; i < tbl->count(); ++i) { - if (!(*tbl)[i].entryInUse()) { - id = i + 1; - break; - } - } - - if (!id) { - tbl->resize(tbl->size() + 1); - id = tbl->count(); - } - - (*tbl)[id - 1].flags = 0x01; // reset flags and set EntryInUse - - return id; -} - -template void syncEntryFlags(T *e, int flag, bool b) -{ - if (b) - e->flags |= flag; - else - e->flags &= ~flag; -} - -uint QSGD3D12EnginePrivate::genBuffer() -{ - return newId(&buffers); -} - -void QSGD3D12EnginePrivate::releaseBuffer(uint id) -{ - if (!id || !initialized) - return; - - const int idx = id - 1; - Q_ASSERT(idx < buffers.count()); - - if (Q_UNLIKELY(debug_buffer())) - qDebug("releasing buffer %u", id); - - Buffer &b(buffers[idx]); - if (!b.entryInUse()) - return; - - // Do not null out and do not mark the entry reusable yet. - // Do that only when the frames potentially in flight have finished for sure. - - for (int i = 0; i < frameInFlightCount; ++i) { - if (b.d[i].buffer) - deferredDelete(b.d[i].buffer); - } - - QSet *pendingReleasesSet = inFrame - ? &pframeData[currentPFrameIndex].pendingReleases - : &pframeData[(currentPFrameIndex + 1) % frameInFlightCount].outOfFramePendingReleases; - - pendingReleasesSet->insert(PersistentFrameData::PendingRelease(PersistentFrameData::PendingRelease::TypeBuffer, id)); -} - -void QSGD3D12EnginePrivate::resetBuffer(uint id, const quint8 *data, int size) -{ - if (!inFrame) { - qWarning("%s: Cannot be called outside begin/endFrame", __FUNCTION__); - return; - } - - Q_ASSERT(id); - const int idx = id - 1; - Q_ASSERT(idx < buffers.count() && buffers[idx].entryInUse()); - Buffer &b(buffers[idx]); - - if (Q_UNLIKELY(debug_buffer())) - qDebug("reset buffer %u, size %d", id, size); - - b.cpuDataRef.p = data; - b.cpuDataRef.size = size; - - b.cpuDataRef.dirty.clear(); - b.d[currentPFrameIndex].dirty.clear(); - - if (size > 0) { - const QPair range = qMakePair(0, size); - b.cpuDataRef.dirty.append(range); - b.d[currentPFrameIndex].dirty.append(range); - } -} - -void QSGD3D12EnginePrivate::addDirtyRange(DirtyList *dirty, int offset, int size, int bufferSize) -{ - // Bail out when the dirty list already spans the entire buffer. - if (!dirty->isEmpty()) { - if (dirty->at(0).first == 0 && dirty->at(0).second == bufferSize) - return; - } - - const QPair range = qMakePair(offset, size); - if (!dirty->contains(range)) - dirty->append(range); -} - -void QSGD3D12EnginePrivate::markBufferDirty(uint id, int offset, int size) -{ - if (!inFrame) { - qWarning("%s: Cannot be called outside begin/endFrame", __FUNCTION__); - return; - } - - Q_ASSERT(id); - const int idx = id - 1; - Q_ASSERT(idx < buffers.count() && buffers[idx].entryInUse()); - Buffer &b(buffers[idx]); - - addDirtyRange(&b.cpuDataRef.dirty, offset, size, b.cpuDataRef.size); - addDirtyRange(&b.d[currentPFrameIndex].dirty, offset, size, b.cpuDataRef.size); -} - -uint QSGD3D12EnginePrivate::genTexture() -{ - const uint id = newId(&textures); - textures[id - 1].fenceValue = 0; - return id; -} - -static inline DXGI_FORMAT textureFormat(QImage::Format format, bool wantsAlpha, bool mipmap, bool force32bit, - QImage::Format *imageFormat, int *bytesPerPixel) -{ - DXGI_FORMAT f = DXGI_FORMAT_R8G8B8A8_UNORM; - QImage::Format convFormat = format; - int bpp = 4; - - if (!mipmap) { - switch (format) { - case QImage::Format_Grayscale8: - case QImage::Format_Indexed8: - case QImage::Format_Alpha8: - if (!force32bit) { - f = DXGI_FORMAT_R8_UNORM; - bpp = 1; - } else { - convFormat = QImage::Format_RGBA8888; - } - break; - case QImage::Format_RGB32: - f = DXGI_FORMAT_B8G8R8A8_UNORM; - break; - case QImage::Format_ARGB32: - f = DXGI_FORMAT_B8G8R8A8_UNORM; - convFormat = wantsAlpha ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32; - break; - case QImage::Format_ARGB32_Premultiplied: - f = DXGI_FORMAT_B8G8R8A8_UNORM; - convFormat = wantsAlpha ? format : QImage::Format_RGB32; - break; - default: - convFormat = wantsAlpha ? QImage::Format_RGBA8888_Premultiplied : QImage::Format_RGBX8888; - break; - } - } else { - // Mipmap generation needs unordered access and BGRA is not an option for that. Stick to RGBA. - convFormat = wantsAlpha ? QImage::Format_RGBA8888_Premultiplied : QImage::Format_RGBX8888; - } - - if (imageFormat) - *imageFormat = convFormat; - - if (bytesPerPixel) - *bytesPerPixel = bpp; - - return f; -} - -static inline QImage::Format imageFormatForTexture(DXGI_FORMAT format) -{ - QImage::Format f = QImage::Format_Invalid; - - switch (format) { - case DXGI_FORMAT_R8G8B8A8_UNORM: - f = QImage::Format_RGBA8888_Premultiplied; - break; - case DXGI_FORMAT_B8G8R8A8_UNORM: - f = QImage::Format_ARGB32_Premultiplied; - break; - case DXGI_FORMAT_R8_UNORM: - f = QImage::Format_Grayscale8; - break; - default: - break; - } - - return f; -} - -void QSGD3D12EnginePrivate::createTexture(uint id, const QSize &size, QImage::Format format, - QSGD3D12Engine::TextureCreateFlags createFlags) -{ - ensureDevice(); - - Q_ASSERT(id); - const int idx = id - 1; - Q_ASSERT(idx < textures.count() && textures[idx].entryInUse()); - Texture &t(textures[idx]); - - syncEntryFlags(&t, Texture::Alpha, createFlags & QSGD3D12Engine::TextureWithAlpha); - syncEntryFlags(&t, Texture::MipMap, createFlags & QSGD3D12Engine::TextureWithMipMaps); - - const QSize adjustedSize = !t.mipmap() ? size : QSGD3D12Engine::mipMapAdjustedSourceSize(size); - - D3D12_HEAP_PROPERTIES defaultHeapProp = {}; - defaultHeapProp.Type = D3D12_HEAP_TYPE_DEFAULT; - - D3D12_RESOURCE_DESC textureDesc = {}; - textureDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; - textureDesc.Width = adjustedSize.width(); - textureDesc.Height = adjustedSize.height(); - textureDesc.DepthOrArraySize = 1; - textureDesc.MipLevels = !t.mipmap() ? 1 : QSGD3D12Engine::mipMapLevels(adjustedSize); - textureDesc.Format = textureFormat(format, t.alpha(), t.mipmap(), - createFlags.testFlag(QSGD3D12Engine::TextureAlways32Bit), - nullptr, nullptr); - textureDesc.SampleDesc.Count = 1; - textureDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; - if (t.mipmap()) - textureDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS; - - HRESULT hr = device->CreateCommittedResource(&defaultHeapProp, D3D12_HEAP_FLAG_NONE, &textureDesc, - D3D12_RESOURCE_STATE_COMMON, nullptr, IID_PPV_ARGS(&t.texture)); - if (FAILED(hr)) { - qWarning("Failed to create texture resource: %s", qPrintable(comErrorMessage(hr))); - return; - } - - t.srv = cpuDescHeapManager.allocate(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); - - D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; - srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; - srvDesc.Format = textureDesc.Format; - srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = textureDesc.MipLevels; - - device->CreateShaderResourceView(t.texture.Get(), &srvDesc, t.srv); - - if (t.mipmap()) { - // Mipmap generation will need an UAV for each level that needs to be generated. - t.mipUAVs.clear(); - for (int level = 1; level < textureDesc.MipLevels; ++level) { - D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {}; - uavDesc.Format = textureDesc.Format; - uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D; - uavDesc.Texture2D.MipSlice = level; - D3D12_CPU_DESCRIPTOR_HANDLE h = cpuDescHeapManager.allocate(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); - device->CreateUnorderedAccessView(t.texture.Get(), nullptr, &uavDesc, h); - t.mipUAVs.append(h); - } - } - - if (Q_UNLIKELY(debug_texture())) - qDebug("created texture %u, size %dx%d, miplevels %d", id, adjustedSize.width(), adjustedSize.height(), textureDesc.MipLevels); -} - -void QSGD3D12EnginePrivate::queueTextureResize(uint id, const QSize &size) -{ - Q_ASSERT(id); - const int idx = id - 1; - Q_ASSERT(idx < textures.count() && textures[idx].entryInUse()); - Texture &t(textures[idx]); - - if (!t.texture) { - qWarning("Cannot resize non-created texture %u", id); - return; - } - - if (t.mipmap()) { - qWarning("Cannot resize mipmapped texture %u", id); - return; - } - - if (Q_UNLIKELY(debug_texture())) - qDebug("resizing texture %u, size %dx%d", id, size.width(), size.height()); - - D3D12_RESOURCE_DESC textureDesc = t.texture->GetDesc(); - textureDesc.Width = size.width(); - textureDesc.Height = size.height(); - - D3D12_HEAP_PROPERTIES defaultHeapProp = {}; - defaultHeapProp.Type = D3D12_HEAP_TYPE_DEFAULT; - - ComPtr oldTexture = t.texture; - deferredDelete(t.texture); - - HRESULT hr = device->CreateCommittedResource(&defaultHeapProp, D3D12_HEAP_FLAG_NONE, &textureDesc, - D3D12_RESOURCE_STATE_COMMON, nullptr, IID_PPV_ARGS(&t.texture)); - if (FAILED(hr)) { - qWarning("Failed to create resized texture resource: %s", - qPrintable(comErrorMessage(hr))); - return; - } - - deferredDelete(t.srv, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); - t.srv = cpuDescHeapManager.allocate(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); - - D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; - srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; - srvDesc.Format = textureDesc.Format; - srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = textureDesc.MipLevels; - - device->CreateShaderResourceView(t.texture.Get(), &srvDesc, t.srv); - - D3D12_TEXTURE_COPY_LOCATION dstLoc; - dstLoc.pResource = t.texture.Get(); - dstLoc.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; - dstLoc.SubresourceIndex = 0; - - D3D12_TEXTURE_COPY_LOCATION srcLoc; - srcLoc.pResource = oldTexture.Get(); - srcLoc.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; - srcLoc.SubresourceIndex = 0; - - copyCommandList->Reset(copyCommandAllocator.Get(), nullptr); - - copyCommandList->CopyTextureRegion(&dstLoc, 0, 0, 0, &srcLoc, nullptr); - - copyCommandList->Close(); - ID3D12CommandList *commandLists[] = { copyCommandList.Get() }; - copyCommandQueue->ExecuteCommandLists(_countof(commandLists), commandLists); - - t.fenceValue = nextTextureUploadFenceValue.fetchAndAddAcquire(1) + 1; - copyCommandQueue->Signal(textureUploadFence.Get(), t.fenceValue); - - if (Q_UNLIKELY(debug_texture())) - qDebug("submitted old content copy for texture %u on the copy queue, fence %llu", id, t.fenceValue); -} - -void QSGD3D12EnginePrivate::queueTextureUpload(uint id, const QVector &images, const QVector &dstPos, - QSGD3D12Engine::TextureUploadFlags flags) -{ - Q_ASSERT(id); - Q_ASSERT(images.count() == dstPos.count()); - if (images.isEmpty()) - return; - - const int idx = id - 1; - Q_ASSERT(idx < textures.count() && textures[idx].entryInUse()); - Texture &t(textures[idx]); - Q_ASSERT(t.texture); - - // When mipmapping is not in use, image can be smaller than the size passed - // to createTexture() and dstPos can specify a non-zero destination position. - - if (t.mipmap() && (images.count() != 1 || dstPos.count() != 1 || !dstPos[0].isNull())) { - qWarning("Mipmapped textures (%u) do not support partial uploads", id); - return; - } - - // Make life simpler by disallowing queuing a new mipmapped upload before the previous one finishes. - if (t.mipmap() && t.fenceValue) { - qWarning("Attempted to queue mipmapped texture upload (%u) while a previous upload is still in progress", id); - return; - } - - t.fenceValue = nextTextureUploadFenceValue.fetchAndAddAcquire(1) + 1; - - if (Q_UNLIKELY(debug_texture())) - qDebug("adding upload for texture %u on the copy queue, fence %llu", id, t.fenceValue); - - D3D12_RESOURCE_DESC textureDesc = t.texture->GetDesc(); - const QSize adjustedTextureSize(textureDesc.Width, textureDesc.Height); - - int totalSize = 0; - for (const QImage &image : images) { - int bytesPerPixel; - textureFormat(image.format(), t.alpha(), t.mipmap(), - flags.testFlag(QSGD3D12Engine::TextureUploadAlways32Bit), - nullptr, &bytesPerPixel); - const int w = !t.mipmap() ? image.width() : adjustedTextureSize.width(); - const int h = !t.mipmap() ? image.height() : adjustedTextureSize.height(); - const int stride = alignedSize(w * bytesPerPixel, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT); - totalSize += alignedSize(h * stride, D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT); - } - - if (Q_UNLIKELY(debug_texture())) - qDebug("%d sub-uploads, heap size %d bytes", images.count(), totalSize); - - // Instead of individual committed resources for each upload buffer, - // allocate only once and use placed resources. - D3D12_HEAP_PROPERTIES uploadHeapProp = {}; - uploadHeapProp.Type = D3D12_HEAP_TYPE_UPLOAD; - D3D12_HEAP_DESC uploadHeapDesc = {}; - uploadHeapDesc.SizeInBytes = totalSize; - uploadHeapDesc.Properties = uploadHeapProp; - uploadHeapDesc.Flags = D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS; - - Texture::StagingHeap sheap; - if (FAILED(device->CreateHeap(&uploadHeapDesc, IID_PPV_ARGS(&sheap.heap)))) { - qWarning("Failed to create texture upload heap of size %d", totalSize); - return; - } - t.stagingHeaps.append(sheap); - - copyCommandList->Reset(copyCommandAllocator.Get(), nullptr); - - int placedOffset = 0; - for (int i = 0; i < images.count(); ++i) { - QImage::Format convFormat; - int bytesPerPixel; - textureFormat(images[i].format(), t.alpha(), t.mipmap(), - flags.testFlag(QSGD3D12Engine::TextureUploadAlways32Bit), - &convFormat, &bytesPerPixel); - if (Q_UNLIKELY(debug_texture() && i == 0)) - qDebug("source image format %d, target format %d, bpp %d", images[i].format(), convFormat, bytesPerPixel); - - QImage convImage = images[i].format() == convFormat ? images[i] : images[i].convertToFormat(convFormat); - - if (t.mipmap() && adjustedTextureSize != convImage.size()) - convImage = convImage.scaled(adjustedTextureSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); - - const int stride = alignedSize(convImage.width() * bytesPerPixel, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT); - - D3D12_RESOURCE_DESC bufDesc = {}; - bufDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; - bufDesc.Width = stride * convImage.height(); - bufDesc.Height = 1; - bufDesc.DepthOrArraySize = 1; - bufDesc.MipLevels = 1; - bufDesc.Format = DXGI_FORMAT_UNKNOWN; - bufDesc.SampleDesc.Count = 1; - bufDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; - - Texture::StagingBuffer sbuf; - if (FAILED(device->CreatePlacedResource(sheap.heap.Get(), placedOffset, - &bufDesc, D3D12_RESOURCE_STATE_GENERIC_READ, - nullptr, IID_PPV_ARGS(&sbuf.buffer)))) { - qWarning("Failed to create texture upload buffer"); - return; - } - - quint8 *p = nullptr; - const D3D12_RANGE readRange = { 0, 0 }; - if (FAILED(sbuf.buffer->Map(0, &readRange, reinterpret_cast(&p)))) { - qWarning("Map failed (texture upload buffer)"); - return; - } - for (int y = 0, ye = convImage.height(); y < ye; ++y) { - memcpy(p, convImage.constScanLine(y), convImage.width() * bytesPerPixel); - p += stride; - } - sbuf.buffer->Unmap(0, nullptr); - - D3D12_TEXTURE_COPY_LOCATION dstLoc; - dstLoc.pResource = t.texture.Get(); - dstLoc.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; - dstLoc.SubresourceIndex = 0; - - D3D12_TEXTURE_COPY_LOCATION srcLoc; - srcLoc.pResource = sbuf.buffer.Get(); - srcLoc.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; - srcLoc.PlacedFootprint.Offset = 0; - srcLoc.PlacedFootprint.Footprint.Format = textureDesc.Format; - srcLoc.PlacedFootprint.Footprint.Width = convImage.width(); - srcLoc.PlacedFootprint.Footprint.Height = convImage.height(); - srcLoc.PlacedFootprint.Footprint.Depth = 1; - srcLoc.PlacedFootprint.Footprint.RowPitch = stride; - - copyCommandList->CopyTextureRegion(&dstLoc, dstPos[i].x(), dstPos[i].y(), 0, &srcLoc, nullptr); - - t.stagingBuffers.append(sbuf); - placedOffset += alignedSize(bufDesc.Width, D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT); - } - - copyCommandList->Close(); - ID3D12CommandList *commandLists[] = { copyCommandList.Get() }; - copyCommandQueue->ExecuteCommandLists(_countof(commandLists), commandLists); - copyCommandQueue->Signal(textureUploadFence.Get(), t.fenceValue); -} - -void QSGD3D12EnginePrivate::releaseTexture(uint id) -{ - if (!id || !initialized) - return; - - const int idx = id - 1; - Q_ASSERT(idx < textures.count()); - - if (Q_UNLIKELY(debug_texture())) - qDebug("releasing texture %d", id); - - Texture &t(textures[idx]); - if (!t.entryInUse()) - return; - - if (t.texture) { - deferredDelete(t.texture); - deferredDelete(t.srv, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); - for (D3D12_CPU_DESCRIPTOR_HANDLE h : t.mipUAVs) - deferredDelete(h, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); - } - - QSet *pendingReleasesSet = inFrame - ? &pframeData[currentPFrameIndex].pendingReleases - : &pframeData[(currentPFrameIndex + 1) % frameInFlightCount].outOfFramePendingReleases; - - pendingReleasesSet->insert(PersistentFrameData::PendingRelease(PersistentFrameData::PendingRelease::TypeTexture, id)); -} - -void QSGD3D12EnginePrivate::useTexture(uint id) -{ - if (!inFrame) { - qWarning("%s: Cannot be called outside begin/endFrame", __FUNCTION__); - return; - } - - Q_ASSERT(id); - const int idx = id - 1; - Q_ASSERT(idx < textures.count() && textures[idx].entryInUse()); - - // Within one frame the order of calling this function determines the - // texture register (0, 1, ...) so fill up activeTextures accordingly. - tframeData.activeTextures[tframeData.activeTextureCount++] - = TransientFrameData::ActiveTexture(TransientFrameData::ActiveTexture::TypeTexture, id); - - if (textures[idx].fenceValue) - pframeData[currentPFrameIndex].pendingTextureUploads.insert(id); -} - -bool QSGD3D12EnginePrivate::MipMapGen::initialize(QSGD3D12EnginePrivate *enginePriv) -{ - engine = enginePriv; - - D3D12_STATIC_SAMPLER_DESC sampler = {}; - sampler.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR; - sampler.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; - sampler.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; - sampler.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; - sampler.MinLOD = 0.0f; - sampler.MaxLOD = D3D12_FLOAT32_MAX; - - D3D12_DESCRIPTOR_RANGE descRange[2]; - descRange[0].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; - descRange[0].NumDescriptors = 1; - descRange[0].BaseShaderRegister = 0; // t0 - descRange[0].RegisterSpace = 0; - descRange[0].OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; - descRange[1].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV; - descRange[1].NumDescriptors = 4; - descRange[1].BaseShaderRegister = 0; // u0..u3 - descRange[1].RegisterSpace = 0; - descRange[1].OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; - - // Split into two to allow switching between the first and second set of UAVs later. - D3D12_ROOT_PARAMETER rootParameters[3]; - rootParameters[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; - rootParameters[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; - rootParameters[0].DescriptorTable.NumDescriptorRanges = 1; - rootParameters[0].DescriptorTable.pDescriptorRanges = &descRange[0]; - - rootParameters[1].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; - rootParameters[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; - rootParameters[1].DescriptorTable.NumDescriptorRanges = 1; - rootParameters[1].DescriptorTable.pDescriptorRanges = &descRange[1]; - - rootParameters[2].ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS; - rootParameters[2].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; - rootParameters[2].Constants.Num32BitValues = 4; // uint2 mip1Size, uint sampleLevel, uint totalMips - rootParameters[2].Constants.ShaderRegister = 0; // b0 - rootParameters[2].Constants.RegisterSpace = 0; - - D3D12_ROOT_SIGNATURE_DESC desc = {}; - desc.NumParameters = 3; - desc.pParameters = rootParameters; - desc.NumStaticSamplers = 1; - desc.pStaticSamplers = &sampler; - - ComPtr signature; - ComPtr error; - if (FAILED(D3D12SerializeRootSignature(&desc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error))) { - QByteArray msg(static_cast(error->GetBufferPointer()), error->GetBufferSize()); - qWarning("Failed to serialize compute root signature: %s", qPrintable(msg)); - return false; - } - if (FAILED(engine->device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), - IID_PPV_ARGS(&rootSig)))) { - qWarning("Failed to create compute root signature"); - return false; - } - - D3D12_COMPUTE_PIPELINE_STATE_DESC psoDesc = {}; - psoDesc.pRootSignature = rootSig.Get(); - psoDesc.CS.pShaderBytecode = g_CS_Generate4MipMaps; - psoDesc.CS.BytecodeLength = sizeof(g_CS_Generate4MipMaps); - - if (FAILED(engine->device->CreateComputePipelineState(&psoDesc, IID_PPV_ARGS(&pipelineState)))) { - qWarning("Failed to create compute pipeline state"); - return false; - } - - return true; -} - -void QSGD3D12EnginePrivate::MipMapGen::releaseResources() -{ - pipelineState = nullptr; - rootSig = nullptr; -} - -// The mipmap generator is used to insert commands on the main 3D queue. It is -// guaranteed that the queue has a wait for the base texture level upload -// before invoking queueGenerate(). There can be any number of invocations -// without waiting for earlier ones to finish. finished() is invoked when it is -// known for sure that frame containing the upload and mipmap generation has -// finished on the GPU. - -void QSGD3D12EnginePrivate::MipMapGen::queueGenerate(const Texture &t) -{ - D3D12_RESOURCE_DESC textureDesc = t.texture->GetDesc(); - - engine->commandList->SetPipelineState(pipelineState.Get()); - engine->commandList->SetComputeRootSignature(rootSig.Get()); - - // 1 SRV + (miplevels - 1) UAVs - const int descriptorCount = 1 + (textureDesc.MipLevels - 1); - - engine->ensureGPUDescriptorHeap(descriptorCount); - - // The descriptor heap is set on the command list either because the - // ensure() call above resized, or, typically, due to a texture-dependent - // draw call earlier. - - engine->transitionResource(t.texture.Get(), engine->commandList, - D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); - - QSGD3D12EnginePrivate::PersistentFrameData &pfd(engine->pframeData[engine->currentPFrameIndex]); - - const uint stride = engine->cpuDescHeapManager.handleSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); - D3D12_CPU_DESCRIPTOR_HANDLE h = pfd.gpuCbvSrvUavHeap->GetCPUDescriptorHandleForHeapStart(); - h.ptr += pfd.cbvSrvUavNextFreeDescriptorIndex * stride; - - engine->device->CopyDescriptorsSimple(1, h, t.srv, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); - h.ptr += stride; - - for (int level = 1; level < textureDesc.MipLevels; ++level, h.ptr += stride) - engine->device->CopyDescriptorsSimple(1, h, t.mipUAVs[level - 1], D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); - - D3D12_GPU_DESCRIPTOR_HANDLE gpuAddr = pfd.gpuCbvSrvUavHeap->GetGPUDescriptorHandleForHeapStart(); - gpuAddr.ptr += pfd.cbvSrvUavNextFreeDescriptorIndex * stride; - - engine->commandList->SetComputeRootDescriptorTable(0, gpuAddr); - gpuAddr.ptr += stride; // now points to the first UAV - - for (int level = 1; level < textureDesc.MipLevels; level += 4, gpuAddr.ptr += stride * 4) { - engine->commandList->SetComputeRootDescriptorTable(1, gpuAddr); - - QSize sz(textureDesc.Width, textureDesc.Height); - sz.setWidth(qMax(1, sz.width() >> level)); - sz.setHeight(qMax(1, sz.height() >> level)); - - const quint32 constants[4] = { quint32(sz.width()), quint32(sz.height()), - quint32(level - 1), - quint32(textureDesc.MipLevels - 1) }; - - engine->commandList->SetComputeRoot32BitConstants(2, 4, constants, 0); - engine->commandList->Dispatch(sz.width(), sz.height(), 1); - engine->uavBarrier(t.texture.Get(), engine->commandList); - } - - engine->transitionResource(t.texture.Get(), engine->commandList, - D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); - - pfd.cbvSrvUavNextFreeDescriptorIndex += descriptorCount; -} - -void QSGD3D12EnginePrivate::deferredDelete(ComPtr res) -{ - PersistentFrameData::DeleteQueueEntry e; - e.res = res; - QVector *dq = inFrame - ? &pframeData[currentPFrameIndex].deleteQueue - : &pframeData[(currentPFrameIndex + 1) % frameInFlightCount].outOfFrameDeleteQueue; - (*dq) << e; -} - -void QSGD3D12EnginePrivate::deferredDelete(ComPtr dh) -{ - PersistentFrameData::DeleteQueueEntry e; - e.descHeap = dh; - QVector *dq = inFrame - ? &pframeData[currentPFrameIndex].deleteQueue - : &pframeData[(currentPFrameIndex + 1) % frameInFlightCount].outOfFrameDeleteQueue; - (*dq) << e; -} - -void QSGD3D12EnginePrivate::deferredDelete(D3D12_CPU_DESCRIPTOR_HANDLE h, D3D12_DESCRIPTOR_HEAP_TYPE type) -{ - PersistentFrameData::DeleteQueueEntry e; - e.cpuDescriptorPtr = h.ptr; - e.descHeapType = type; - QVector *dq = inFrame - ? &pframeData[currentPFrameIndex].deleteQueue - : &pframeData[(currentPFrameIndex + 1) % frameInFlightCount].outOfFrameDeleteQueue; - (*dq) << e; -} - -uint QSGD3D12EnginePrivate::genRenderTarget() -{ - return newId(&renderTargets); -} - -void QSGD3D12EnginePrivate::createRenderTarget(uint id, const QSize &size, const QVector4D &clearColor, uint samples) -{ - ensureDevice(); - - Q_ASSERT(id); - const int idx = id - 1; - Q_ASSERT(idx < renderTargets.count() && renderTargets[idx].entryInUse()); - RenderTarget &rt(renderTargets[idx]); - - rt.rtv = cpuDescHeapManager.allocate(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); - rt.dsv = cpuDescHeapManager.allocate(D3D12_DESCRIPTOR_HEAP_TYPE_DSV); - rt.srv = cpuDescHeapManager.allocate(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); - - ID3D12Resource *res = createColorBuffer(rt.rtv, size, clearColor, samples); - if (res) - rt.color.Attach(res); - - ID3D12Resource *dsres = createDepthStencil(rt.dsv, size, samples); - if (dsres) - rt.ds.Attach(dsres); - - const bool multisample = rt.color->GetDesc().SampleDesc.Count > 1; - syncEntryFlags(&rt, RenderTarget::Multisample, multisample); - - if (!multisample) { - device->CreateShaderResourceView(rt.color.Get(), nullptr, rt.srv); - } else { - D3D12_HEAP_PROPERTIES defaultHeapProp = {}; - defaultHeapProp.Type = D3D12_HEAP_TYPE_DEFAULT; - - D3D12_RESOURCE_DESC textureDesc = {}; - textureDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; - textureDesc.Width = size.width(); - textureDesc.Height = size.height(); - textureDesc.DepthOrArraySize = 1; - textureDesc.MipLevels = 1; - textureDesc.Format = RT_COLOR_FORMAT; - textureDesc.SampleDesc.Count = 1; - textureDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; - - HRESULT hr = device->CreateCommittedResource(&defaultHeapProp, D3D12_HEAP_FLAG_NONE, &textureDesc, - D3D12_RESOURCE_STATE_COMMON, nullptr, IID_PPV_ARGS(&rt.colorResolve)); - if (FAILED(hr)) { - qWarning("Failed to create resolve buffer: %s", - qPrintable(comErrorMessage(hr))); - return; - } - - device->CreateShaderResourceView(rt.colorResolve.Get(), nullptr, rt.srv); - } - - if (Q_UNLIKELY(debug_render())) - qDebug("created new render target %u, size %dx%d, samples %d", id, size.width(), size.height(), samples); -} - -void QSGD3D12EnginePrivate::releaseRenderTarget(uint id) -{ - if (!id || !initialized) - return; - - const int idx = id - 1; - Q_ASSERT(idx < renderTargets.count()); - RenderTarget &rt(renderTargets[idx]); - if (!rt.entryInUse()) - return; - - if (Q_UNLIKELY(debug_render())) - qDebug("releasing render target %u", id); - - if (rt.colorResolve) { - deferredDelete(rt.colorResolve); - rt.colorResolve = nullptr; - } - if (rt.color) { - deferredDelete(rt.color); - rt.color = nullptr; - deferredDelete(rt.rtv, D3D12_DESCRIPTOR_HEAP_TYPE_RTV); - deferredDelete(rt.srv, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); - } - if (rt.ds) { - deferredDelete(rt.ds); - rt.ds = nullptr; - deferredDelete(rt.dsv, D3D12_DESCRIPTOR_HEAP_TYPE_DSV); - } - - rt.flags &= ~RenderTarget::EntryInUse; -} - -void QSGD3D12EnginePrivate::useRenderTargetAsTexture(uint id) -{ - if (!inFrame) { - qWarning("%s: Cannot be called outside begin/endFrame", __FUNCTION__); - return; - } - - Q_ASSERT(id); - const int idx = id - 1; - Q_ASSERT(idx < renderTargets.count()); - RenderTarget &rt(renderTargets[idx]); - Q_ASSERT(rt.entryInUse() && rt.color); - - if (rt.flags & RenderTarget::NeedsReadBarrier) { - rt.flags &= ~RenderTarget::NeedsReadBarrier; - if (rt.flags & RenderTarget::Multisample) - resolveMultisampledTarget(rt.color.Get(), rt.colorResolve.Get(), D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, commandList); - else - transitionResource(rt.color.Get(), commandList, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); - } - - tframeData.activeTextures[tframeData.activeTextureCount++] = - TransientFrameData::ActiveTexture(TransientFrameData::ActiveTexture::TypeRenderTarget, id); -} - -QImage QSGD3D12EnginePrivate::executeAndWaitReadbackRenderTarget(uint id) -{ - // Readback due to QQuickWindow::grabWindow() happens outside - // begin-endFrame, but QQuickItemGrabResult leads to rendering a layer - // without a real frame afterwards and triggering readback. This has to be - // supported as well. - if (inFrame && (!activeLayers || currentLayerDepth)) { - qWarning("%s: Cannot be called while frame preparation is active", __FUNCTION__); - return QImage(); - } - - // Due to the above we insert a fake "real" frame when a layer was just rendered into. - if (inFrame) { - beginFrame(); - endFrame(); - } - - frameCommandList->Reset(frameCommandAllocator[frameIndex % frameInFlightCount].Get(), nullptr); - - D3D12_RESOURCE_STATES bstate; - bool needsBarrier = false; - ID3D12Resource *rtRes; - if (id == 0) { - const int idx = presentFrameIndex % swapChainBufferCount; - if (windowSamples > 1) { - resolveMultisampledTarget(defaultRT[idx].Get(), backBufferRT[idx].Get(), - D3D12_RESOURCE_STATE_COPY_SOURCE, frameCommandList.Get()); - } else { - bstate = D3D12_RESOURCE_STATE_PRESENT; - needsBarrier = true; - } - rtRes = backBufferRT[idx].Get(); - } else { - const int idx = id - 1; - Q_ASSERT(idx < renderTargets.count()); - RenderTarget &rt(renderTargets[idx]); - Q_ASSERT(rt.entryInUse() && rt.color); - - if (rt.flags & RenderTarget::Multisample) { - resolveMultisampledTarget(rt.color.Get(), rt.colorResolve.Get(), - D3D12_RESOURCE_STATE_COPY_SOURCE, frameCommandList.Get()); - rtRes = rt.colorResolve.Get(); - } else { - rtRes = rt.color.Get(); - bstate = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; - needsBarrier = true; - } - } - - ComPtr readbackBuf; - - D3D12_RESOURCE_DESC rtDesc = rtRes->GetDesc(); - UINT64 textureByteSize = 0; - D3D12_PLACED_SUBRESOURCE_FOOTPRINT textureLayout = {}; - device->GetCopyableFootprints(&rtDesc, 0, 1, 0, &textureLayout, nullptr, nullptr, &textureByteSize); - - D3D12_HEAP_PROPERTIES heapProp = {}; - heapProp.Type = D3D12_HEAP_TYPE_READBACK; - - D3D12_RESOURCE_DESC bufDesc = {}; - bufDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; - bufDesc.Width = textureByteSize; - bufDesc.Height = 1; - bufDesc.DepthOrArraySize = 1; - bufDesc.MipLevels = 1; - bufDesc.Format = DXGI_FORMAT_UNKNOWN; - bufDesc.SampleDesc.Count = 1; - bufDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; - - if (FAILED(device->CreateCommittedResource(&heapProp, D3D12_HEAP_FLAG_NONE, &bufDesc, - D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_PPV_ARGS(&readbackBuf)))) { - qWarning("Failed to create committed resource (readback buffer)"); - return QImage(); - } - - D3D12_TEXTURE_COPY_LOCATION dstLoc; - dstLoc.pResource = readbackBuf.Get(); - dstLoc.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; - dstLoc.PlacedFootprint = textureLayout; - D3D12_TEXTURE_COPY_LOCATION srcLoc; - srcLoc.pResource = rtRes; - srcLoc.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; - srcLoc.SubresourceIndex = 0; - - ID3D12GraphicsCommandList *cl = frameCommandList.Get(); - if (needsBarrier) - transitionResource(rtRes, cl, bstate, D3D12_RESOURCE_STATE_COPY_SOURCE); - cl->CopyTextureRegion(&dstLoc, 0, 0, 0, &srcLoc, nullptr); - if (needsBarrier) - transitionResource(rtRes, cl, D3D12_RESOURCE_STATE_COPY_SOURCE, bstate); - - cl->Close(); - ID3D12CommandList *commandLists[] = { cl }; - commandQueue->ExecuteCommandLists(_countof(commandLists), commandLists); - - QScopedPointer f(createCPUWaitableFence()); - waitForGPU(f.data()); // uh oh - - QImage::Format fmt = imageFormatForTexture(rtDesc.Format); - if (fmt == QImage::Format_Invalid) { - qWarning("Could not map render target format %d to a QImage format", rtDesc.Format); - return QImage(); - } - QImage img(rtDesc.Width, rtDesc.Height, fmt); - quint8 *p = nullptr; - const D3D12_RANGE readRange = { 0, 0 }; - if (FAILED(readbackBuf->Map(0, &readRange, reinterpret_cast(&p)))) { - qWarning("Mapping the readback buffer failed"); - return QImage(); - } - const int bpp = 4; // ### - if (id == 0) { - for (UINT y = 0; y < rtDesc.Height; ++y) { - quint8 *dst = img.scanLine(y); - memcpy(dst, p, rtDesc.Width * bpp); - p += textureLayout.Footprint.RowPitch; - } - } else { - for (int y = rtDesc.Height - 1; y >= 0; --y) { - quint8 *dst = img.scanLine(y); - memcpy(dst, p, rtDesc.Width * bpp); - p += textureLayout.Footprint.RowPitch; - } - } - readbackBuf->Unmap(0, nullptr); - - return img; -} - -void QSGD3D12EnginePrivate::simulateDeviceLoss() -{ - qWarning("QSGD3D12Engine: Triggering device loss via TDR"); - devLossTest.killDevice(); -} - -bool QSGD3D12EnginePrivate::DeviceLossTester::initialize(QSGD3D12EnginePrivate *enginePriv) -{ - engine = enginePriv; - -#ifdef DEVLOSS_TEST - D3D12_DESCRIPTOR_RANGE descRange[2]; - descRange[0].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_CBV; - descRange[0].NumDescriptors = 1; - descRange[0].BaseShaderRegister = 0; - descRange[0].RegisterSpace = 0; - descRange[0].OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; - descRange[1].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV; - descRange[1].NumDescriptors = 1; - descRange[1].BaseShaderRegister = 0; - descRange[1].RegisterSpace = 0; - descRange[1].OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; - - D3D12_ROOT_PARAMETER param; - param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; - param.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; - param.DescriptorTable.NumDescriptorRanges = 2; - param.DescriptorTable.pDescriptorRanges = descRange; - - D3D12_ROOT_SIGNATURE_DESC desc = {}; - desc.NumParameters = 1; - desc.pParameters = ¶m; - - ComPtr signature; - ComPtr error; - if (FAILED(D3D12SerializeRootSignature(&desc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error))) { - QByteArray msg(static_cast(error->GetBufferPointer()), error->GetBufferSize()); - qWarning("Failed to serialize compute root signature: %s", qPrintable(msg)); - return false; - } - if (FAILED(engine->device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), - IID_PPV_ARGS(&computeRootSignature)))) { - qWarning("Failed to create compute root signature"); - return false; - } - - D3D12_COMPUTE_PIPELINE_STATE_DESC psoDesc = {}; - psoDesc.pRootSignature = computeRootSignature.Get(); - psoDesc.CS.pShaderBytecode = g_timeout; - psoDesc.CS.BytecodeLength = sizeof(g_timeout); - - if (FAILED(engine->device->CreateComputePipelineState(&psoDesc, IID_PPV_ARGS(&computeState)))) { - qWarning("Failed to create compute pipeline state"); - return false; - } -#endif - - return true; -} - -void QSGD3D12EnginePrivate::DeviceLossTester::releaseResources() -{ - computeState = nullptr; - computeRootSignature = nullptr; -} - -void QSGD3D12EnginePrivate::DeviceLossTester::killDevice() -{ -#ifdef DEVLOSS_TEST - ID3D12CommandAllocator *ca = engine->frameCommandAllocator[engine->frameIndex % engine->frameInFlightCount].Get(); - ID3D12GraphicsCommandList *cl = engine->frameCommandList.Get(); - cl->Reset(ca, computeState.Get()); - - cl->SetComputeRootSignature(computeRootSignature.Get()); - cl->Dispatch(256, 1, 1); - - cl->Close(); - ID3D12CommandList *commandLists[] = { cl }; - engine->commandQueue->ExecuteCommandLists(_countof(commandLists), commandLists); - - engine->waitGPU(); -#endif -} - -void *QSGD3D12EnginePrivate::getResource(QSGRendererInterface::Resource resource) const -{ - switch (resource) { - case QSGRendererInterface::DeviceResource: - return device; - case QSGRendererInterface::CommandQueueResource: - return commandQueue.Get(); - case QSGRendererInterface::CommandListResource: - return commandList; - default: - break; - } - return nullptr; -} - -QT_END_NAMESPACE diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12engine_p.h b/src/plugins/scenegraph/d3d12/qsgd3d12engine_p.h deleted file mode 100644 index b80de28bed..0000000000 --- a/src/plugins/scenegraph/d3d12/qsgd3d12engine_p.h +++ /dev/null @@ -1,394 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#ifndef QSGD3D12ENGINE_P_H -#define QSGD3D12ENGINE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include -#include -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -// No D3D or COM headers must be pulled in here. All that has to be isolated -// to engine_p_p.h and engine.cpp. - -class QSGD3D12EnginePrivate; - -// Shader bytecode and other strings are expected to be static so that a -// different pointer means a different shader. - -enum QSGD3D12Format { - FmtUnknown = 0, - - FmtFloat4 = 2, // DXGI_FORMAT_R32G32B32A32_FLOAT - FmtFloat3 = 6, // DXGI_FORMAT_R32G32B32_FLOAT - FmtFloat2 = 16, // DXGI_FORMAT_R32G32_FLOAT - FmtFloat = 41, // DXGI_FORMAT_R32_FLOAT - - // glVertexAttribPointer with GL_UNSIGNED_BYTE and normalized == true maps to the UNORM formats below - FmtUNormByte4 = 28, // DXGI_FORMAT_R8G8B8A8_UNORM - FmtUNormByte2 = 49, // DXGI_FORMAT_R8G8_UNORM - FmtUNormByte = 61, // DXGI_FORMAT_R8_UNORM - - // Index data types - FmtUnsignedShort = 57, // DXGI_FORMAT_R16_UINT - FmtUnsignedInt = 42 // DXGI_FORMAT_R32_UINT -}; - -struct QSGD3D12InputElement -{ - const char *semanticName = nullptr; - int semanticIndex = 0; - QSGD3D12Format format = FmtFloat4; - quint32 slot = 0; - quint32 offset = 0; - - bool operator==(const QSGD3D12InputElement &other) const { - return semanticName == other.semanticName && semanticIndex == other.semanticIndex - && format == other.format && slot == other.slot && offset == other.offset; - } -}; - -inline uint qHash(const QSGD3D12InputElement &key, uint seed = 0) -{ - return qHash(key.semanticName, seed) + key.semanticIndex + key.format + key.offset; -} - -struct QSGD3D12TextureView -{ - enum Filter { - FilterNearest = 0, - FilterLinear = 0x15, - FilterMinMagNearestMipLinear = 0x1, - FilterMinMagLinearMipNearest = 0x14 - }; - - enum AddressMode { - AddressWrap = 1, - AddressClamp = 3 - }; - - Filter filter = FilterLinear; - AddressMode addressModeHoriz = AddressClamp; - AddressMode addressModeVert = AddressClamp; - - bool operator==(const QSGD3D12TextureView &other) const { - return filter == other.filter - && addressModeHoriz == other.addressModeHoriz - && addressModeVert == other.addressModeVert; - } -}; - -inline uint qHash(const QSGD3D12TextureView &key, uint seed = 0) -{ - Q_UNUSED(seed); - return key.filter + key.addressModeHoriz + key.addressModeVert; -} - -const int QSGD3D12_MAX_TEXTURE_VIEWS = 8; - -struct QSGD3D12RootSignature -{ - int textureViewCount = 0; - QSGD3D12TextureView textureViews[QSGD3D12_MAX_TEXTURE_VIEWS]; - - bool operator==(const QSGD3D12RootSignature &other) const { - if (textureViewCount != other.textureViewCount) - return false; - for (int i = 0; i < textureViewCount; ++i) - if (!(textureViews[i] == other.textureViews[i])) - return false; - return true; - } -}; - -inline uint qHash(const QSGD3D12RootSignature &key, uint seed = 0) -{ - return key.textureViewCount + (key.textureViewCount > 0 ? qHash(key.textureViews[0], seed) : 0); -} - -// Shader bytecode blobs and root signature-related data. -struct QSGD3D12ShaderState -{ - const quint8 *vs = nullptr; - quint32 vsSize = 0; - const quint8 *ps = nullptr; - quint32 psSize = 0; - - QSGD3D12RootSignature rootSig; - - bool operator==(const QSGD3D12ShaderState &other) const { - return vs == other.vs && vsSize == other.vsSize - && ps == other.ps && psSize == other.psSize - && rootSig == other.rootSig; - } -}; - -inline uint qHash(const QSGD3D12ShaderState &key, uint seed = 0) -{ - return qHash(key.vs, seed) + key.vsSize + qHash(key.ps, seed) + key.psSize + qHash(key.rootSig, seed); -} - -const int QSGD3D12_MAX_INPUT_ELEMENTS = 8; - -struct QSGD3D12PipelineState -{ - enum CullMode { - CullNone = 1, - CullFront, - CullBack - }; - - enum CompareFunc { - CompareNever = 1, - CompareLess, - CompareEqual, - CompareLessEqual, - CompareGreater, - CompareNotEqual, - CompareGreaterEqual, - CompareAlways - }; - - enum StencilOp { - StencilKeep = 1, - StencilZero, - StencilReplace, - StencilIncrSat, - StencilDecrSat, - StencilInvert, - StencilIncr, - StencilDescr - }; - - enum TopologyType { - TopologyTypePoint = 1, - TopologyTypeLine, - TopologyTypeTriangle - }; - - enum BlendType { - BlendNone, - BlendPremul, // == GL_ONE, GL_ONE_MINUS_SRC_ALPHA - BlendColor // == GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_COLOR - }; - - QSGD3D12ShaderState shaders; - - int inputElementCount = 0; - QSGD3D12InputElement inputElements[QSGD3D12_MAX_INPUT_ELEMENTS]; - - CullMode cullMode = CullNone; - bool frontCCW = true; - bool colorWrite = true; - BlendType blend = BlendNone; - bool depthEnable = true; - CompareFunc depthFunc = CompareLess; - bool depthWrite = true; - bool stencilEnable = false; - CompareFunc stencilFunc = CompareEqual; - StencilOp stencilFailOp = StencilKeep; - StencilOp stencilDepthFailOp = StencilKeep; - StencilOp stencilPassOp = StencilKeep; - TopologyType topologyType = TopologyTypeTriangle; - - bool operator==(const QSGD3D12PipelineState &other) const { - bool eq = shaders == other.shaders - && inputElementCount == other.inputElementCount - && cullMode == other.cullMode - && frontCCW == other.frontCCW - && colorWrite == other.colorWrite - && blend == other.blend - && depthEnable == other.depthEnable - && (!depthEnable || depthFunc == other.depthFunc) - && depthWrite == other.depthWrite - && stencilEnable == other.stencilEnable - && (!stencilEnable || stencilFunc == other.stencilFunc) - && (!stencilEnable || stencilFailOp == other.stencilFailOp) - && (!stencilEnable || stencilDepthFailOp == other.stencilDepthFailOp) - && (!stencilEnable || stencilPassOp == other.stencilPassOp) - && topologyType == other.topologyType; - if (eq) { - for (int i = 0; i < inputElementCount; ++i) { - if (!(inputElements[i] == other.inputElements[i])) { - eq = false; - break; - } - } - } - return eq; - } -}; - -inline uint qHash(const QSGD3D12PipelineState &key, uint seed = 0) -{ - return qHash(key.shaders, seed) + key.inputElementCount - + key.cullMode + key.frontCCW - + key.colorWrite + key.blend - + key.depthEnable + key.depthWrite - + key.stencilEnable - + key.topologyType; -} - -class QSGD3D12Engine -{ -public: - QSGD3D12Engine(); - ~QSGD3D12Engine(); - - bool attachToWindow(WId window, const QSize &size, float dpr, int surfaceFormatSamples, bool alpha); - void releaseResources(); - bool hasResources() const; - void setWindowSize(const QSize &size, float dpr); - WId window() const; - QSize windowSize() const; - float windowDevicePixelRatio() const; - uint windowSamples() const; - - void beginFrame(); - void endFrame(); - void beginLayer(); - void endLayer(); - void invalidateCachedFrameState(); - void restoreFrameState(bool minimal = false); - - uint genBuffer(); - void releaseBuffer(uint id); - void resetBuffer(uint id, const quint8 *data, int size); - void markBufferDirty(uint id, int offset, int size); - - enum ClearFlag { - ClearDepth = 0x1, - ClearStencil = 0x2 - }; - Q_DECLARE_FLAGS(ClearFlags, ClearFlag) - - void queueViewport(const QRect &rect); - void queueScissor(const QRect &rect); - void queueSetRenderTarget(uint id = 0); - void queueClearRenderTarget(const QColor &color); - void queueClearDepthStencil(float depthValue, quint8 stencilValue, ClearFlags which); - void queueSetBlendFactor(const QVector4D &factor); - void queueSetStencilRef(quint32 ref); - - void finalizePipeline(const QSGD3D12PipelineState &pipelineState); - - struct DrawParams { - QSGGeometry::DrawingMode mode = QSGGeometry::DrawTriangles; - int count = 0; - uint vertexBuf = 0; - uint indexBuf = 0; - uint constantBuf = 0; - int vboOffset = 0; - int vboSize = 0; - int vboStride = 0; - int cboOffset = 0; - int startIndexIndex = -1; - QSGD3D12Format indexFormat = FmtUnsignedShort; - }; - - void queueDraw(const DrawParams ¶ms); - - void present(); - void waitGPU(); - - static quint32 alignedConstantBufferSize(quint32 size); - static QSGD3D12Format toDXGIFormat(QSGGeometry::Type sgtype, int tupleSize = 1, int *size = nullptr); - static int mipMapLevels(const QSize &size); - static QSize mipMapAdjustedSourceSize(const QSize &size); - - enum TextureCreateFlag { - TextureWithAlpha = 0x01, - TextureWithMipMaps = 0x02, - TextureAlways32Bit = 0x04 - }; - Q_DECLARE_FLAGS(TextureCreateFlags, TextureCreateFlag) - - enum TextureUploadFlag { - TextureUploadAlways32Bit = 0x01 - }; - Q_DECLARE_FLAGS(TextureUploadFlags, TextureUploadFlag) - - uint genTexture(); - void createTexture(uint id, const QSize &size, QImage::Format format, TextureCreateFlags flags); - void queueTextureResize(uint id, const QSize &size); - void queueTextureUpload(uint id, const QImage &image, const QPoint &dstPos = QPoint(), TextureUploadFlags flags = { }); - void queueTextureUpload(uint id, const QVector &images, const QVector &dstPos, TextureUploadFlags flags = { }); - void releaseTexture(uint id); - void useTexture(uint id); - - uint genRenderTarget(); - void createRenderTarget(uint id, const QSize &size, const QVector4D &clearColor, uint samples); - void releaseRenderTarget(uint id); - void useRenderTargetAsTexture(uint id); - uint activeRenderTarget() const; - - QImage executeAndWaitReadbackRenderTarget(uint id = 0); - - void simulateDeviceLoss(); - - void *getResource(QQuickWindow *window, QSGRendererInterface::Resource resource) const; - -private: - QSGD3D12EnginePrivate *d; - Q_DISABLE_COPY(QSGD3D12Engine) -}; - -Q_DECLARE_OPERATORS_FOR_FLAGS(QSGD3D12Engine::ClearFlags) -Q_DECLARE_OPERATORS_FOR_FLAGS(QSGD3D12Engine::TextureCreateFlags) -Q_DECLARE_OPERATORS_FOR_FLAGS(QSGD3D12Engine::TextureUploadFlags) - -QT_END_NAMESPACE - -#endif // QSGD3D12ENGINE_P_H diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12engine_p_p.h b/src/plugins/scenegraph/d3d12/qsgd3d12engine_p_p.h deleted file mode 100644 index a95cbb1cbb..0000000000 --- a/src/plugins/scenegraph/d3d12/qsgd3d12engine_p_p.h +++ /dev/null @@ -1,455 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#ifndef QSGD3D12ENGINE_P_P_H -#define QSGD3D12ENGINE_P_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qsgd3d12engine_p.h" -#include - -#include -#include -#include -#include - -using namespace Microsoft::WRL; - -// No moc-related features (Q_OBJECT, signals, etc.) can be used here to due -// moc-generated code failing to compile when combined with COM stuff. - -// Recommended reading before moving further: https://github.com/Microsoft/DirectXTK/wiki/ComPtr -// Note esp. operator= vs. Attach and operator& vs. GetAddressOf - -// ID3D12* is never passed to Qt containers directly. Always use ComPtr and put it into a struct. - -QT_BEGIN_NAMESPACE - -class QSGD3D12CPUDescriptorHeapManager -{ -public: - void initialize(ID3D12Device *device); - - void releaseResources(); - - D3D12_CPU_DESCRIPTOR_HANDLE allocate(D3D12_DESCRIPTOR_HEAP_TYPE type); - void release(D3D12_CPU_DESCRIPTOR_HANDLE handle, D3D12_DESCRIPTOR_HEAP_TYPE type); - quint32 handleSize(D3D12_DESCRIPTOR_HEAP_TYPE type) const { return m_handleSizes[type]; } - -private: - ID3D12Device *m_device = nullptr; - struct Heap { - D3D12_DESCRIPTOR_HEAP_TYPE type; - ComPtr heap; - D3D12_CPU_DESCRIPTOR_HANDLE start; - quint32 handleSize; - quint32 freeMap[8]; - }; - QVector m_heaps; - quint32 m_handleSizes[D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES]; -}; - -class QSGD3D12DeviceManager -{ -public: - ID3D12Device *ref(); - void unref(); - void deviceLossDetected(); - IDXGIFactory4 *dxgi(); - - struct DeviceLossObserver { - virtual void deviceLost() = 0; - virtual ~DeviceLossObserver() = default; - }; - void registerDeviceLossObserver(DeviceLossObserver *observer); - -private: - void ensureCreated(); - - ComPtr m_device; - ComPtr m_factory; - QAtomicInt m_ref; - QVector m_observers; -}; - -struct QSGD3D12CPUWaitableFence -{ - ~QSGD3D12CPUWaitableFence() { - if (event) - CloseHandle(event); - } - ComPtr fence; - HANDLE event = nullptr; - QAtomicInt value; -}; - -class QSGD3D12EnginePrivate : public QSGD3D12DeviceManager::DeviceLossObserver -{ -public: - void initialize(WId w, const QSize &size, float dpr, int surfaceFormatSamples, bool alpha); - bool isInitialized() const { return initialized; } - void releaseResources(); - void setWindowSize(const QSize &size, float dpr); - WId currentWindow() const { return window; } - QSize currentWindowSize() const { return windowSize; } - float currentWindowDpr() const { return windowDpr; } - uint currentWindowSamples() const { return windowSamples; } - - void beginFrame(); - void endFrame(); - void beginLayer(); - void endLayer(); - void invalidateCachedFrameState(); - void restoreFrameState(bool minimal = false); - - uint genBuffer(); - void releaseBuffer(uint id); - void resetBuffer(uint id, const quint8 *data, int size); - void markBufferDirty(uint id, int offset, int size); - - void queueViewport(const QRect &rect); - void queueScissor(const QRect &rect); - void queueSetRenderTarget(uint id); - void queueClearRenderTarget(const QColor &color); - void queueClearDepthStencil(float depthValue, quint8 stencilValue, QSGD3D12Engine::ClearFlags which); - void queueSetBlendFactor(const QVector4D &factor); - void queueSetStencilRef(quint32 ref); - - void finalizePipeline(const QSGD3D12PipelineState &pipelineState); - - void queueDraw(const QSGD3D12Engine::DrawParams ¶ms); - - void present(); - void waitGPU(); - - uint genTexture(); - void createTexture(uint id, const QSize &size, QImage::Format format, QSGD3D12Engine::TextureCreateFlags flags); - void queueTextureResize(uint id, const QSize &size); - void queueTextureUpload(uint id, const QVector &images, const QVector &dstPos, - QSGD3D12Engine::TextureUploadFlags flags); - void releaseTexture(uint id); - void useTexture(uint id); - - uint genRenderTarget(); - void createRenderTarget(uint id, const QSize &size, const QVector4D &clearColor, uint samples); - void releaseRenderTarget(uint id); - void useRenderTargetAsTexture(uint id); - uint activeRenderTarget() const { return currentRenderTarget; } - - QImage executeAndWaitReadbackRenderTarget(uint id); - - void simulateDeviceLoss(); - - void *getResource(QSGRendererInterface::Resource resource) const; - - // the device is intentionally hidden here. all resources have to go - // through the engine and, unlike with GL, cannot just be created in random - // places due to the need for proper tracking, managing and releasing. -private: - void ensureDevice(); - void setupDefaultRenderTargets(); - void deviceLost() override; - - bool createCbvSrvUavHeap(int pframeIndex, int descriptorCount); - void setDescriptorHeaps(bool force = false); - void ensureGPUDescriptorHeap(int cbvSrvUavDescriptorCount); - - DXGI_SAMPLE_DESC makeSampleDesc(DXGI_FORMAT format, uint samples); - ID3D12Resource *createColorBuffer(D3D12_CPU_DESCRIPTOR_HANDLE viewHandle, const QSize &size, - const QVector4D &clearColor, uint samples); - ID3D12Resource *createDepthStencil(D3D12_CPU_DESCRIPTOR_HANDLE viewHandle, const QSize &size, uint samples); - - QSGD3D12CPUWaitableFence *createCPUWaitableFence() const; - void waitForGPU(QSGD3D12CPUWaitableFence *f) const; - - void transitionResource(ID3D12Resource *resource, ID3D12GraphicsCommandList *commandList, - D3D12_RESOURCE_STATES before, D3D12_RESOURCE_STATES after) const; - void resolveMultisampledTarget(ID3D12Resource *msaa, ID3D12Resource *resolve, D3D12_RESOURCE_STATES resolveUsage, - ID3D12GraphicsCommandList *commandList) const; - void uavBarrier(ID3D12Resource *resource, ID3D12GraphicsCommandList *commandList) const; - - ID3D12Resource *createBuffer(int size); - - typedef QVector > DirtyList; - void addDirtyRange(DirtyList *dirty, int offset, int size, int bufferSize); - - struct PersistentFrameData { - ComPtr gpuCbvSrvUavHeap; - int gpuCbvSrvUavHeapSize; - int cbvSrvUavNextFreeDescriptorIndex; - QSet pendingTextureUploads; - QSet pendingTextureMipMap; - struct DeleteQueueEntry { - ComPtr res; - ComPtr descHeap; - SIZE_T cpuDescriptorPtr = 0; - D3D12_DESCRIPTOR_HEAP_TYPE descHeapType = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; - }; - QVector deleteQueue; - QVector outOfFrameDeleteQueue; - QSet buffersUsedInDrawCallSet; - QSet buffersUsedInFrame; - struct PendingRelease { - enum Type { - TypeTexture, - TypeBuffer - }; - Type type = TypeTexture; - uint id = 0; - PendingRelease(Type type, uint id) : type(type), id(id) { } - PendingRelease() { } - bool operator==(const PendingRelease &other) const { return type == other.type && id == other.id; } - }; - QSet pendingReleases; - QSet outOfFramePendingReleases; - }; - friend uint qHash(const PersistentFrameData::PendingRelease &pr, uint seed); - - void deferredDelete(ComPtr res); - void deferredDelete(ComPtr dh); - void deferredDelete(D3D12_CPU_DESCRIPTOR_HANDLE h, D3D12_DESCRIPTOR_HEAP_TYPE type); - - struct Buffer; - void ensureBuffer(Buffer *buf); - void updateBuffer(Buffer *buf); - - void beginDrawCalls(); - void beginFrameDraw(); - void endDrawCalls(bool lastInFrame = false); - - static const int MAX_SWAP_CHAIN_BUFFER_COUNT = 4; - static const int MAX_FRAME_IN_FLIGHT_COUNT = 4; - - bool initialized = false; - bool inFrame = false; - WId window = 0; - QSize windowSize; - float windowDpr; - uint windowSamples; - bool windowAlpha; - int swapChainBufferCount; - int frameInFlightCount; - int waitableSwapChainMaxLatency; - ID3D12Device *device; - ComPtr commandQueue; - ComPtr copyCommandQueue; - ComPtr swapChain; - HANDLE swapEvent; - ComPtr backBufferRT[MAX_SWAP_CHAIN_BUFFER_COUNT]; - ComPtr defaultRT[MAX_SWAP_CHAIN_BUFFER_COUNT]; - D3D12_CPU_DESCRIPTOR_HANDLE defaultRTV[MAX_SWAP_CHAIN_BUFFER_COUNT]; - ComPtr defaultDS; - D3D12_CPU_DESCRIPTOR_HANDLE defaultDSV; - ComPtr frameCommandAllocator[MAX_FRAME_IN_FLIGHT_COUNT]; - ComPtr copyCommandAllocator; - ComPtr frameCommandList; - ComPtr copyCommandList; - QSGD3D12CPUDescriptorHeapManager cpuDescHeapManager; - quint64 presentFrameIndex; - quint64 frameIndex; - QSGD3D12CPUWaitableFence *presentFence = nullptr; - QSGD3D12CPUWaitableFence *frameFence[MAX_FRAME_IN_FLIGHT_COUNT]; - - PersistentFrameData pframeData[MAX_FRAME_IN_FLIGHT_COUNT]; - int currentPFrameIndex; - ID3D12GraphicsCommandList *commandList = nullptr; - int activeLayers = 0; - int currentLayerDepth = 0; - - struct PSOCacheEntry { - ComPtr pso; - }; - QCache psoCache; - struct RootSigCacheEntry { - ComPtr rootSig; - }; - QCache rootSigCache; - - struct Texture { - enum Flag { - EntryInUse = 0x01, - Alpha = 0x02, - MipMap = 0x04 - }; - int flags = 0; - bool entryInUse() const { return flags & EntryInUse; } - bool alpha() const { return flags & Alpha; } - bool mipmap() const { return flags & MipMap; } - ComPtr texture; - D3D12_CPU_DESCRIPTOR_HANDLE srv; - quint64 fenceValue = 0; - quint64 lastWaitFenceValue = 0; - struct StagingHeap { - ComPtr heap; - }; - QVector stagingHeaps; - struct StagingBuffer { - ComPtr buffer; - }; - QVector stagingBuffers; - QVector mipUAVs; - }; - - QVector textures; - ComPtr textureUploadFence; - QAtomicInt nextTextureUploadFenceValue; - - struct TransientFrameData { - QSGGeometry::DrawingMode drawingMode; - uint currentIndexBuffer; - struct ActiveTexture { - enum Type { - TypeTexture, - TypeRenderTarget - }; - Type type = TypeTexture; - uint id = 0; - ActiveTexture(Type type, uint id) : type(type), id(id) { } - ActiveTexture() { } - }; - int activeTextureCount; - ActiveTexture activeTextures[QSGD3D12_MAX_TEXTURE_VIEWS]; - int drawCount; - ID3D12PipelineState *lastPso; - ID3D12RootSignature *lastRootSig; - bool descHeapSet; - - QRect viewport; - QRect scissor; - QVector4D blendFactor = QVector4D(1, 1, 1, 1); - quint32 stencilRef = 1; - QSGD3D12PipelineState pipelineState; - }; - TransientFrameData tframeData; - - struct MipMapGen { - bool initialize(QSGD3D12EnginePrivate *enginePriv); - void releaseResources(); - void queueGenerate(const Texture &t); - - QSGD3D12EnginePrivate *engine; - ComPtr rootSig; - ComPtr pipelineState; - }; - - MipMapGen mipmapper; - - struct RenderTarget { - enum Flag { - EntryInUse = 0x01, - NeedsReadBarrier = 0x02, - Multisample = 0x04 - }; - int flags = 0; - bool entryInUse() const { return flags & EntryInUse; } - ComPtr color; - ComPtr colorResolve; - D3D12_CPU_DESCRIPTOR_HANDLE rtv; - ComPtr ds; - D3D12_CPU_DESCRIPTOR_HANDLE dsv; - D3D12_CPU_DESCRIPTOR_HANDLE srv; - }; - - QVector renderTargets; - uint currentRenderTarget; - - struct CPUBufferRef { - const quint8 *p = nullptr; - quint32 size = 0; - DirtyList dirty; - CPUBufferRef() { dirty.reserve(16); } - }; - - struct Buffer { - enum Flag { - EntryInUse = 0x01 - }; - int flags = 0; - bool entryInUse() const { return flags & EntryInUse; } - struct InFlightData { - ComPtr buffer; - DirtyList dirty; - quint32 dataSize = 0; - quint32 resourceSize = 0; - InFlightData() { dirty.reserve(16); } - }; - InFlightData d[MAX_FRAME_IN_FLIGHT_COUNT]; - CPUBufferRef cpuDataRef; - }; - - QVector buffers; - - struct DeviceLossTester { - bool initialize(QSGD3D12EnginePrivate *enginePriv); - void releaseResources(); - void killDevice(); - - QSGD3D12EnginePrivate *engine; - ComPtr computeState; - ComPtr computeRootSignature; - }; - - DeviceLossTester devLossTest; - -#ifndef Q_OS_WINRT - ComPtr dcompDevice; - ComPtr dcompTarget; - ComPtr dcompVisual; -#endif -}; - -inline uint qHash(const QSGD3D12EnginePrivate::PersistentFrameData::PendingRelease &pr, uint seed = 0) -{ - Q_UNUSED(seed); - return pr.id + pr.type; -} - -QT_END_NAMESPACE - -#endif diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12glyphcache.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12glyphcache.cpp deleted file mode 100644 index 915917c3d5..0000000000 --- a/src/plugins/scenegraph/d3d12/qsgd3d12glyphcache.cpp +++ /dev/null @@ -1,197 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include "qsgd3d12glyphcache_p.h" -#include "qsgd3d12engine_p.h" - -QT_BEGIN_NAMESPACE - -// Convert A8 glyphs to 32-bit in the engine. This is here to work around -// QTBUG-55330 for AMD cards. -// If removing, textmask.hlsl must be adjusted! (.a -> .r) -#define ALWAYS_32BIT - -// NOTE: Avoid categorized logging. It is slow. - -#define DECLARE_DEBUG_VAR(variable) \ - static bool debug_ ## variable() \ - { static bool value = qgetenv("QSG_RENDERER_DEBUG").contains(QT_STRINGIFY(variable)); return value; } - -DECLARE_DEBUG_VAR(render) - -QSGD3D12GlyphCache::QSGD3D12GlyphCache(QSGD3D12Engine *engine, QFontEngine::GlyphFormat format, const QTransform &matrix) - : QTextureGlyphCache(format, matrix), - m_engine(engine) -{ -} - -QSGD3D12GlyphCache::~QSGD3D12GlyphCache() -{ - if (m_id) - m_engine->releaseTexture(m_id); -} - -void QSGD3D12GlyphCache::createTextureData(int width, int height) -{ - width = qMax(128, width); - height = qMax(32, height); - - m_id = m_engine->genTexture(); - Q_ASSERT(m_id); - - if (Q_UNLIKELY(debug_render())) - qDebug("new glyph cache texture %u of size %dx%d, fontengine format %d", m_id, width, height, m_format); - - m_size = QSize(width, height); - - const QImage::Format imageFormat = - m_format == QFontEngine::Format_A8 ? QImage::Format_Alpha8 : QImage::Format_ARGB32_Premultiplied; - m_engine->createTexture(m_id, m_size, imageFormat, QSGD3D12Engine::TextureWithAlpha -#ifdef ALWAYS_32BIT - | QSGD3D12Engine::TextureAlways32Bit -#endif - ); -} - -void QSGD3D12GlyphCache::resizeTextureData(int width, int height) -{ - width = qMax(128, width); - height = qMax(32, height); - - if (m_size.width() >= width && m_size.height() >= height) - return; - - if (Q_UNLIKELY(debug_render())) - qDebug("glyph cache texture %u resize to %dx%d", m_id, width, height); - - m_size = QSize(width, height); - - m_engine->queueTextureResize(m_id, m_size); -} - -void QSGD3D12GlyphCache::beginFillTexture() -{ - Q_ASSERT(m_glyphImages.isEmpty() && m_glyphPos.isEmpty()); -} - -void QSGD3D12GlyphCache::fillTexture(const Coord &c, glyph_t glyph, QFixed subPixelPosition) -{ - QImage mask = textureMapForGlyph(glyph, subPixelPosition); - const int maskWidth = mask.width(); - const int maskHeight = mask.height(); - - if (mask.format() == QImage::Format_Mono) { - mask = mask.convertToFormat(QImage::Format_Indexed8); - for (int y = 0; y < maskHeight; ++y) { - uchar *src = mask.scanLine(y); - for (int x = 0; x < maskWidth; ++x) - src[x] = -src[x]; // convert 0 and 1 into 0 and 255 - } - } else if (mask.depth() == 32) { - if (mask.format() == QImage::Format_RGB32) { - // We need to make the alpha component equal to the average of the RGB values. - // This is needed when drawing sub-pixel antialiased text on translucent targets. - for (int y = 0; y < maskHeight; ++y) { - QRgb *src = reinterpret_cast(mask.scanLine(y)); - for (int x = 0; x < maskWidth; ++x) { - const int r = qRed(src[x]); - const int g = qGreen(src[x]); - const int b = qBlue(src[x]); - int avg; - if (mask.format() == QImage::Format_RGB32) - avg = (r + g + b + 1) / 3; // "+1" for rounding. - else // Format_ARGB32_Premultiplied - avg = qAlpha(src[x]); - src[x] = qRgba(r, g, b, avg); - } - } - } - } - - m_glyphImages.append(mask); - m_glyphPos.append(QPoint(c.x, c.y)); -} - -void QSGD3D12GlyphCache::endFillTexture() -{ - if (m_glyphImages.isEmpty()) - return; - - Q_ASSERT(m_id); - - m_engine->queueTextureUpload(m_id, m_glyphImages, m_glyphPos -#ifdef ALWAYS_32BIT - , QSGD3D12Engine::TextureUploadAlways32Bit -#endif - ); - - // Nothing else left to do, it is up to the text material to call - // useTexture() which will then add the texture dependency to the frame. - - m_glyphImages.clear(); - m_glyphPos.clear(); -} - -int QSGD3D12GlyphCache::glyphPadding() const -{ - return 1; -} - -int QSGD3D12GlyphCache::maxTextureWidth() const -{ - return 16384; -} - -int QSGD3D12GlyphCache::maxTextureHeight() const -{ - return 16384; -} - -void QSGD3D12GlyphCache::useTexture() -{ - if (m_id) - m_engine->useTexture(m_id); -} - -QSize QSGD3D12GlyphCache::currentSize() const -{ - return m_size; -} - -QT_END_NAMESPACE diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12glyphcache_p.h b/src/plugins/scenegraph/d3d12/qsgd3d12glyphcache_p.h deleted file mode 100644 index 88d3d36f33..0000000000 --- a/src/plugins/scenegraph/d3d12/qsgd3d12glyphcache_p.h +++ /dev/null @@ -1,88 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#ifndef QSGD3D12GLYPHCACHE_P_H -#define QSGD3D12GLYPHCACHE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include - -QT_BEGIN_NAMESPACE - -class QSGD3D12Engine; - -class QSGD3D12GlyphCache : public QTextureGlyphCache -{ -public: - QSGD3D12GlyphCache(QSGD3D12Engine *engine, QFontEngine::GlyphFormat format, const QTransform &matrix); - ~QSGD3D12GlyphCache(); - - void createTextureData(int width, int height) override; - void resizeTextureData(int width, int height) override; - void beginFillTexture() override; - void fillTexture(const Coord &c, glyph_t glyph, QFixed subPixelPosition) override; - void endFillTexture() override; - int glyphPadding() const override; - int maxTextureWidth() const override; - int maxTextureHeight() const override; - - void useTexture(); - QSize currentSize() const; - -private: - QSGD3D12Engine *m_engine; - uint m_id = 0; - QVector m_glyphImages; - QVector m_glyphPos; - QSize m_size; -}; - -QT_END_NAMESPACE - -#endif // QSGD3D12GLYPHCACHE_P_H diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12glyphnode.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12glyphnode.cpp deleted file mode 100644 index e559739018..0000000000 --- a/src/plugins/scenegraph/d3d12/qsgd3d12glyphnode.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include "qsgd3d12glyphnode_p.h" -#include "qsgd3d12builtinmaterials_p.h" - -QT_BEGIN_NAMESPACE - -void QSGD3D12GlyphNode::setMaterialColor(const QColor &color) -{ - static_cast(m_material)->setColor(color); -} - -void QSGD3D12GlyphNode::update() -{ - QRawFont font = m_glyphs.rawFont(); - QMargins margins(0, 0, 0, 0); - - if (m_style == QQuickText::Normal) { - // QSGBasicGlyphNode dtor will delete - m_material = new QSGD3D12TextMaterial(QSGD3D12TextMaterial::Normal, m_rc, font); - } else if (m_style == QQuickText::Outline) { - QSGD3D12TextMaterial *material = new QSGD3D12TextMaterial(QSGD3D12TextMaterial::Outlined, - m_rc, font, QFontEngine::Format_A8); - material->setStyleColor(m_styleColor); - m_material = material; - margins = QMargins(1, 1, 1, 1); - } else { - QSGD3D12TextMaterial *material = new QSGD3D12TextMaterial(QSGD3D12TextMaterial::Styled, - m_rc, font, QFontEngine::Format_A8); - if (m_style == QQuickText::Sunken) { - material->setStyleShift(QVector2D(0, -1)); - margins.setTop(1); - } else if (m_style == QQuickText::Raised) { - material->setStyleShift(QVector2D(0, 1)); - margins.setBottom(1); - } - material->setStyleColor(m_styleColor); - m_material = material; - } - - QSGD3D12TextMaterial *textMaterial = static_cast(m_material); - textMaterial->setColor(m_color); - - QRectF boundingRect; - textMaterial->populate(m_position, m_glyphs.glyphIndexes(), m_glyphs.positions(), geometry(), - &boundingRect, &m_baseLine, margins); - setBoundingRect(boundingRect); - - setMaterial(m_material); - markDirty(DirtyGeometry); -} - -QT_END_NAMESPACE diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12glyphnode_p.h b/src/plugins/scenegraph/d3d12/qsgd3d12glyphnode_p.h deleted file mode 100644 index d04a8e8777..0000000000 --- a/src/plugins/scenegraph/d3d12/qsgd3d12glyphnode_p.h +++ /dev/null @@ -1,74 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#ifndef QSGD3D12GLYPHNODE_P_H -#define QSGD3D12GLYPHNODE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include - -QT_BEGIN_NAMESPACE - -class QSGD3D12RenderContext; - -class QSGD3D12GlyphNode : public QSGBasicGlyphNode -{ -public: - QSGD3D12GlyphNode(QSGD3D12RenderContext *rc) : m_rc(rc) { } - - void setMaterialColor(const QColor &color) override; - void update() override; - -private: - QSGD3D12RenderContext *m_rc; -}; - -QT_END_NAMESPACE - -#endif // QSGD3D12GLYPHNODE_P_H diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12internalimagenode.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12internalimagenode.cpp deleted file mode 100644 index aa163cacbf..0000000000 --- a/src/plugins/scenegraph/d3d12/qsgd3d12internalimagenode.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include "qsgd3d12internalimagenode_p.h" - -QT_BEGIN_NAMESPACE - -QSGD3D12InternalImageNode::QSGD3D12InternalImageNode() -{ - setMaterial(&m_material); -} - -void QSGD3D12InternalImageNode::setFiltering(QSGTexture::Filtering filtering) -{ - if (m_material.filtering() == filtering) - return; - - m_material.setFiltering(filtering); - m_smoothMaterial.setFiltering(filtering); - markDirty(DirtyMaterial); -} - -void QSGD3D12InternalImageNode::setMipmapFiltering(QSGTexture::Filtering filtering) -{ - if (m_material.mipmapFiltering() == filtering) - return; - - m_material.setMipmapFiltering(filtering); - m_smoothMaterial.setMipmapFiltering(filtering); - markDirty(DirtyMaterial); -} - -void QSGD3D12InternalImageNode::setVerticalWrapMode(QSGTexture::WrapMode wrapMode) -{ - if (m_material.verticalWrapMode() == wrapMode) - return; - - m_material.setVerticalWrapMode(wrapMode); - m_smoothMaterial.setVerticalWrapMode(wrapMode); - markDirty(DirtyMaterial); -} - -void QSGD3D12InternalImageNode::setHorizontalWrapMode(QSGTexture::WrapMode wrapMode) -{ - if (m_material.horizontalWrapMode() == wrapMode) - return; - - m_material.setHorizontalWrapMode(wrapMode); - m_smoothMaterial.setHorizontalWrapMode(wrapMode); - markDirty(DirtyMaterial); -} - -void QSGD3D12InternalImageNode::updateMaterialAntialiasing() -{ - if (m_antialiasing) - setMaterial(&m_smoothMaterial); - else - setMaterial(&m_material); -} - -void QSGD3D12InternalImageNode::setMaterialTexture(QSGTexture *texture) -{ - m_material.setTexture(texture); - m_smoothMaterial.setTexture(texture); -} - -QSGTexture *QSGD3D12InternalImageNode::materialTexture() const -{ - return m_material.texture(); -} - -bool QSGD3D12InternalImageNode::updateMaterialBlending() -{ - const bool alpha = m_material.flags() & QSGMaterial::Blending; - if (materialTexture() && alpha != materialTexture()->hasAlphaChannel()) { - m_material.setFlag(QSGMaterial::Blending, !alpha); - return true; - } - return false; -} - -bool QSGD3D12InternalImageNode::supportsWrap(const QSize &) const -{ - return true; -} - -QT_END_NAMESPACE diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12internalimagenode_p.h b/src/plugins/scenegraph/d3d12/qsgd3d12internalimagenode_p.h deleted file mode 100644 index 26284740ee..0000000000 --- a/src/plugins/scenegraph/d3d12/qsgd3d12internalimagenode_p.h +++ /dev/null @@ -1,82 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#ifndef QSGD3D12INTERNALIMAGENODE_P_H -#define QSGD3D12INTERNALIMAGENODE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include -#include "qsgd3d12builtinmaterials_p.h" - -QT_BEGIN_NAMESPACE - -class QSGD3D12InternalImageNode : public QSGBasicInternalImageNode -{ -public: - QSGD3D12InternalImageNode(); - - void setMipmapFiltering(QSGTexture::Filtering filtering) override; - void setFiltering(QSGTexture::Filtering filtering) override; - void setHorizontalWrapMode(QSGTexture::WrapMode wrapMode) override; - void setVerticalWrapMode(QSGTexture::WrapMode wrapMode) override; - - void updateMaterialAntialiasing() override; - void setMaterialTexture(QSGTexture *texture) override; - QSGTexture *materialTexture() const override; - bool updateMaterialBlending() override; - bool supportsWrap(const QSize &size) const override; - -private: - QSGD3D12TextureMaterial m_material; - QSGD3D12SmoothTextureMaterial m_smoothMaterial; -}; - -QT_END_NAMESPACE - -#endif // QSGD3D12INTERNALIMAGENODE_P_H diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12internalrectanglenode.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12internalrectanglenode.cpp deleted file mode 100644 index 2d9c5b55d1..0000000000 --- a/src/plugins/scenegraph/d3d12/qsgd3d12internalrectanglenode.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include "qsgd3d12internalrectanglenode_p.h" - -QT_BEGIN_NAMESPACE - -QSGD3D12InternalRectangleNode::QSGD3D12InternalRectangleNode() -{ - setMaterial(&m_material); -} - -void QSGD3D12InternalRectangleNode::updateMaterialAntialiasing() -{ - if (m_antialiasing) - setMaterial(&m_smoothMaterial); - else - setMaterial(&m_material); -} - -void QSGD3D12InternalRectangleNode::updateMaterialBlending(QSGNode::DirtyState *state) -{ - // smoothed material is always blended, so no change in material state - if (material() == &m_material) { - bool wasBlending = (m_material.flags() & QSGMaterial::Blending); - bool isBlending = (m_gradient_stops.size() > 0 && !m_gradient_is_opaque) - || (m_color.alpha() < 255 && m_color.alpha() != 0) - || (m_pen_width > 0 && m_border_color.alpha() < 255); - if (wasBlending != isBlending) { - m_material.setFlag(QSGMaterial::Blending, isBlending); - *state |= QSGNode::DirtyMaterial; - } - } -} - -QT_END_NAMESPACE diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12internalrectanglenode_p.h b/src/plugins/scenegraph/d3d12/qsgd3d12internalrectanglenode_p.h deleted file mode 100644 index 2fc3c69285..0000000000 --- a/src/plugins/scenegraph/d3d12/qsgd3d12internalrectanglenode_p.h +++ /dev/null @@ -1,74 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#ifndef QSGD3D12INTERNALRECTANGLENODE_P_H -#define QSGD3D12INTERNALRECTANGLENODE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include -#include "qsgd3d12builtinmaterials_p.h" - -QT_BEGIN_NAMESPACE - -class QSGD3D12InternalRectangleNode : public QSGBasicInternalRectangleNode -{ -public: - QSGD3D12InternalRectangleNode(); - -private: - void updateMaterialAntialiasing() override; - void updateMaterialBlending(QSGNode::DirtyState *state) override; - - QSGD3D12VertexColorMaterial m_material; - QSGD3D12SmoothColorMaterial m_smoothMaterial; -}; - -QT_END_NAMESPACE - -#endif // QSGD3D12INTERNALRECTANGLENODE_P_H diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12layer.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12layer.cpp deleted file mode 100644 index b9d3a180cf..0000000000 --- a/src/plugins/scenegraph/d3d12/qsgd3d12layer.cpp +++ /dev/null @@ -1,370 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include "qsgd3d12layer_p.h" -#include "qsgd3d12rendercontext_p.h" -#include "qsgd3d12engine_p.h" -#include "qsgd3d12renderer_p.h" - -QT_BEGIN_NAMESPACE - -// NOTE: Avoid categorized logging. It is slow. - -#define DECLARE_DEBUG_VAR(variable) \ - static bool debug_ ## variable() \ - { static bool value = qgetenv("QSG_RENDERER_DEBUG").contains(QT_STRINGIFY(variable)); return value; } - -DECLARE_DEBUG_VAR(render) - -QSGD3D12Layer::QSGD3D12Layer(QSGD3D12RenderContext *rc) - : QSGLayer(*(new QSGD3D12LayerPrivate)), - m_rc(rc) -{ - if (Q_UNLIKELY(debug_render())) - qDebug("new layer %p", this); -} - -QSGD3D12Layer::~QSGD3D12Layer() -{ - if (Q_UNLIKELY(debug_render())) - qDebug("destroying layer %p", this); - - cleanup(); -} - -// QSGTexture - -int QSGD3D12Layer::textureId() const -{ - return m_rt; // not a texture id per se but will do -} - -int QSGD3D12LayerPrivate::comparisonKey() const -{ - Q_Q(const QSGD3D12Layer); - return q->m_rt; -} - -QSize QSGD3D12Layer::textureSize() const -{ - return m_size; -} - -bool QSGD3D12Layer::hasAlphaChannel() const -{ - return true; -} - -bool QSGD3D12Layer::hasMipmaps() const -{ - // mipmapped layers are not supported for now - return false; -} - -QRectF QSGD3D12Layer::normalizedTextureSubRect() const -{ - return QRectF(m_mirrorHorizontal ? 1 : 0, - m_mirrorVertical ? 0 : 1, - m_mirrorHorizontal ? -1 : 1, - m_mirrorVertical ? 1 : -1); -} - -void QSGD3D12Layer::bind() -{ - if (Q_UNLIKELY(debug_render())) - qDebug("layer %p bind rt=%u", this, m_rt); - - QSGD3D12Engine *engine = m_rc->engine(); - Q_ASSERT(m_rt); - -#ifndef QT_NO_DEBUG - // Should not use the color buffer as a texture while it is the current render target. - if (!m_recursive && engine->activeRenderTarget() == m_rt && engine->windowSamples() == 1) - qWarning("ShaderEffectSource: \'recursive\' must be set to true when rendering recursively."); -#endif - - engine->useRenderTargetAsTexture(m_rt); -} - -// QSGDynamicTexture - -bool QSGD3D12Layer::updateTexture() -{ - if (Q_UNLIKELY(debug_render())) - qDebug("layer %p updateTexture", this); - - const bool doUpdate = (m_live || m_updateContentPending) && m_dirtyTexture; - - if (doUpdate) - updateContent(); - - if (m_updateContentPending) { - m_updateContentPending = false; - emit scheduledUpdateCompleted(); - } - - return doUpdate; -} - -// QSGLayer - -void QSGD3D12Layer::setItem(QSGNode *item) -{ - if (m_item == item) - return; - - if (m_live && !item) - resetRenderTarget(); - - m_item = item; - markDirtyTexture(); -} - -void QSGD3D12Layer::setRect(const QRectF &rect) -{ - if (m_rect == rect) - return; - - m_rect = rect; - markDirtyTexture(); -} - -void QSGD3D12Layer::setSize(const QSize &size) -{ - if (m_size == size) - return; - - if (m_live && size.isNull()) - resetRenderTarget(); - - m_size = size; - markDirtyTexture(); -} - -void QSGD3D12Layer::scheduleUpdate() -{ - if (m_updateContentPending) - return; - - if (Q_UNLIKELY(debug_render())) - qDebug("layer %p scheduleUpdate", this); - - m_updateContentPending = true; - - if (m_dirtyTexture) - emit updateRequested(); -} - -QImage QSGD3D12Layer::toImage() const -{ - return m_rc->engine()->executeAndWaitReadbackRenderTarget(m_rt); -} - -void QSGD3D12Layer::setLive(bool live) -{ - if (m_live == live) - return; - - if (live && (!m_item || m_size.isNull())) - resetRenderTarget(); - - m_live = live; - markDirtyTexture(); -} - -void QSGD3D12Layer::setRecursive(bool recursive) -{ - m_recursive = recursive; -} - -void QSGD3D12Layer::setFormat(uint format) -{ - Q_UNUSED(format); -} - -void QSGD3D12Layer::setHasMipmaps(bool mipmap) -{ - // mipmapped layers are not supported for now - Q_UNUSED(mipmap); -} - -void QSGD3D12Layer::setDevicePixelRatio(qreal ratio) -{ - m_dpr = ratio; -} - -void QSGD3D12Layer::setMirrorHorizontal(bool mirror) -{ - m_mirrorHorizontal = mirror; -} - -void QSGD3D12Layer::setMirrorVertical(bool mirror) -{ - m_mirrorVertical = mirror; -} - -void QSGD3D12Layer::markDirtyTexture() -{ - if (Q_UNLIKELY(debug_render())) - qDebug("layer %p markDirtyTexture", this); - - m_dirtyTexture = true; - - if (m_live || m_updateContentPending) - emit updateRequested(); -} - -void QSGD3D12Layer::invalidated() -{ - cleanup(); -} - -void QSGD3D12Layer::cleanup() -{ - if (!m_renderer && !m_rt) - return; - - if (Q_UNLIKELY(debug_render())) - qDebug("layer %p cleanup renderer=%p rt=%u", this, m_renderer, m_rt); - - delete m_renderer; - m_renderer = nullptr; - - resetRenderTarget(); -} - -void QSGD3D12Layer::resetRenderTarget() -{ - if (!m_rt) - return; - - if (Q_UNLIKELY(debug_render())) - qDebug("layer %p resetRenderTarget rt=%u", this, m_rt); - - m_rc->engine()->releaseRenderTarget(m_rt); - m_rt = 0; - - if (m_secondaryRT) { - m_rc->engine()->releaseRenderTarget(m_secondaryRT); - m_secondaryRT = 0; - } -} - -void QSGD3D12Layer::updateContent() -{ - if (Q_UNLIKELY(debug_render())) - qDebug("layer %p updateContent", this); - - if (!m_item || m_size.isNull()) { - resetRenderTarget(); - m_dirtyTexture = false; - return; - } - - QSGNode *root = m_item; - while (root->firstChild() && root->type() != QSGNode::RootNodeType) - root = root->firstChild(); - - if (root->type() != QSGNode::RootNodeType) - return; - - if (!m_renderer) { - m_renderer = m_rc->createRenderer(); - static_cast(m_renderer)->turnToLayerRenderer(); - connect(m_renderer, &QSGRenderer::sceneGraphChanged, this, &QSGD3D12Layer::markDirtyTexture); - } - - m_renderer->setDevicePixelRatio(m_dpr); - m_renderer->setRootNode(static_cast(root)); - - QSGD3D12Engine *engine = m_rc->engine(); - const uint sampleCount = engine->windowSamples(); - const QVector4D clearColor; - - if (!m_rt || m_rtSize != m_size) { - if (m_rt) - resetRenderTarget(); - - m_rt = engine->genRenderTarget(); - m_rtSize = m_size; - - if (Q_UNLIKELY(debug_render())) - qDebug("new render target for layer %p, size=%dx%d, samples=%d", - this, m_size.width(), m_size.height(), sampleCount); - - engine->createRenderTarget(m_rt, m_rtSize, clearColor, sampleCount); - - // For multisampling the resolving via an extra non-ms color buffer is - // handled internally in the engine, no need to worry about it here. - } - - if (m_recursive && !m_secondaryRT && sampleCount == 1) { - m_secondaryRT = engine->genRenderTarget(); - engine->createRenderTarget(m_secondaryRT, m_rtSize, clearColor, sampleCount); - } - - m_dirtyTexture = false; - - m_renderer->setDeviceRect(m_size); - m_renderer->setViewportRect(m_size); - - // Note that the handling of vertical mirroring differs from OpenGL here - // due to y running top-bottom with D3D as opposed to bottom-top with GL. - // The common parts of Quick follow OpenGL so vertical mirroring is - // typically enabled. - QRectF mirrored(m_mirrorHorizontal ? m_rect.right() : m_rect.left(), - m_mirrorVertical ? m_rect.top() : m_rect.bottom(), - m_mirrorHorizontal ? -m_rect.width() : m_rect.width(), - m_mirrorVertical ? m_rect.height() : -m_rect.height()); - - m_renderer->setProjectionMatrixToRect(mirrored); - m_renderer->setClearColor(Qt::transparent); - - if (!m_recursive || sampleCount > 1) { - m_renderer->renderScene(m_rt); - } else { - m_renderer->renderScene(m_secondaryRT); - qSwap(m_rt, m_secondaryRT); - } - - if (m_recursive) - markDirtyTexture(); // Continuously update if 'live' and 'recursive'. -} - -QT_END_NAMESPACE diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12layer_p.h b/src/plugins/scenegraph/d3d12/qsgd3d12layer_p.h deleted file mode 100644 index 42a56877cf..0000000000 --- a/src/plugins/scenegraph/d3d12/qsgd3d12layer_p.h +++ /dev/null @@ -1,129 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#ifndef QSGD3D12LAYER_P_H -#define QSGD3D12LAYER_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include -#include - -QT_BEGIN_NAMESPACE - -class QSGD3D12RenderContext; -class QSGD3D12LayerPrivate; - -class QSGD3D12Layer : public QSGLayer -{ - Q_DECLARE_PRIVATE(QSGD3D12Layer) - Q_OBJECT - -public: - QSGD3D12Layer(QSGD3D12RenderContext *rc); - ~QSGD3D12Layer(); - - int textureId() const override; - QSize textureSize() const override; - bool hasAlphaChannel() const override; - bool hasMipmaps() const override; - QRectF normalizedTextureSubRect() const override; - void bind() override; - - bool updateTexture() override; - - void setItem(QSGNode *item) override; - void setRect(const QRectF &rect) override; - void setSize(const QSize &size) override; - void scheduleUpdate() override; - QImage toImage() const override; - void setLive(bool live) override; - void setRecursive(bool recursive) override; - void setFormat(uint format) override; - void setHasMipmaps(bool mipmap) override; - void setDevicePixelRatio(qreal ratio) override; - void setMirrorHorizontal(bool mirror) override; - void setMirrorVertical(bool mirror) override; - void setSamples(int) override { } - -public Q_SLOTS: - void markDirtyTexture() override; - void invalidated() override; - -private: - void cleanup(); - void resetRenderTarget(); - void updateContent(); - - QSGD3D12RenderContext *m_rc; - uint m_rt = 0; - uint m_secondaryRT = 0; - QSize m_rtSize; - QSize m_size; - QRectF m_rect; - QSGNode *m_item = nullptr; - QSGRenderer *m_renderer = nullptr; - float m_dpr = 1; - bool m_mirrorHorizontal = false; - bool m_mirrorVertical = true; - bool m_live = true; - bool m_recursive = false; - bool m_dirtyTexture = true; - bool m_updateContentPending = false; -}; - -class QSGD3D12LayerPrivate : public QSGTexturePrivate -{ - Q_DECLARE_PUBLIC(QSGD3D12Layer) -public: - int comparisonKey() const override; -}; - -QT_END_NAMESPACE - -#endif // QSGD3D12LAYER_P_H diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12material.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12material.cpp deleted file mode 100644 index 1b638106ee..0000000000 --- a/src/plugins/scenegraph/d3d12/qsgd3d12material.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include "qsgd3d12material_p.h" - -QT_BEGIN_NAMESPACE - -QSGMaterialShader *QSGD3D12Material::createShader() const -{ - return nullptr; -} - -QT_END_NAMESPACE diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12material_p.h b/src/plugins/scenegraph/d3d12/qsgd3d12material_p.h deleted file mode 100644 index 65d53600c3..0000000000 --- a/src/plugins/scenegraph/d3d12/qsgd3d12material_p.h +++ /dev/null @@ -1,96 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#ifndef QSGD3D12MATERIAL_P_H -#define QSGD3D12MATERIAL_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include -#include "qsgd3d12engine_p.h" - -QT_BEGIN_NAMESPACE - -class QSGRenderer; - -// The D3D renderer works with QSGD3D12Material as the "base" class since -// QSGMaterial and its GL program related bits are not suitable. Also, there is -// no split like with QSGMaterialShader. - -typedef QSGMaterialShader::RenderState QSGD3D12MaterialRenderState; - -class QSGD3D12Material : public QSGMaterial -{ -public: - struct ExtraState { - QVector4D blendFactor; - }; - - enum UpdateResult { - UpdatedShaders = 0x0001, - UpdatedConstantBuffer = 0x0002, - UpdatedBlendFactor = 0x0004 - }; - Q_DECLARE_FLAGS(UpdateResults, UpdateResult) - - virtual int constantBufferSize() const = 0; - virtual void preparePipeline(QSGD3D12PipelineState *pipelineState) = 0; - virtual UpdateResults updatePipeline(const QSGD3D12MaterialRenderState &state, - QSGD3D12PipelineState *pipelineState, - ExtraState *extraState, - quint8 *constantBuffer) = 0; - -private: - QSGMaterialShader *createShader() const override; // dummy, QSGMaterialShader is too GL dependent -}; - -Q_DECLARE_OPERATORS_FOR_FLAGS(QSGD3D12Material::UpdateResults) - -QT_END_NAMESPACE - -#endif // QSGD3D12MATERIAL_P_H diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12painternode.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12painternode.cpp deleted file mode 100644 index b22c42f2e5..0000000000 --- a/src/plugins/scenegraph/d3d12/qsgd3d12painternode.cpp +++ /dev/null @@ -1,255 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include "qsgd3d12painternode_p.h" -#include "qsgd3d12rendercontext_p.h" -#include "qsgd3d12engine_p.h" -#include -#include - -QT_BEGIN_NAMESPACE - -QSGD3D12PainterTexture::QSGD3D12PainterTexture(QSGD3D12Engine *engine) - : QSGD3D12Texture(engine) -{ -} - -void QSGD3D12PainterTexture::bind() -{ - if (m_image.isNull()) { - if (!m_id) { - m_id = m_engine->genTexture(); - m_engine->createTexture(m_id, QSize(16, 16), QImage::Format_RGB32, 0); - } - } else if (m_image.size() != lastSize) { - lastSize = m_image.size(); - if (m_id) - m_engine->releaseTexture(m_id); - m_id = m_engine->genTexture(); - m_engine->createTexture(m_id, m_image.size(), m_image.format(), QSGD3D12Engine::TextureWithAlpha); - m_engine->queueTextureUpload(m_id, m_image); - } else if (!dirty.isEmpty()) { - const int bpl = m_image.bytesPerLine(); - const uchar *p = m_image.constBits() + dirty.y() * bpl + dirty.x() * 4; - QImage subImg(p, dirty.width(), dirty.height(), bpl, QImage::Format_ARGB32_Premultiplied); - m_engine->queueTextureUpload(m_id, subImg, dirty.topLeft()); - } - - dirty = QRect(); - - m_engine->useTexture(m_id); -} - -QSGD3D12PainterNode::QSGD3D12PainterNode(QQuickPaintedItem *item) - : m_item(item), - m_engine(static_cast(QQuickItemPrivate::get(item)->sceneGraphRenderContext())->engine()), - m_texture(new QSGD3D12PainterTexture(m_engine)), - m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4), - m_dirtyGeometry(false), - m_dirtyContents(false) -{ - setGeometry(&m_geometry); - m_material.setTexture(m_texture); - setMaterial(&m_material); -} - -QSGD3D12PainterNode::~QSGD3D12PainterNode() -{ - delete m_texture; -} - -void QSGD3D12PainterNode::setPreferredRenderTarget(QQuickPaintedItem::RenderTarget) -{ - // always QImage-based -} - -void QSGD3D12PainterNode::setSize(const QSize &size) -{ - if (m_size == size) - return; - - m_size = size; - m_dirtyGeometry = true; -} - -void QSGD3D12PainterNode::setDirty(const QRect &dirtyRect) -{ - m_dirtyRect = dirtyRect; - m_dirtyContents = true; - markDirty(DirtyMaterial); -} - -void QSGD3D12PainterNode::setOpaquePainting(bool) -{ - // ignored -} - -void QSGD3D12PainterNode::setLinearFiltering(bool linearFiltering) -{ - m_material.setFiltering(linearFiltering ? QSGTexture::Linear : QSGTexture::Nearest); - markDirty(DirtyMaterial); -} - -void QSGD3D12PainterNode::setMipmapping(bool) -{ - // ### not yet -} - -void QSGD3D12PainterNode::setSmoothPainting(bool s) -{ - if (m_smoothPainting == s) - return; - - m_smoothPainting = s; - m_dirtyContents = true; - markDirty(DirtyMaterial); -} - -void QSGD3D12PainterNode::setFillColor(const QColor &c) -{ - if (m_fillColor == c) - return; - - m_fillColor = c; - m_dirtyContents = true; - markDirty(DirtyMaterial); -} - -void QSGD3D12PainterNode::setContentsScale(qreal s) -{ - if (m_contentsScale == s) - return; - - m_contentsScale = s; - m_dirtyContents = true; - markDirty(DirtyMaterial); -} - -void QSGD3D12PainterNode::setFastFBOResizing(bool) -{ - // nope -} - -void QSGD3D12PainterNode::setTextureSize(const QSize &size) -{ - if (m_textureSize == size) - return; - - m_textureSize = size; - m_dirtyGeometry = true; -} - -QImage QSGD3D12PainterNode::toImage() const -{ - return *m_texture->image(); -} - -void QSGD3D12PainterNode::update() -{ - if (m_dirtyGeometry) { - m_dirtyGeometry = false; - QRectF src(0, 0, 1, 1); - QRectF dst(QPointF(0, 0), m_size); - QSGGeometry::updateTexturedRectGeometry(&m_geometry, dst, src); - markDirty(DirtyGeometry); - } - - QImage *img = m_texture->image(); - if (img->size() != m_textureSize) { - *img = QImage(m_textureSize, QImage::Format_ARGB32_Premultiplied); - img->fill(Qt::transparent); - m_dirtyContents = true; - } - - if (m_dirtyContents) { - m_dirtyContents = false; - if (!img->isNull()) { - QRect dirtyRect = m_dirtyRect.isNull() ? QRect(QPoint(0, 0), m_size) : m_dirtyRect; - QPainter painter; - painter.begin(img); - if (m_smoothPainting) - painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform); - - QRect clipRect; - QRect dirtyTextureRect; - - if (m_contentsScale == 1) { - float scaleX = m_textureSize.width() / (float) m_size.width(); - float scaleY = m_textureSize.height() / (float) m_size.height(); - painter.scale(scaleX, scaleY); - clipRect = dirtyRect; - dirtyTextureRect = QRectF(dirtyRect.x() * scaleX, - dirtyRect.y() * scaleY, - dirtyRect.width() * scaleX, - dirtyRect.height() * scaleY).toAlignedRect(); - } else { - painter.scale(m_contentsScale, m_contentsScale); - QRect sclip(qFloor(dirtyRect.x() / m_contentsScale), - qFloor(dirtyRect.y() / m_contentsScale), - qCeil(dirtyRect.width() / m_contentsScale + dirtyRect.x() / m_contentsScale - - qFloor(dirtyRect.x() / m_contentsScale)), - qCeil(dirtyRect.height() / m_contentsScale + dirtyRect.y() / m_contentsScale - - qFloor(dirtyRect.y() / m_contentsScale))); - clipRect = sclip; - dirtyTextureRect = dirtyRect; - } - - // only clip if we were originally updating only a subrect - if (!m_dirtyRect.isNull()) - painter.setClipRect(clipRect); - - painter.setCompositionMode(QPainter::CompositionMode_Source); - painter.fillRect(clipRect, m_fillColor); - painter.setCompositionMode(QPainter::CompositionMode_SourceOver); - - m_item->paint(&painter); - painter.end(); - - m_texture->dirty = dirtyTextureRect; - } - m_dirtyRect = QRect(); - } -} - -QSGTexture *QSGD3D12PainterNode::texture() const -{ - return m_texture; -} - -QT_END_NAMESPACE diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12painternode_p.h b/src/plugins/scenegraph/d3d12/qsgd3d12painternode_p.h deleted file mode 100644 index 7f4842b3a6..0000000000 --- a/src/plugins/scenegraph/d3d12/qsgd3d12painternode_p.h +++ /dev/null @@ -1,120 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#ifndef QSGD3D12PAINTERNODE_P_H -#define QSGD3D12PAINTERNODE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include -#include "qsgd3d12texture_p.h" -#include "qsgd3d12builtinmaterials_p.h" - -QT_BEGIN_NAMESPACE - -class QSGD3D12Engine; - -class QSGD3D12PainterTexture : public QSGD3D12Texture -{ -public: - QSGD3D12PainterTexture(QSGD3D12Engine *engine); - - void bind() override; - bool hasAlphaChannel() const override { return true; } - - QImage *image() { return &m_image; } - - QRect dirty; - -private: - QSize lastSize; -}; - -class QSGD3D12PainterNode : public QSGPainterNode -{ -public: - QSGD3D12PainterNode(QQuickPaintedItem *item); - ~QSGD3D12PainterNode(); - - void setPreferredRenderTarget(QQuickPaintedItem::RenderTarget target) override; - void setSize(const QSize &size) override; - void setDirty(const QRect &dirtyRect = QRect()) override; - void setOpaquePainting(bool opaque) override; - void setLinearFiltering(bool linearFiltering) override; - void setMipmapping(bool mipmapping) override; - void setSmoothPainting(bool s) override; - void setFillColor(const QColor &c) override; - void setContentsScale(qreal s) override; - void setFastFBOResizing(bool dynamic) override; - void setTextureSize(const QSize &size) override; - - QImage toImage() const override; - void update() override; - QSGTexture *texture() const override; - -private: - QQuickPaintedItem *m_item; - QSGD3D12Engine *m_engine; - QSGD3D12PainterTexture *m_texture; - QSize m_size; - QSize m_textureSize; - float m_contentsScale = 1; - bool m_smoothPainting = false; - QColor m_fillColor = Qt::transparent; - QRect m_dirtyRect; - - QSGGeometry m_geometry; - QSGD3D12TextureMaterial m_material; - - uint m_dirtyGeometry : 1; - uint m_dirtyContents : 1; -}; - -QT_END_NAMESPACE - -#endif // QSGD3D12PAINTERNODE_P_H diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12publicnodes.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12publicnodes.cpp deleted file mode 100644 index 1f01c440e5..0000000000 --- a/src/plugins/scenegraph/d3d12/qsgd3d12publicnodes.cpp +++ /dev/null @@ -1,250 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include "qsgd3d12publicnodes_p.h" - -QT_BEGIN_NAMESPACE - -QSGD3D12RectangleNode::QSGD3D12RectangleNode() - : m_geometry(QSGGeometry::defaultAttributes_Point2D(), 4) -{ - QSGGeometry::updateRectGeometry(&m_geometry, QRectF()); - setMaterial(&m_material); - setGeometry(&m_geometry); -#ifdef QSG_RUNTIME_DESCRIPTION - qsgnode_set_description(this, QLatin1String("rectangle")); -#endif -} - -void QSGD3D12RectangleNode::setRect(const QRectF &rect) -{ - QSGGeometry::updateRectGeometry(&m_geometry, rect); - markDirty(QSGNode::DirtyGeometry); -} - -QRectF QSGD3D12RectangleNode::rect() const -{ - const QSGGeometry::Point2D *pts = m_geometry.vertexDataAsPoint2D(); - return QRectF(pts[0].x, - pts[0].y, - pts[3].x - pts[0].x, - pts[3].y - pts[0].y); -} - -void QSGD3D12RectangleNode::setColor(const QColor &color) -{ - if (color != m_material.color()) { - m_material.setColor(color); - markDirty(QSGNode::DirtyMaterial); - } -} - -QColor QSGD3D12RectangleNode::color() const -{ - return m_material.color(); -} - -QSGD3D12ImageNode::QSGD3D12ImageNode() - : m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4), - m_texCoordMode(QSGD3D12ImageNode::NoTransform), - m_isAtlasTexture(false), - m_ownsTexture(false) -{ - setGeometry(&m_geometry); - setMaterial(&m_material); - m_material.setMipmapFiltering(QSGTexture::None); -#ifdef QSG_RUNTIME_DESCRIPTION - qsgnode_set_description(this, QLatin1String("image")); -#endif -} - -QSGD3D12ImageNode::~QSGD3D12ImageNode() -{ - if (m_ownsTexture) - delete m_material.texture(); -} - -void QSGD3D12ImageNode::setFiltering(QSGTexture::Filtering filtering) -{ - if (m_material.filtering() == filtering) - return; - - m_material.setFiltering(filtering); - markDirty(DirtyMaterial); -} - -QSGTexture::Filtering QSGD3D12ImageNode::filtering() const -{ - return m_material.filtering(); -} - -void QSGD3D12ImageNode::setMipmapFiltering(QSGTexture::Filtering filtering) -{ - if (m_material.mipmapFiltering() == filtering) - return; - - m_material.setMipmapFiltering(filtering); - markDirty(DirtyMaterial); -} - -QSGTexture::Filtering QSGD3D12ImageNode::mipmapFiltering() const -{ - return m_material.mipmapFiltering(); -} - -void QSGD3D12ImageNode::setRect(const QRectF &r) -{ - if (m_rect == r) - return; - - m_rect = r; - QSGImageNode::rebuildGeometry(&m_geometry, texture(), m_rect, m_sourceRect, m_texCoordMode); - markDirty(DirtyGeometry); -} - -QRectF QSGD3D12ImageNode::rect() const -{ - return m_rect; -} - -void QSGD3D12ImageNode::setSourceRect(const QRectF &r) -{ - if (m_sourceRect == r) - return; - - m_sourceRect = r; - QSGImageNode::rebuildGeometry(&m_geometry, texture(), m_rect, m_sourceRect, m_texCoordMode); - markDirty(DirtyGeometry); -} - -QRectF QSGD3D12ImageNode::sourceRect() const -{ - return m_sourceRect; -} - -void QSGD3D12ImageNode::setTexture(QSGTexture *texture) -{ - Q_ASSERT(texture); - - if (m_ownsTexture) - delete m_material.texture(); - - m_material.setTexture(texture); - QSGImageNode::rebuildGeometry(&m_geometry, texture, m_rect, m_sourceRect, m_texCoordMode); - - DirtyState dirty = DirtyMaterial; - const bool wasAtlas = m_isAtlasTexture; - m_isAtlasTexture = texture->isAtlasTexture(); - if (wasAtlas || m_isAtlasTexture) - dirty |= DirtyGeometry; - - markDirty(dirty); -} - -QSGTexture *QSGD3D12ImageNode::texture() const -{ - return m_material.texture(); -} - -void QSGD3D12ImageNode::setTextureCoordinatesTransform(TextureCoordinatesTransformMode mode) -{ - if (m_texCoordMode == mode) - return; - - m_texCoordMode = mode; - QSGImageNode::rebuildGeometry(&m_geometry, texture(), m_rect, m_sourceRect, m_texCoordMode); - markDirty(DirtyMaterial); -} - -QSGD3D12ImageNode::TextureCoordinatesTransformMode QSGD3D12ImageNode::textureCoordinatesTransform() const -{ - return m_texCoordMode; -} - -void QSGD3D12ImageNode::setOwnsTexture(bool owns) -{ - m_ownsTexture = owns; -} - -bool QSGD3D12ImageNode::ownsTexture() const -{ - return m_ownsTexture; -} - -QSGD3D12NinePatchNode::QSGD3D12NinePatchNode() - : m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4) -{ - m_geometry.setDrawingMode(QSGGeometry::DrawTriangleStrip); - setGeometry(&m_geometry); - setMaterial(&m_material); -} - -QSGD3D12NinePatchNode::~QSGD3D12NinePatchNode() -{ - delete m_material.texture(); -} - -void QSGD3D12NinePatchNode::setTexture(QSGTexture *texture) -{ - delete m_material.texture(); - m_material.setTexture(texture); -} - -void QSGD3D12NinePatchNode::setBounds(const QRectF &bounds) -{ - m_bounds = bounds; -} - -void QSGD3D12NinePatchNode::setDevicePixelRatio(qreal ratio) -{ - m_devicePixelRatio = ratio; -} - -void QSGD3D12NinePatchNode::setPadding(qreal left, qreal top, qreal right, qreal bottom) -{ - m_padding = QVector4D(left, top, right, bottom); -} - -void QSGD3D12NinePatchNode::update() -{ - QSGNinePatchNode::rebuildGeometry(m_material.texture(), &m_geometry, m_padding, m_bounds, m_devicePixelRatio); - markDirty(QSGNode::DirtyGeometry | QSGNode::DirtyMaterial); -} - -QT_END_NAMESPACE diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12publicnodes_p.h b/src/plugins/scenegraph/d3d12/qsgd3d12publicnodes_p.h deleted file mode 100644 index 6150083aaf..0000000000 --- a/src/plugins/scenegraph/d3d12/qsgd3d12publicnodes_p.h +++ /dev/null @@ -1,136 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#ifndef QSGD3D12PUBLICNODES_P_H -#define QSGD3D12PUBLICNODES_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include -#include -#include -#include "qsgd3d12builtinmaterials_p.h" - -QT_BEGIN_NAMESPACE - -class QSGD3D12RectangleNode : public QSGRectangleNode -{ -public: - QSGD3D12RectangleNode(); - - void setRect(const QRectF &rect) override; - QRectF rect() const override; - - void setColor(const QColor &color) override; - QColor color() const override; - -private: - QSGGeometry m_geometry; - QSGD3D12FlatColorMaterial m_material; -}; - -class QSGD3D12ImageNode : public QSGImageNode -{ -public: - QSGD3D12ImageNode(); - ~QSGD3D12ImageNode(); - - void setRect(const QRectF &rect) override; - QRectF rect() const override; - - void setSourceRect(const QRectF &r) override; - QRectF sourceRect() const override; - - void setTexture(QSGTexture *texture) override; - QSGTexture *texture() const override; - - void setFiltering(QSGTexture::Filtering filtering) override; - QSGTexture::Filtering filtering() const override; - - void setMipmapFiltering(QSGTexture::Filtering filtering) override; - QSGTexture::Filtering mipmapFiltering() const override; - - void setTextureCoordinatesTransform(TextureCoordinatesTransformMode mode) override; - TextureCoordinatesTransformMode textureCoordinatesTransform() const override; - - void setOwnsTexture(bool owns) override; - bool ownsTexture() const override; - -private: - QSGGeometry m_geometry; - QSGD3D12TextureMaterial m_material; - QRectF m_rect; - QRectF m_sourceRect; - TextureCoordinatesTransformMode m_texCoordMode; - uint m_isAtlasTexture : 1; - uint m_ownsTexture : 1; -}; - -class QSGD3D12NinePatchNode : public QSGNinePatchNode -{ -public: - QSGD3D12NinePatchNode(); - ~QSGD3D12NinePatchNode(); - - void setTexture(QSGTexture *texture) override; - void setBounds(const QRectF &bounds) override; - void setDevicePixelRatio(qreal ratio) override; - void setPadding(qreal left, qreal top, qreal right, qreal bottom) override; - void update() override; - -private: - QSGGeometry m_geometry; - QSGD3D12TextureMaterial m_material; - QRectF m_bounds; - qreal m_devicePixelRatio; - QVector4D m_padding; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12rendercontext.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12rendercontext.cpp deleted file mode 100644 index 48693207c6..0000000000 --- a/src/plugins/scenegraph/d3d12/qsgd3d12rendercontext.cpp +++ /dev/null @@ -1,169 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include "qsgd3d12rendercontext_p.h" -#include "qsgd3d12renderer_p.h" -#include "qsgd3d12texture_p.h" - -QT_BEGIN_NAMESPACE - -// NOTE: Avoid categorized logging. It is slow. - -#define DECLARE_DEBUG_VAR(variable) \ - static bool debug_ ## variable() \ - { static bool value = qgetenv("QSG_RENDERER_DEBUG").contains(QT_STRINGIFY(variable)); return value; } - -DECLARE_DEBUG_VAR(render) - -QSGD3D12RenderContext::QSGD3D12RenderContext(QSGContext *ctx) - : QSGRenderContext(ctx) -{ -} - -bool QSGD3D12RenderContext::isValid() const -{ - // The render thread sets an engine when it starts up and resets when it - // quits. The rc is initialized and functional between those two points, - // regardless of any calls to invalidate(). See setEngine(). - return m_engine != nullptr; -} - -void QSGD3D12RenderContext::initialize(const InitParams *) -{ - if (m_initialized) - return; - - m_initialized = true; - emit initialized(); -} - -void QSGD3D12RenderContext::invalidate() -{ - if (!m_initialized) - return; - - m_initialized = false; - - if (Q_UNLIKELY(debug_render())) - qDebug("rendercontext invalidate engine %p, %d/%d/%d", m_engine, - m_texturesToDelete.count(), m_textures.count(), m_fontEnginesToClean.count()); - - qDeleteAll(m_texturesToDelete); - m_texturesToDelete.clear(); - - qDeleteAll(m_textures); - m_textures.clear(); - - for (QSet::const_iterator it = m_fontEnginesToClean.constBegin(), - end = m_fontEnginesToClean.constEnd(); it != end; ++it) { - (*it)->clearGlyphCache(m_engine); - if (!(*it)->ref.deref()) - delete *it; - } - m_fontEnginesToClean.clear(); - - m_sg->renderContextInvalidated(this); - emit invalidated(); -} - -QSGTexture *QSGD3D12RenderContext::createTexture(const QImage &image, uint flags) const -{ - Q_ASSERT(m_engine); - QSGD3D12Texture *t = new QSGD3D12Texture(m_engine); - t->create(image, flags); - return t; -} - -QSGRenderer *QSGD3D12RenderContext::createRenderer() -{ - return new QSGD3D12Renderer(this); -} - -int QSGD3D12RenderContext::maxTextureSize() const -{ - return 16384; // D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION -} - -void QSGD3D12RenderContext::renderNextFrame(QSGRenderer *renderer, uint fbo) -{ - static_cast(renderer)->renderScene(fbo); -} - -void QSGD3D12RenderContext::setEngine(QSGD3D12Engine *engine) -{ - if (m_engine == engine) - return; - - m_engine = engine; - - if (m_engine) - initialize(nullptr); -} - -QSGRendererInterface::GraphicsApi QSGD3D12RenderContext::graphicsApi() const -{ - return Direct3D12; -} - -void *QSGD3D12RenderContext::getResource(QQuickWindow *window, Resource resource) const -{ - if (!m_engine) { - qWarning("getResource: No D3D12 engine available yet (window not exposed?)"); - return nullptr; - } - // window can be ignored since the rendercontext and engine are both per window - return m_engine->getResource(window, resource); -} - -QSGRendererInterface::ShaderType QSGD3D12RenderContext::shaderType() const -{ - return HLSL; -} - -QSGRendererInterface::ShaderCompilationTypes QSGD3D12RenderContext::shaderCompilationType() const -{ - return RuntimeCompilation | OfflineCompilation; -} - -QSGRendererInterface::ShaderSourceTypes QSGD3D12RenderContext::shaderSourceType() const -{ - return ShaderSourceString | ShaderSourceFile | ShaderByteCode; -} - -QT_END_NAMESPACE diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12rendercontext_p.h b/src/plugins/scenegraph/d3d12/qsgd3d12rendercontext_p.h deleted file mode 100644 index c555c0808e..0000000000 --- a/src/plugins/scenegraph/d3d12/qsgd3d12rendercontext_p.h +++ /dev/null @@ -1,90 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#ifndef QSGD3D12RENDERCONTEXT_P_H -#define QSGD3D12RENDERCONTEXT_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include -#include - -QT_BEGIN_NAMESPACE - -class QSGD3D12Engine; - -class QSGD3D12RenderContext : public QSGRenderContext, public QSGRendererInterface -{ -public: - QSGD3D12RenderContext(QSGContext *ctx); - bool isValid() const override; - void initialize(const InitParams *params) override; - void invalidate() override; - void renderNextFrame(QSGRenderer *renderer, uint fbo) override; - QSGTexture *createTexture(const QImage &image, uint flags) const override; - QSGRenderer *createRenderer() override; - int maxTextureSize() const override; - - void setEngine(QSGD3D12Engine *engine); - QSGD3D12Engine *engine() { return m_engine; } - - // QSGRendererInterface - GraphicsApi graphicsApi() const override; - void *getResource(QQuickWindow *window, Resource resource) const override; - ShaderType shaderType() const override; - ShaderCompilationTypes shaderCompilationType() const override; - ShaderSourceTypes shaderSourceType() const override; - -private: - QSGD3D12Engine *m_engine = nullptr; - bool m_initialized = false; -}; - -QT_END_NAMESPACE - -#endif // QSGD3D12RENDERCONTEXT_P_H diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12renderer.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12renderer.cpp deleted file mode 100644 index c38c616ae6..0000000000 --- a/src/plugins/scenegraph/d3d12/qsgd3d12renderer.cpp +++ /dev/null @@ -1,785 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include "qsgd3d12renderer_p.h" -#include "qsgd3d12rendercontext_p.h" -#include -#include - -#include "vs_stencilclip.hlslh" -#include "ps_stencilclip.hlslh" - -//#define I_LIKE_STENCIL - -QT_BEGIN_NAMESPACE - -#define QSGNODE_TRAVERSE(NODE) for (QSGNode *child = NODE->firstChild(); child; child = child->nextSibling()) - -// NOTE: Avoid categorized logging. It is slow. - -#define DECLARE_DEBUG_VAR(variable) \ - static bool debug_ ## variable() \ - { static bool value = qgetenv("QSG_RENDERER_DEBUG").contains(QT_STRINGIFY(variable)); return value; } - -DECLARE_DEBUG_VAR(build) -DECLARE_DEBUG_VAR(change) -DECLARE_DEBUG_VAR(render) - -class DummyUpdater : public QSGNodeUpdater -{ -public: - void updateState(QSGNode *) { }; -}; - -QSGD3D12Renderer::QSGD3D12Renderer(QSGRenderContext *context) - : QSGRenderer(context), - m_vboData(1024), - m_iboData(256), - m_cboData(4096), - m_renderList(16) -{ - setNodeUpdater(new DummyUpdater); -} - -QSGD3D12Renderer::~QSGD3D12Renderer() -{ - if (m_engine) { - m_engine->releaseBuffer(m_vertexBuf); - m_engine->releaseBuffer(m_indexBuf); - m_engine->releaseBuffer(m_constantBuf); - } -} - -void QSGD3D12Renderer::renderScene(GLuint fboId) -{ - m_renderTarget = fboId; - - struct DummyBindable : public QSGBindable { - void bind() const { } - } bindable; - - QSGRenderer::renderScene(bindable); // calls back render() -} - -// Search through the node set and remove nodes that are descendants of other -// nodes in the same set. -static QSet qsg_removeDescendants(const QSet &nodes, QSGRootNode *root) -{ - QSet result = nodes; - for (QSGNode *node : nodes) { - QSGNode *n = node; - while (n != root) { - if (n != node && result.contains(n)) { - result.remove(node); - break; - } - n = n->parent(); - } - } - return result; -} - -void QSGD3D12Renderer::updateMatrices(QSGNode *node, QSGTransformNode *xform) -{ - if (node->isSubtreeBlocked()) - return; - - if (node->type() == QSGNode::TransformNodeType) { - QSGTransformNode *tn = static_cast(node); - if (xform) - tn->setCombinedMatrix(xform->combinedMatrix() * tn->matrix()); - else - tn->setCombinedMatrix(tn->matrix()); - QSGNODE_TRAVERSE(node) - updateMatrices(child, tn); - } else { - if (node->type() == QSGNode::GeometryNodeType || node->type() == QSGNode::ClipNodeType) { - m_nodeDirtyMap[node] |= QSGD3D12MaterialRenderState::DirtyMatrix; - QSGBasicGeometryNode *gnode = static_cast(node); - const QMatrix4x4 *newMatrix = xform ? &xform->combinedMatrix() : nullptr; - // NB the newMatrix ptr is usually the same as before as it just - // references the transform node's own matrix. - gnode->setRendererMatrix(newMatrix); - } - QSGNODE_TRAVERSE(node) - updateMatrices(child, xform); - } -} - -void QSGD3D12Renderer::updateOpacities(QSGNode *node, float inheritedOpacity) -{ - if (node->isSubtreeBlocked()) - return; - - if (node->type() == QSGNode::OpacityNodeType) { - QSGOpacityNode *on = static_cast(node); - float combined = inheritedOpacity * on->opacity(); - on->setCombinedOpacity(combined); - QSGNODE_TRAVERSE(node) - updateOpacities(child, combined); - } else { - if (node->type() == QSGNode::GeometryNodeType) { - m_nodeDirtyMap[node] |= QSGD3D12MaterialRenderState::DirtyOpacity; - QSGGeometryNode *gn = static_cast(node); - gn->setInheritedOpacity(inheritedOpacity); - } - QSGNODE_TRAVERSE(node) - updateOpacities(child, inheritedOpacity); - } -} - -void QSGD3D12Renderer::buildRenderList(QSGNode *node, QSGClipNode *clip) -{ - if (node->isSubtreeBlocked()) - return; - - if (node->type() == QSGNode::GeometryNodeType || node->type() == QSGNode::ClipNodeType) { - QSGBasicGeometryNode *gn = static_cast(node); - QSGGeometry *g = gn->geometry(); - - Element e; - e.node = gn; - - if (g->vertexCount() > 0) { - e.vboOffset = m_vboData.size(); - const int vertexSize = g->sizeOfVertex() * g->vertexCount(); - m_vboData.resize(m_vboData.size() + vertexSize); - memcpy(m_vboData.data() + e.vboOffset, g->vertexData(), vertexSize); - } - - if (g->indexCount() > 0) { - e.iboOffset = m_iboData.size(); - e.iboStride = g->sizeOfIndex(); - const int indexSize = e.iboStride * g->indexCount(); - m_iboData.resize(m_iboData.size() + indexSize); - memcpy(m_iboData.data() + e.iboOffset, g->indexData(), indexSize); - } - - e.cboOffset = m_cboData.size(); - if (node->type() == QSGNode::GeometryNodeType) { - QSGD3D12Material *m = static_cast(static_cast(node)->activeMaterial()); - e.cboSize = m->constantBufferSize(); - } else { - // Stencil-based clipping needs a 4x4 matrix. - e.cboSize = QSGD3D12Engine::alignedConstantBufferSize(16 * sizeof(float)); - } - m_cboData.resize(m_cboData.size() + e.cboSize); - - m_renderList.add(e); - - gn->setRendererClipList(clip); - if (node->type() == QSGNode::ClipNodeType) - clip = static_cast(node); - } else if (node->type() == QSGNode::RenderNodeType) { - QSGRenderNode *rn = static_cast(node); - Element e; - e.node = rn; - m_renderList.add(e); - } - - QSGNODE_TRAVERSE(node) - buildRenderList(child, clip); -} - -void QSGD3D12Renderer::render() -{ - QSGD3D12RenderContext *rc = static_cast(context()); - m_engine = rc->engine(); - if (!m_layerRenderer) - m_engine->beginFrame(); - else - m_engine->beginLayer(); - - m_activeScissorRect = QRect(); - - if (m_rebuild) { - m_rebuild = false; - - m_dirtyTransformNodes.clear(); - m_dirtyTransformNodes.insert(rootNode()); - m_dirtyOpacityNodes.clear(); - m_dirtyOpacityNodes.insert(rootNode()); - - m_renderList.reset(); - m_vboData.reset(); - m_iboData.reset(); - m_cboData.reset(); - - buildRenderList(rootNode(), nullptr); - - if (!m_vertexBuf) - m_vertexBuf = m_engine->genBuffer(); - m_engine->resetBuffer(m_vertexBuf, m_vboData.data(), m_vboData.size()); - - if (!m_constantBuf) - m_constantBuf = m_engine->genBuffer(); - m_engine->resetBuffer(m_constantBuf, m_cboData.data(), m_cboData.size()); - - if (m_iboData.size()) { - if (!m_indexBuf) - m_indexBuf = m_engine->genBuffer(); - m_engine->resetBuffer(m_indexBuf, m_iboData.data(), m_iboData.size()); - } else if (m_indexBuf) { - m_engine->releaseBuffer(m_indexBuf); - m_indexBuf = 0; - } - - if (Q_UNLIKELY(debug_build())) { - qDebug("renderList: %d elements in total", m_renderList.size()); - for (int i = 0; i < m_renderList.size(); ++i) { - const Element &e = m_renderList.at(i); - qDebug() << " - " << e.vboOffset << e.iboOffset << e.cboOffset << e.cboSize << e.node; - } - } - } - - const QRect devRect = deviceRect(); - m_projectionChangedDueToDeviceSize = devRect != m_lastDeviceRect; - if (m_projectionChangedDueToDeviceSize) - m_lastDeviceRect = devRect; - - if (m_dirtyTransformNodes.size()) { - const QSet subTreeRoots = qsg_removeDescendants(m_dirtyTransformNodes, rootNode()); - for (QSGNode *node : subTreeRoots) { - // First find the parent transform so we have the accumulated - // matrix up until this point. - QSGTransformNode *xform = 0; - QSGNode *n = node; - if (n->type() == QSGNode::TransformNodeType) - n = node->parent(); - while (n != rootNode() && n->type() != QSGNode::TransformNodeType) - n = n->parent(); - if (n != rootNode()) - xform = static_cast(n); - - // Then update in the subtree - updateMatrices(node, xform); - } - } - - if (m_dirtyOpacityNodes.size()) { - const QSet subTreeRoots = qsg_removeDescendants(m_dirtyOpacityNodes, rootNode()); - for (QSGNode *node : subTreeRoots) { - float opacity = 1.0f; - QSGNode *n = node; - if (n->type() == QSGNode::OpacityNodeType) - n = node->parent(); - while (n != rootNode() && n->type() != QSGNode::OpacityNodeType) - n = n->parent(); - if (n != rootNode()) - opacity = static_cast(n)->combinedOpacity(); - - updateOpacities(node, opacity); - } - m_dirtyOpaqueElements = true; - } - - if (m_dirtyOpaqueElements) { - m_dirtyOpaqueElements = false; - m_opaqueElements.clear(); - m_opaqueElements.resize(m_renderList.size()); - for (int i = 0; i < m_renderList.size(); ++i) { - const Element &e = m_renderList.at(i); - if (e.node->type() == QSGNode::GeometryNodeType) { - const QSGGeometryNode *gn = static_cast(e.node); - if (gn->inheritedOpacity() > 0.999f && ((gn->activeMaterial()->flags() & QSGMaterial::Blending) == 0)) - m_opaqueElements.setBit(i); - } - // QSGRenderNodes are always treated as non-opaque - } - } - - // Build pipeline state and draw calls. - renderElements(); - - m_dirtyTransformNodes.clear(); - m_dirtyOpacityNodes.clear(); - m_dirtyOpaqueElements = false; - m_nodeDirtyMap.clear(); - - // Finalize buffers and execute commands. - if (!m_layerRenderer) - m_engine->endFrame(); - else - m_engine->endLayer(); -} - -void QSGD3D12Renderer::nodeChanged(QSGNode *node, QSGNode::DirtyState state) -{ - // note that with DirtyNodeRemoved the window and all the graphics engine may already be gone - - if (Q_UNLIKELY(debug_change())) { - QDebug debug = qDebug(); - debug << "dirty:"; - if (state & QSGNode::DirtyGeometry) - debug << "Geometry"; - if (state & QSGNode::DirtyMaterial) - debug << "Material"; - if (state & QSGNode::DirtyMatrix) - debug << "Matrix"; - if (state & QSGNode::DirtyNodeAdded) - debug << "Added"; - if (state & QSGNode::DirtyNodeRemoved) - debug << "Removed"; - if (state & QSGNode::DirtyOpacity) - debug << "Opacity"; - if (state & QSGNode::DirtySubtreeBlocked) - debug << "SubtreeBlocked"; - if (state & QSGNode::DirtyForceUpdate) - debug << "ForceUpdate"; - - // when removed, some parts of the node could already have been destroyed - // so don't debug it out. - if (state & QSGNode::DirtyNodeRemoved) - debug << (void *) node << node->type(); - else - debug << node; - } - - if (state & (QSGNode::DirtyNodeAdded - | QSGNode::DirtyNodeRemoved - | QSGNode::DirtySubtreeBlocked - | QSGNode::DirtyGeometry - | QSGNode::DirtyForceUpdate)) - m_rebuild = true; - - if (state & QSGNode::DirtyMatrix) - m_dirtyTransformNodes << node; - - if (state & QSGNode::DirtyOpacity) - m_dirtyOpacityNodes << node; - - if (state & QSGNode::DirtyMaterial) - m_dirtyOpaqueElements = true; - - QSGRenderer::nodeChanged(node, state); -} - -void QSGD3D12Renderer::renderElements() -{ - m_engine->queueSetRenderTarget(m_renderTarget); - m_engine->queueViewport(viewportRect()); - m_engine->queueClearRenderTarget(clearColor()); - m_engine->queueClearDepthStencil(1, 0, QSGD3D12Engine::ClearDepth | QSGD3D12Engine::ClearStencil); - - m_pipelineState.blend = m_freshPipelineState.blend = QSGD3D12PipelineState::BlendNone; - m_pipelineState.depthEnable = m_freshPipelineState.depthEnable = true; - m_pipelineState.depthWrite = m_freshPipelineState.depthWrite = true; - - // First do opaque... - // The algorithm is quite simple. We traverse the list back-to-front, and - // for every item we start a second traversal and draw all elements which - // have identical material. Then we clear the bit for this in the rendered - // list so we don't draw it again when we come to that index. - QBitArray rendered = m_opaqueElements; - for (int i = m_renderList.size() - 1; i >= 0; --i) { - if (rendered.testBit(i)) { - renderElement(i); - for (int j = i - 1; j >= 0; --j) { - if (rendered.testBit(j)) { - const QSGGeometryNode *gni = static_cast(m_renderList.at(i).node); - const QSGGeometryNode *gnj = static_cast(m_renderList.at(j).node); - if (gni->clipList() == gnj->clipList() - && gni->inheritedOpacity() == gnj->inheritedOpacity() - && gni->geometry()->drawingMode() == gnj->geometry()->drawingMode() - && gni->geometry()->attributes() == gnj->geometry()->attributes()) { - const QSGMaterial *ami = gni->activeMaterial(); - const QSGMaterial *amj = gnj->activeMaterial(); - if (ami->type() == amj->type() - && ami->flags() == amj->flags() - && ami->compare(amj) == 0) { - renderElement(j); - rendered.clearBit(j); - } - } - } - } - } - } - - m_pipelineState.blend = m_freshPipelineState.blend = QSGD3D12PipelineState::BlendPremul; - m_pipelineState.depthWrite = m_freshPipelineState.depthWrite = false; - - // ...then the alpha ones - for (int i = 0; i < m_renderList.size(); ++i) { - if ((m_renderList.at(i).node->type() == QSGNode::GeometryNodeType && !m_opaqueElements.testBit(i)) - || m_renderList.at(i).node->type() == QSGNode::RenderNodeType) - renderElement(i); - } -} - -struct RenderNodeState : public QSGRenderNode::RenderState -{ - const QMatrix4x4 *projectionMatrix() const override { return m_projectionMatrix; } - QRect scissorRect() const override { return m_scissorRect; } - bool scissorEnabled() const override { return m_scissorEnabled; } - int stencilValue() const override { return m_stencilValue; } - bool stencilEnabled() const override { return m_stencilEnabled; } - const QRegion *clipRegion() const override { return nullptr; } - - const QMatrix4x4 *m_projectionMatrix; - QRect m_scissorRect; - bool m_scissorEnabled; - int m_stencilValue; - bool m_stencilEnabled; -}; - -void QSGD3D12Renderer::renderElement(int elementIndex) -{ - Element &e = m_renderList.at(elementIndex); - Q_ASSERT(e.node->type() == QSGNode::GeometryNodeType || e.node->type() == QSGNode::RenderNodeType); - - if (e.node->type() == QSGNode::RenderNodeType) { - renderRenderNode(static_cast(e.node), elementIndex); - return; - } - - if (e.vboOffset < 0) - return; - - Q_ASSERT(e.cboOffset >= 0); - - const QSGGeometryNode *gn = static_cast(e.node); - if (Q_UNLIKELY(debug_render())) - qDebug() << "renderElement:" << elementIndex << gn << e.vboOffset << e.iboOffset << gn->inheritedOpacity() << gn->clipList(); - - if (gn->inheritedOpacity() < 0.001f) // pretty much invisible, don't draw it - return; - - // Update the QSGRenderer members which the materials will access. - m_current_projection_matrix = projectionMatrix(); - const float scale = 1.0 / m_renderList.size(); - m_current_projection_matrix(2, 2) = scale; - m_current_projection_matrix(2, 3) = 1.0f - (elementIndex + 1) * scale; - m_current_model_view_matrix = gn->matrix() ? *gn->matrix() : QMatrix4x4(); - m_current_determinant = m_current_model_view_matrix.determinant(); - m_current_opacity = gn->inheritedOpacity(); - - const QSGGeometry *g = gn->geometry(); - QSGD3D12Material *m = static_cast(gn->activeMaterial()); - - if (m->type() != m_lastMaterialType) { - m_pipelineState = m_freshPipelineState; - m->preparePipeline(&m_pipelineState); - } - - QSGD3D12MaterialRenderState::DirtyStates dirtyState = m_nodeDirtyMap.value(e.node); - - // After a rebuild everything in the cbuffer has to be updated. - if (!e.cboPrepared) { - e.cboPrepared = true; - dirtyState = QSGD3D12MaterialRenderState::DirtyAll; - } - - // DirtyMatrix does not include projection matrix changes that can arise - // due to changing the render target's size (and there is no rebuild). - // Accommodate for this. - if (m_projectionChangedDueToDeviceSize) - dirtyState |= QSGD3D12MaterialRenderState::DirtyMatrix; - - quint8 *cboPtr = nullptr; - if (e.cboSize > 0) - cboPtr = m_cboData.data() + e.cboOffset; - - if (Q_UNLIKELY(debug_render())) - qDebug() << "dirty state for" << e.node << "is" << dirtyState; - - QSGD3D12Material::ExtraState extraState; - QSGD3D12Material::UpdateResults updRes = m->updatePipeline(state(dirtyState), - &m_pipelineState, - &extraState, - cboPtr); - - if (updRes.testFlag(QSGD3D12Material::UpdatedConstantBuffer)) - m_engine->markBufferDirty(m_constantBuf, e.cboOffset, e.cboSize); - - if (updRes.testFlag(QSGD3D12Material::UpdatedBlendFactor)) - m_engine->queueSetBlendFactor(extraState.blendFactor); - - setInputLayout(g, &m_pipelineState); - - m_lastMaterialType = m->type(); - - setupClipping(gn->clipList(), elementIndex); - - // ### Lines and points with sizes other than 1 have to be implemented in some other way. Just ignore for now. - if (g->drawingMode() == QSGGeometry::DrawLineStrip || g->drawingMode() == QSGGeometry::DrawLines) { - if (g->lineWidth() != 1.0f) - qWarning("QSGD3D12Renderer: Line widths other than 1 are not supported by this renderer"); - } else if (g->drawingMode() == QSGGeometry::DrawPoints) { - if (g->lineWidth() != 1.0f) - qWarning("QSGD3D12Renderer: Point sprites are not supported by this renderer"); - } - - m_engine->finalizePipeline(m_pipelineState); - - queueDrawCall(g, e); -} - -void QSGD3D12Renderer::setInputLayout(const QSGGeometry *g, QSGD3D12PipelineState *pipelineState) -{ - pipelineState->inputElementCount = g->attributeCount(); - const QSGGeometry::Attribute *attrs = g->attributes(); - quint32 offset = 0; - for (int i = 0; i < g->attributeCount(); ++i) { - QSGD3D12InputElement &ie(pipelineState->inputElements[i]); - static const char *semanticNames[] = { "UNKNOWN", "POSITION", "COLOR", "TEXCOORD", "TEXCOORD", "TEXCOORD" }; - static const int semanticIndices[] = { 0, 0, 0, 0, 1, 2 }; - const int semantic = attrs[i].attributeType; - Q_ASSERT(semantic >= 1 && semantic < _countof(semanticNames)); - const int tupleSize = attrs[i].tupleSize; - ie.semanticName = semanticNames[semantic]; - ie.semanticIndex = semanticIndices[semantic]; - ie.offset = offset; - int bytesPerTuple = 0; - ie.format = QSGD3D12Engine::toDXGIFormat(QSGGeometry::Type(attrs[i].type), tupleSize, &bytesPerTuple); - if (ie.format == FmtUnknown) - qFatal("QSGD3D12Renderer: unsupported tuple size for attribute type 0x%x", attrs[i].type); - offset += bytesPerTuple; - // There is one buffer with interleaved data so the slot is always 0. - ie.slot = 0; - } -} - -void QSGD3D12Renderer::queueDrawCall(const QSGGeometry *g, const QSGD3D12Renderer::Element &e) -{ - QSGD3D12Engine::DrawParams dp; - dp.mode = QSGGeometry::DrawingMode(g->drawingMode()); - dp.vertexBuf = m_vertexBuf; - dp.constantBuf = m_constantBuf; - dp.vboOffset = e.vboOffset; - dp.vboSize = g->vertexCount() * g->sizeOfVertex(); - dp.vboStride = g->sizeOfVertex(); - dp.cboOffset = e.cboOffset; - - if (e.iboOffset >= 0) { - const QSGGeometry::Type indexType = QSGGeometry::Type(g->indexType()); - const QSGD3D12Format indexFormat = QSGD3D12Engine::toDXGIFormat(indexType); - if (indexFormat == FmtUnknown) - qFatal("QSGD3D12Renderer: unsupported index type 0x%x", indexType); - dp.count = g->indexCount(); - dp.indexBuf = m_indexBuf; - dp.startIndexIndex = e.iboOffset / e.iboStride; - dp.indexFormat = indexFormat; - } else { - dp.count = g->vertexCount(); - } - - m_engine->queueDraw(dp); -} - -void QSGD3D12Renderer::setupClipping(const QSGClipNode *clip, int elementIndex) -{ - const QRect devRect = deviceRect(); - QRect scissorRect; - int clipTypes = 0; - quint32 stencilValue = 0; - - while (clip) { - QMatrix4x4 m = projectionMatrix(); - if (clip->matrix()) - m *= *clip->matrix(); - -#ifndef I_LIKE_STENCIL - const bool isRectangleWithNoPerspective = clip->isRectangular() - && qFuzzyIsNull(m(3, 0)) && qFuzzyIsNull(m(3, 1)); - const bool noRotate = qFuzzyIsNull(m(0, 1)) && qFuzzyIsNull(m(1, 0)); - const bool isRotate90 = qFuzzyIsNull(m(0, 0)) && qFuzzyIsNull(m(1, 1)); - - if (isRectangleWithNoPerspective && (noRotate || isRotate90)) { - QRectF bbox = clip->clipRect(); - float invW = 1.0f / m(3, 3); - float fx1, fy1, fx2, fy2; - if (noRotate) { - fx1 = (bbox.left() * m(0, 0) + m(0, 3)) * invW; - fy1 = (bbox.bottom() * m(1, 1) + m(1, 3)) * invW; - fx2 = (bbox.right() * m(0, 0) + m(0, 3)) * invW; - fy2 = (bbox.top() * m(1, 1) + m(1, 3)) * invW; - } else { - Q_ASSERT(isRotate90); - fx1 = (bbox.bottom() * m(0, 1) + m(0, 3)) * invW; - fy1 = (bbox.left() * m(1, 0) + m(1, 3)) * invW; - fx2 = (bbox.top() * m(0, 1) + m(0, 3)) * invW; - fy2 = (bbox.right() * m(1, 0) + m(1, 3)) * invW; - } - - if (fx1 > fx2) - qSwap(fx1, fx2); - if (fy1 > fy2) - qSwap(fy1, fy2); - - int ix1 = qRound((fx1 + 1) * devRect.width() * 0.5f); - int iy1 = qRound((fy1 + 1) * devRect.height() * 0.5f); - int ix2 = qRound((fx2 + 1) * devRect.width() * 0.5f); - int iy2 = qRound((fy2 + 1) * devRect.height() * 0.5f); - - if (!(clipTypes & ClipScissor)) { - scissorRect = QRect(ix1, devRect.height() - iy2, ix2 - ix1, iy2 - iy1); - clipTypes |= ClipScissor; - } else { - scissorRect &= QRect(ix1, devRect.height() - iy2, ix2 - ix1, iy2 - iy1); - } - } else -#endif - { - clipTypes |= ClipStencil; - renderStencilClip(clip, elementIndex, m, stencilValue); - } - - clip = clip->clipList(); - } - - setScissor((clipTypes & ClipScissor) ? scissorRect : viewportRect()); - - if (clipTypes & ClipStencil) { - m_pipelineState.stencilEnable = true; - m_engine->queueSetStencilRef(stencilValue); - m_currentStencilValue = stencilValue; - } else { - m_pipelineState.stencilEnable = false; - m_currentStencilValue = 0; - } - - m_currentClipTypes = clipTypes; -} - -void QSGD3D12Renderer::setScissor(const QRect &r) -{ - if (m_activeScissorRect == r) - return; - - m_activeScissorRect = r; - m_engine->queueScissor(r); -} - -void QSGD3D12Renderer::renderStencilClip(const QSGClipNode *clip, int elementIndex, - const QMatrix4x4 &m, quint32 &stencilValue) -{ - QSGD3D12PipelineState sps; - sps.shaders.vs = g_VS_StencilClip; - sps.shaders.vsSize = sizeof(g_VS_StencilClip); - sps.shaders.ps = g_PS_StencilClip; - sps.shaders.psSize = sizeof(g_PS_StencilClip); - - m_engine->queueClearDepthStencil(1, 0, QSGD3D12Engine::ClearStencil); - sps.stencilEnable = true; - sps.colorWrite = false; - sps.depthWrite = false; - - sps.stencilFunc = QSGD3D12PipelineState::CompareEqual; - sps.stencilFailOp = QSGD3D12PipelineState::StencilKeep; - sps.stencilDepthFailOp = QSGD3D12PipelineState::StencilKeep; - sps.stencilPassOp = QSGD3D12PipelineState::StencilIncr; - - m_engine->queueSetStencilRef(stencilValue); - - int clipIndex = elementIndex; - while (m_renderList.at(--clipIndex).node != clip) { - Q_ASSERT(clipIndex >= 0); - } - const Element &ce = m_renderList.at(clipIndex); - Q_ASSERT(ce.node == clip); - - const QSGGeometry *g = clip->geometry(); - Q_ASSERT(g->attributeCount() == 1); - Q_ASSERT(g->attributes()[0].tupleSize == 2); - Q_ASSERT(g->attributes()[0].type == QSGGeometry::FloatType); - - setInputLayout(g, &sps); - m_engine->finalizePipeline(sps); - - Q_ASSERT(ce.cboSize > 0); - quint8 *p = m_cboData.data() + ce.cboOffset; - memcpy(p, m.constData(), 16 * sizeof(float)); - m_engine->markBufferDirty(m_constantBuf, ce.cboOffset, ce.cboSize); - - queueDrawCall(g, ce); - - ++stencilValue; -} - -void QSGD3D12Renderer::renderRenderNode(QSGRenderNode *node, int elementIndex) -{ - QSGRenderNodePrivate *rd = QSGRenderNodePrivate::get(node); - RenderNodeState state; - - setupClipping(rd->m_clip_list, elementIndex); - - QMatrix4x4 pm = projectionMatrix(); - state.m_projectionMatrix = ± - state.m_scissorEnabled = m_currentClipTypes & ClipScissor; - state.m_stencilEnabled = m_currentClipTypes & ClipStencil; - state.m_scissorRect = m_activeScissorRect; - state.m_stencilValue = m_currentStencilValue; - - // ### rendernodes do not have the QSGBasicGeometryNode infrastructure - // for storing combined matrices, opacity and such, but perhaps they should. - QSGNode *xform = node->parent(); - QSGNode *root = rootNode(); - QMatrix4x4 modelview; - while (xform != root) { - if (xform->type() == QSGNode::TransformNodeType) { - modelview *= static_cast(xform)->combinedMatrix(); - break; - } - xform = xform->parent(); - } - rd->m_matrix = &modelview; - - QSGNode *opacity = node->parent(); - rd->m_opacity = 1.0; - while (opacity != rootNode()) { - if (opacity->type() == QSGNode::OpacityNodeType) { - rd->m_opacity = static_cast(opacity)->combinedOpacity(); - break; - } - opacity = opacity->parent(); - } - - node->render(&state); - - m_engine->invalidateCachedFrameState(); - // For simplicity, reset viewport, scissor, blend factor, stencil ref when - // any of them got changed. This will likely be rare so skip these otherwise. - // Render target, pipeline state, draw call related stuff will be reset always. - const bool restoreMinimal = node->changedStates() == 0; - m_engine->restoreFrameState(restoreMinimal); -} - -QT_END_NAMESPACE diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12renderer_p.h b/src/plugins/scenegraph/d3d12/qsgd3d12renderer_p.h deleted file mode 100644 index df30a49f0d..0000000000 --- a/src/plugins/scenegraph/d3d12/qsgd3d12renderer_p.h +++ /dev/null @@ -1,137 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#ifndef QSGD3D12RENDERER_P_H -#define QSGD3D12RENDERER_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include -#include -#include -#include "qsgd3d12engine_p.h" -#include "qsgd3d12material_p.h" - -QT_BEGIN_NAMESPACE - -class QSGRenderNode; - -class QSGD3D12Renderer : public QSGRenderer -{ -public: - QSGD3D12Renderer(QSGRenderContext *context); - ~QSGD3D12Renderer(); - - void renderScene(GLuint fboId) override; - void render() override; - void nodeChanged(QSGNode *node, QSGNode::DirtyState state) override; - - void turnToLayerRenderer() { m_layerRenderer = true; } - -private: - void updateMatrices(QSGNode *node, QSGTransformNode *xform); - void updateOpacities(QSGNode *node, float inheritedOpacity); - void buildRenderList(QSGNode *node, QSGClipNode *clip); - void renderElements(); - void renderElement(int elementIndex); - void setInputLayout(const QSGGeometry *g, QSGD3D12PipelineState *pipelineState); - void setupClipping(const QSGClipNode *clip, int elementIndex); - void setScissor(const QRect &r); - void renderStencilClip(const QSGClipNode *clip, int elementIndex, const QMatrix4x4 &m, quint32 &stencilValue); - void renderRenderNode(QSGRenderNode *node, int elementIndex); - - struct Element { - QSGNode *node = nullptr; - qint32 vboOffset = -1; - qint32 iboOffset = -1; - quint32 iboStride = 0; - qint32 cboOffset = -1; - quint32 cboSize = 0; - bool cboPrepared = false; - }; - - void queueDrawCall(const QSGGeometry *g, const Element &e); - - bool m_layerRenderer = false; - QSet m_dirtyTransformNodes; - QSet m_dirtyOpacityNodes; - QBitArray m_opaqueElements; - bool m_rebuild = true; - bool m_dirtyOpaqueElements = true; - QDataBuffer m_vboData; - QDataBuffer m_iboData; - QDataBuffer m_cboData; - QDataBuffer m_renderList; - uint m_vertexBuf = 0; - uint m_indexBuf = 0; - uint m_constantBuf = 0; - QSGD3D12Engine *m_engine = nullptr; - - QSGMaterialType *m_lastMaterialType = nullptr; - QSGD3D12PipelineState m_pipelineState; - QSGD3D12PipelineState m_freshPipelineState; - - typedef QHash NodeDirtyMap; - NodeDirtyMap m_nodeDirtyMap; - - QRect m_activeScissorRect; - QRect m_lastDeviceRect; - bool m_projectionChangedDueToDeviceSize; - - uint m_renderTarget = 0; - quint32 m_currentStencilValue; - enum ClipType { - ClipScissor = 0x1, - ClipStencil = 0x2 - }; - int m_currentClipTypes; -}; - -QT_END_NAMESPACE - -#endif // QSGD3D12RENDERER_P_H diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12renderloop.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12renderloop.cpp deleted file mode 100644 index 79ffee7689..0000000000 --- a/src/plugins/scenegraph/d3d12/qsgd3d12renderloop.cpp +++ /dev/null @@ -1,548 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include "qsgd3d12renderloop_p.h" -#include "qsgd3d12engine_p.h" -#include "qsgd3d12context_p.h" -#include "qsgd3d12rendercontext_p.h" -#include "qsgd3d12shadereffectnode_p.h" -#include -#include -#include -#include -#include -#include - -#include - -QT_BEGIN_NAMESPACE - -// NOTE: Avoid categorized logging. It is slow. - -#define DECLARE_DEBUG_VAR(variable) \ - static bool debug_ ## variable() \ - { static bool value = qgetenv("QSG_RENDERER_DEBUG").contains(QT_STRINGIFY(variable)); return value; } - -DECLARE_DEBUG_VAR(loop) -DECLARE_DEBUG_VAR(time) - - -// This render loop operates on the gui (main) thread. -// Conceptually it matches the OpenGL 'windows' render loop. - -static inline int qsgrl_animation_interval() -{ - const qreal refreshRate = QGuiApplication::primaryScreen() ? QGuiApplication::primaryScreen()->refreshRate() : 0; - return refreshRate < 1 ? 16 : int(1000 / refreshRate); -} - -QSGD3D12RenderLoop::QSGD3D12RenderLoop() -{ - if (Q_UNLIKELY(debug_loop())) - qDebug("new d3d12 render loop"); - - sg = new QSGD3D12Context; - - m_anims = sg->createAnimationDriver(this); - connect(m_anims, &QAnimationDriver::started, this, &QSGD3D12RenderLoop::onAnimationStarted); - connect(m_anims, &QAnimationDriver::stopped, this, &QSGD3D12RenderLoop::onAnimationStopped); - m_anims->install(); - - m_vsyncDelta = qsgrl_animation_interval(); -} - -QSGD3D12RenderLoop::~QSGD3D12RenderLoop() -{ - delete sg; -} - -void QSGD3D12RenderLoop::show(QQuickWindow *window) -{ - if (Q_UNLIKELY(debug_loop())) - qDebug() << "show" << window; -} - -void QSGD3D12RenderLoop::hide(QQuickWindow *window) -{ - if (Q_UNLIKELY(debug_loop())) - qDebug() << "hide" << window; -} - -void QSGD3D12RenderLoop::resize(QQuickWindow *window) -{ - if (!m_windows.contains(window) || window->size().isEmpty()) - return; - - if (Q_UNLIKELY(debug_loop())) - qDebug() << "resize" << window; - - const WindowData &data(m_windows[window]); - - if (!data.exposed) - return; - - if (data.engine) - data.engine->setWindowSize(window->size(), window->effectiveDevicePixelRatio()); -} - -void QSGD3D12RenderLoop::windowDestroyed(QQuickWindow *window) -{ - if (Q_UNLIKELY(debug_loop())) - qDebug() << "window destroyed" << window; - - if (!m_windows.contains(window)) - return; - - QQuickWindowPrivate *wd = QQuickWindowPrivate::get(window); - wd->fireAboutToStop(); - - WindowData &data(m_windows[window]); - QSGD3D12Engine *engine = data.engine; - QSGD3D12RenderContext *rc = data.rc; - m_windows.remove(window); - - // QSGNode destruction may release graphics resources in use so wait first. - engine->waitGPU(); - - // Bye bye nodes... - wd->cleanupNodesOnShutdown(); - - QSGD3D12ShaderEffectNode::cleanupMaterialTypeCache(); - - rc->invalidate(); - - delete rc; - delete engine; - - wd->animationController.reset(); -} - -void QSGD3D12RenderLoop::exposeWindow(QQuickWindow *window) -{ - WindowData data; - data.exposed = true; - data.engine = new QSGD3D12Engine; - data.rc = static_cast(QQuickWindowPrivate::get(window)->context); - data.rc->setEngine(data.engine); - m_windows[window] = data; - - const int samples = window->format().samples(); - const bool alpha = window->format().alphaBufferSize() > 0; - const qreal dpr = window->effectiveDevicePixelRatio(); - - if (Q_UNLIKELY(debug_loop())) - qDebug() << "initializing D3D12 engine" << window << window->size() << dpr << samples << alpha; - - data.engine->attachToWindow(window->winId(), window->size(), dpr, samples, alpha); -} - -void QSGD3D12RenderLoop::obscureWindow(QQuickWindow *window) -{ - m_windows[window].exposed = false; - QQuickWindowPrivate *wd = QQuickWindowPrivate::get(window); - wd->fireAboutToStop(); -} - -void QSGD3D12RenderLoop::exposureChanged(QQuickWindow *window) -{ - if (Q_UNLIKELY(debug_loop())) - qDebug() << "exposure changed" << window << window->isExposed(); - - if (window->isExposed()) { - if (!m_windows.contains(window)) - exposeWindow(window); - - // Stop non-visual animation timer as we now have a window rendering. - if (m_animationTimer && somethingVisible()) { - killTimer(m_animationTimer); - m_animationTimer = 0; - } - // If we have a pending timer and we get an expose, we need to stop it. - // Otherwise we get two frames and two animation ticks in the same time interval. - if (m_updateTimer) { - killTimer(m_updateTimer); - m_updateTimer = 0; - } - - WindowData &data(m_windows[window]); - data.exposed = true; - data.updatePending = true; - - render(); - - } else if (m_windows.contains(window)) { - obscureWindow(window); - - // Potentially start the non-visual animation timer if nobody is rendering. - if (m_anims->isRunning() && !somethingVisible() && !m_animationTimer) - m_animationTimer = startTimer(m_vsyncDelta); - } -} - -QImage QSGD3D12RenderLoop::grab(QQuickWindow *window) -{ - const bool tempExpose = !m_windows.contains(window); - if (tempExpose) - exposeWindow(window); - - m_windows[window].grabOnly = true; - - renderWindow(window); - - QImage grabbed = m_grabContent; - m_grabContent = QImage(); - - if (tempExpose) - obscureWindow(window); - - return grabbed; -} - -bool QSGD3D12RenderLoop::somethingVisible() const -{ - for (auto it = m_windows.constBegin(), itEnd = m_windows.constEnd(); it != itEnd; ++it) { - if (it.key()->isVisible() && it.key()->isExposed()) - return true; - } - return false; -} - -void QSGD3D12RenderLoop::maybePostUpdateTimer() -{ - if (!m_updateTimer) { - if (Q_UNLIKELY(debug_loop())) - qDebug("starting update timer"); - m_updateTimer = startTimer(m_vsyncDelta / 3); - } -} - -void QSGD3D12RenderLoop::update(QQuickWindow *window) -{ - maybeUpdate(window); -} - -void QSGD3D12RenderLoop::maybeUpdate(QQuickWindow *window) -{ - if (!m_windows.contains(window) || !somethingVisible()) - return; - - m_windows[window].updatePending = true; - maybePostUpdateTimer(); -} - -QAnimationDriver *QSGD3D12RenderLoop::animationDriver() const -{ - return m_anims; -} - -QSGContext *QSGD3D12RenderLoop::sceneGraphContext() const -{ - return sg; -} - -QSGRenderContext *QSGD3D12RenderLoop::createRenderContext(QSGContext *) const -{ - // The rendercontext and engine are per-window, like with the threaded - // loop, but unlike the non-threaded OpenGL variants. - return sg->createRenderContext(); -} - -void QSGD3D12RenderLoop::releaseResources(QQuickWindow *window) -{ - if (Q_UNLIKELY(debug_loop())) - qDebug() << "releaseResources" << window; -} - -void QSGD3D12RenderLoop::postJob(QQuickWindow *window, QRunnable *job) -{ - Q_UNUSED(window); - Q_ASSERT(job); - Q_ASSERT(window); - job->run(); - delete job; -} - -QSurface::SurfaceType QSGD3D12RenderLoop::windowSurfaceType() const -{ - return QSurface::OpenGLSurface; -} - -bool QSGD3D12RenderLoop::interleaveIncubation() const -{ - return m_anims->isRunning() && somethingVisible(); -} - -void QSGD3D12RenderLoop::onAnimationStarted() -{ - if (!somethingVisible()) { - if (!m_animationTimer) { - if (Q_UNLIKELY(debug_loop())) - qDebug("starting non-visual animation timer"); - m_animationTimer = startTimer(m_vsyncDelta); - } - } else { - maybePostUpdateTimer(); - } -} - -void QSGD3D12RenderLoop::onAnimationStopped() -{ - if (m_animationTimer) { - if (Q_UNLIKELY(debug_loop())) - qDebug("stopping non-visual animation timer"); - killTimer(m_animationTimer); - m_animationTimer = 0; - } -} - -bool QSGD3D12RenderLoop::event(QEvent *event) -{ - switch (event->type()) { - case QEvent::Timer: - { - QTimerEvent *te = static_cast(event); - if (te->timerId() == m_animationTimer) { - if (Q_UNLIKELY(debug_loop())) - qDebug("animation tick while no windows exposed"); - m_anims->advance(); - } else if (te->timerId() == m_updateTimer) { - if (Q_UNLIKELY(debug_loop())) - qDebug("update timeout - rendering"); - killTimer(m_updateTimer); - m_updateTimer = 0; - render(); - } - return true; - } - default: - break; - } - - return QObject::event(event); -} - -void QSGD3D12RenderLoop::render() -{ - bool rendered = false; - for (auto it = m_windows.begin(), itEnd = m_windows.end(); it != itEnd; ++it) { - if (it->updatePending) { - it->updatePending = false; - renderWindow(it.key()); - rendered = true; - } - } - - if (!rendered) { - if (Q_UNLIKELY(debug_loop())) - qDebug("render - no changes, sleep"); - QThread::msleep(m_vsyncDelta); - } - - if (m_anims->isRunning()) { - if (Q_UNLIKELY(debug_loop())) - qDebug("render - advancing animations"); - - m_anims->advance(); - - // It is not given that animations triggered another maybeUpdate() - // and thus another render pass, so to keep things running, - // make sure there is another frame pending. - maybePostUpdateTimer(); - - emit timeToIncubate(); - } -} - -void QSGD3D12RenderLoop::renderWindow(QQuickWindow *window) -{ - if (Q_UNLIKELY(debug_loop())) - qDebug() << "renderWindow" << window; - - QQuickWindowPrivate *wd = QQuickWindowPrivate::get(window); - if (!m_windows.contains(window) || !window->geometry().isValid()) - return; - - WindowData &data(m_windows[window]); - if (!data.exposed) { // not the same as window->isExposed(), when grabbing invisible windows for instance - if (Q_UNLIKELY(debug_loop())) - qDebug("renderWindow - not exposed, abort"); - return; - } - - Q_TRACE_SCOPE(QSG_renderWindow); - - if (!data.grabOnly) - wd->flushFrameSynchronousEvents(); - - QElapsedTimer renderTimer; - qint64 renderTime = 0, syncTime = 0, polishTime = 0; - const bool profileFrames = debug_time(); - if (profileFrames) - renderTimer.start(); - Q_QUICK_SG_PROFILE_START(QQuickProfiler::SceneGraphPolishFrame); - Q_TRACE(QSG_polishItems_entry); - - wd->polishItems(); - - if (profileFrames) - polishTime = renderTimer.nsecsElapsed(); - Q_TRACE(QSG_polishItems_exit); - Q_QUICK_SG_PROFILE_SWITCH(QQuickProfiler::SceneGraphPolishFrame, - QQuickProfiler::SceneGraphRenderLoopFrame, - QQuickProfiler::SceneGraphPolishPolish); - Q_TRACE(QSG_sync_entry); - - emit window->afterAnimating(); - - // The native window may change in some (quite artificial) cases, e.g. due - // to a hide - destroy - show on the QWindow. - bool needsWindow = !data.engine->window(); - if (data.engine->window() && data.engine->window() != window->winId()) { - if (Q_UNLIKELY(debug_loop())) - qDebug("sync - native window handle changes for active engine"); - data.engine->waitGPU(); - wd->cleanupNodesOnShutdown(); - QSGD3D12ShaderEffectNode::cleanupMaterialTypeCache(); - data.rc->invalidate(); - data.engine->releaseResources(); - needsWindow = true; - } - if (needsWindow) { - // Must only ever get here when there is no window or releaseResources() has been called. - const int samples = window->format().samples(); - const bool alpha = window->format().alphaBufferSize() > 0; - const qreal dpr = window->effectiveDevicePixelRatio(); - if (Q_UNLIKELY(debug_loop())) - qDebug() << "sync - reinitializing D3D12 engine" << window << window->size() << dpr << samples << alpha; - data.engine->attachToWindow(window->winId(), window->size(), dpr, samples, alpha); - } - - // Recover from device loss. - if (!data.engine->hasResources()) { - if (Q_UNLIKELY(debug_loop())) - qDebug("sync - device was lost, resetting scenegraph"); - wd->cleanupNodesOnShutdown(); - QSGD3D12ShaderEffectNode::cleanupMaterialTypeCache(); - data.rc->invalidate(); - } - - data.rc->initialize(nullptr); - - wd->syncSceneGraph(); - data.rc->endSync(); - - if (profileFrames) - syncTime = renderTimer.nsecsElapsed(); - Q_TRACE(QSG_sync_exit); - Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame, - QQuickProfiler::SceneGraphRenderLoopSync); - Q_TRACE(QSG_render_entry); - - wd->renderSceneGraph(window->size()); - - if (profileFrames) - renderTime = renderTimer.nsecsElapsed(); - Q_TRACE(QSG_render_exit); - Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame, - QQuickProfiler::SceneGraphRenderLoopRender); - Q_TRACE(QSG_swap_entry); - - if (!data.grabOnly) { - // The engine is able to have multiple frames in flight. This in effect is - // similar to BufferQueueingOpenGL. Provide an env var to force the - // traditional blocking swap behavior, just in case. - static bool blockOnEachFrame = qEnvironmentVariableIntValue("QT_D3D_BLOCKING_PRESENT") != 0; - - if (window->isVisible()) { - data.engine->present(); - if (blockOnEachFrame) - data.engine->waitGPU(); - // The concept of "frame swaps" is quite misleading by default, when - // blockOnEachFrame is not used, but emit it for compatibility. - wd->fireFrameSwapped(); - } else { - if (blockOnEachFrame) - data.engine->waitGPU(); - } - } else { - m_grabContent = data.engine->executeAndWaitReadbackRenderTarget(); - data.grabOnly = false; - } - - qint64 swapTime = 0; - if (profileFrames) - swapTime = renderTimer.nsecsElapsed(); - Q_TRACE(QSG_swap_exit); - Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphRenderLoopFrame, - QQuickProfiler::SceneGraphRenderLoopSwap); - - if (Q_UNLIKELY(debug_time())) { - static QTime lastFrameTime = QTime::currentTime(); - qDebug("Frame rendered with 'd3d12' renderloop in %dms, polish=%d, sync=%d, render=%d, swap=%d, frameDelta=%d", - int(swapTime / 1000000), - int(polishTime / 1000000), - int((syncTime - polishTime) / 1000000), - int((renderTime - syncTime) / 1000000), - int((swapTime - renderTime) / 10000000), - int(lastFrameTime.msecsTo(QTime::currentTime()))); - lastFrameTime = QTime::currentTime(); - } - - // Simulate device loss if requested. - static int devLossTest = qEnvironmentVariableIntValue("QT_D3D_TEST_DEVICE_LOSS"); - if (devLossTest > 0) { - static QElapsedTimer kt; - static bool timerRunning = false; - if (!timerRunning) { - kt.start(); - timerRunning = true; - } else if (kt.elapsed() > 5000) { - --devLossTest; - kt.restart(); - data.engine->simulateDeviceLoss(); - } - } -} - -int QSGD3D12RenderLoop::flags() const -{ - return SupportsGrabWithoutExpose; -} - -QT_END_NAMESPACE diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12renderloop_p.h b/src/plugins/scenegraph/d3d12/qsgd3d12renderloop_p.h deleted file mode 100644 index c0333ffad0..0000000000 --- a/src/plugins/scenegraph/d3d12/qsgd3d12renderloop_p.h +++ /dev/null @@ -1,130 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#ifndef QSGD3D12RENDERLOOP_P_H -#define QSGD3D12RENDERLOOP_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include - -QT_BEGIN_NAMESPACE - -class QSGD3D12Engine; -class QSGD3D12Context; -class QSGD3D12RenderContext; - -class QSGD3D12RenderLoop : public QSGRenderLoop -{ - Q_OBJECT - -public: - QSGD3D12RenderLoop(); - ~QSGD3D12RenderLoop(); - - void show(QQuickWindow *window) override; - void hide(QQuickWindow *window) override; - void resize(QQuickWindow *window) override; - - void windowDestroyed(QQuickWindow *window) override; - - void exposureChanged(QQuickWindow *window) override; - - QImage grab(QQuickWindow *window) override; - - void update(QQuickWindow *window) override; - void maybeUpdate(QQuickWindow *window) override; - - QAnimationDriver *animationDriver() const override; - - QSGContext *sceneGraphContext() const override; - QSGRenderContext *createRenderContext(QSGContext *) const override; - - void releaseResources(QQuickWindow *window) override; - void postJob(QQuickWindow *window, QRunnable *job) override; - - QSurface::SurfaceType windowSurfaceType() const override; - bool interleaveIncubation() const override; - int flags() const override; - - bool event(QEvent *event) override; - -public Q_SLOTS: - void onAnimationStarted(); - void onAnimationStopped(); - -private: - void exposeWindow(QQuickWindow *window); - void obscureWindow(QQuickWindow *window); - void renderWindow(QQuickWindow *window); - void render(); - void maybePostUpdateTimer(); - bool somethingVisible() const; - - QSGD3D12Context *sg; - QAnimationDriver *m_anims; - int m_vsyncDelta; - int m_updateTimer = 0; - int m_animationTimer = 0; - - struct WindowData { - QSGD3D12RenderContext *rc = nullptr; - QSGD3D12Engine *engine = nullptr; - bool updatePending = false; - bool grabOnly = false; - bool exposed = false; - }; - - QHash m_windows; - - QImage m_grabContent; -}; - -QT_END_NAMESPACE - -#endif // QSGD3D12RENDERLOOP_P_H diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12shadereffectnode.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12shadereffectnode.cpp deleted file mode 100644 index 1f574a9802..0000000000 --- a/src/plugins/scenegraph/d3d12/qsgd3d12shadereffectnode.cpp +++ /dev/null @@ -1,995 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include "qsgd3d12shadereffectnode_p.h" -#include "qsgd3d12rendercontext_p.h" -#include "qsgd3d12texture_p.h" -#include "qsgd3d12engine_p.h" -#include -#include -#include -#include -#include - -#include -#include - -#include "vs_shadereffectdefault.hlslh" -#include "ps_shadereffectdefault.hlslh" - -QT_BEGIN_NAMESPACE - -// NOTE: Avoid categorized logging. It is slow. - -#define DECLARE_DEBUG_VAR(variable) \ - static bool debug_ ## variable() \ - { static bool value = qgetenv("QSG_RENDERER_DEBUG").contains(QT_STRINGIFY(variable)); return value; } - -DECLARE_DEBUG_VAR(shader) - -void QSGD3D12ShaderLinker::reset(const QByteArray &vertBlob, const QByteArray &fragBlob) -{ - Q_ASSERT(!vertBlob.isEmpty() && !fragBlob.isEmpty()); - vs = vertBlob; - fs = fragBlob; - - error = false; - - constantBufferSize = 0; - constants.clear(); - samplers.clear(); - textures.clear(); - textureNameMap.clear(); -} - -void QSGD3D12ShaderLinker::feedConstants(const QSGShaderEffectNode::ShaderData &shader, const QSet *dirtyIndices) -{ - Q_ASSERT(shader.shaderInfo.variables.count() == shader.varData.count()); - if (!dirtyIndices) { - constantBufferSize = qMax(constantBufferSize, shader.shaderInfo.constantDataSize); - for (int i = 0; i < shader.shaderInfo.variables.count(); ++i) { - const auto &var(shader.shaderInfo.variables.at(i)); - if (var.type == QSGGuiThreadShaderEffectManager::ShaderInfo::Constant) { - const auto &vd(shader.varData.at(i)); - Constant c; - c.size = var.size; - c.specialType = vd.specialType; - if (c.specialType != QSGShaderEffectNode::VariableData::SubRect) { - c.value = vd.value; - } else { - Q_ASSERT(var.name.startsWith(QByteArrayLiteral("qt_SubRect_"))); - c.value = var.name.mid(11); - } - constants[var.offset] = c; - } - } - } else { - for (int idx : *dirtyIndices) - constants[shader.shaderInfo.variables.at(idx).offset].value = shader.varData.at(idx).value; - } -} - -void QSGD3D12ShaderLinker::feedSamplers(const QSGShaderEffectNode::ShaderData &shader) -{ - for (int i = 0; i < shader.shaderInfo.variables.count(); ++i) { - const auto &var(shader.shaderInfo.variables.at(i)); - if (var.type == QSGGuiThreadShaderEffectManager::ShaderInfo::Sampler) { - Q_ASSERT(shader.varData.at(i).specialType == QSGShaderEffectNode::VariableData::Unused); - samplers.insert(var.bindPoint); - } - } -} - -void QSGD3D12ShaderLinker::feedTextures(const QSGShaderEffectNode::ShaderData &shader, const QSet *dirtyIndices) -{ - if (!dirtyIndices) { - for (int i = 0; i < shader.shaderInfo.variables.count(); ++i) { - const auto &var(shader.shaderInfo.variables.at(i)); - const auto &vd(shader.varData.at(i)); - if (var.type == QSGGuiThreadShaderEffectManager::ShaderInfo::Texture) { - Q_ASSERT(vd.specialType == QSGShaderEffectNode::VariableData::Source); - textures.insert(var.bindPoint, vd.value); - textureNameMap.insert(var.name, var.bindPoint); - } - } - } else { - for (int idx : *dirtyIndices) { - const auto &var(shader.shaderInfo.variables.at(idx)); - const auto &vd(shader.varData.at(idx)); - textures.insert(var.bindPoint, vd.value); - textureNameMap.insert(var.name, var.bindPoint); - } - } -} - -void QSGD3D12ShaderLinker::linkTextureSubRects() -{ - // feedConstants stores in Constant::value for subrect entries. Now - // that both constants and textures are known, replace the name with the - // texture bind point. - for (Constant &c : constants) { - if (c.specialType == QSGShaderEffectNode::VariableData::SubRect) { - if (c.value.type() == QVariant::ByteArray) { - const QByteArray name = c.value.toByteArray(); - if (!textureNameMap.contains(name)) - qWarning("ShaderEffect: qt_SubRect_%s refers to unknown source texture", qPrintable(name)); - c.value = textureNameMap[name]; - } - } - } -} - -void QSGD3D12ShaderLinker::dump() -{ - if (error) { - qDebug() << "Failed to generate program data"; - return; - } - qDebug() << "Combined shader data" << vs.size() << fs.size() << "cbuffer size" << constantBufferSize; - qDebug() << " - constants" << constants; - qDebug() << " - samplers" << samplers; - qDebug() << " - textures" << textures; -} - -QDebug operator<<(QDebug debug, const QSGD3D12ShaderLinker::Constant &c) -{ - QDebugStateSaver saver(debug); - debug.space(); - debug << "size" << c.size; - if (c.specialType != QSGShaderEffectNode::VariableData::None) - debug << "special" << c.specialType; - else - debug << "value" << c.value; - return debug; -} - -QSGD3D12ShaderEffectMaterial::QSGD3D12ShaderEffectMaterial(QSGD3D12ShaderEffectNode *node) - : node(node) -{ - setFlag(Blending | RequiresFullMatrix, true); // may be changed in sync() -} - -QSGD3D12ShaderEffectMaterial::~QSGD3D12ShaderEffectMaterial() -{ - delete dummy; -} - -struct QSGD3D12ShaderMaterialTypeCache -{ - QSGMaterialType *get(const QByteArray &vs, const QByteArray &fs); - void reset() { qDeleteAll(m_types); m_types.clear(); } - - struct Key { - QByteArray blob[2]; - Key() { } - Key(const QByteArray &vs, const QByteArray &fs) { blob[0] = vs; blob[1] = fs; } - bool operator==(const Key &other) const { - return blob[0] == other.blob[0] && blob[1] == other.blob[1]; - } - }; - QHash m_types; -}; - -uint qHash(const QSGD3D12ShaderMaterialTypeCache::Key &key, uint seed = 0) -{ - uint hash = seed; - for (int i = 0; i < 2; ++i) - hash = hash * 31337 + qHash(key.blob[i]); - return hash; -} - -QSGMaterialType *QSGD3D12ShaderMaterialTypeCache::get(const QByteArray &vs, const QByteArray &fs) -{ - const Key k(vs, fs); - if (m_types.contains(k)) - return m_types.value(k); - - QSGMaterialType *t = new QSGMaterialType; - m_types.insert(k, t); - return t; -} - -Q_GLOBAL_STATIC(QSGD3D12ShaderMaterialTypeCache, shaderMaterialTypeCache) - -void QSGD3D12ShaderEffectNode::cleanupMaterialTypeCache() -{ - shaderMaterialTypeCache()->reset(); -} - -QSGMaterialType *QSGD3D12ShaderEffectMaterial::type() const -{ - return mtype; -} - -static bool hasAtlasTexture(const QVector &textureProviders) -{ - for (int i = 0; i < textureProviders.count(); ++i) { - QSGTextureProvider *t = textureProviders.at(i); - if (t && t->texture() && t->texture()->isAtlasTexture()) - return true; - } - return false; -} - -int QSGD3D12ShaderEffectMaterial::compare(const QSGMaterial *other) const -{ - Q_ASSERT(other && type() == other->type()); - const QSGD3D12ShaderEffectMaterial *o = static_cast(other); - - if (int diff = cullMode - o->cullMode) - return diff; - - if (int diff = textureProviders.count() - o->textureProviders.count()) - return diff; - - if (linker.constants != o->linker.constants) - return 1; - - if ((hasAtlasTexture(textureProviders) && !geometryUsesTextureSubRect) - || (hasAtlasTexture(o->textureProviders) && !o->geometryUsesTextureSubRect)) - return 1; - - for (int i = 0; i < textureProviders.count(); ++i) { - QSGTextureProvider *tp1 = textureProviders.at(i); - QSGTextureProvider *tp2 = o->textureProviders.at(i); - if (!tp1 || !tp2) - return tp1 == tp2 ? 0 : 1; - QSGTexture *t1 = tp1->texture(); - QSGTexture *t2 = tp2->texture(); - if (!t1 || !t2) - return t1 == t2 ? 0 : 1; - if (int diff = t1->textureId() - t2->textureId()) - return diff; - } - - return 0; -} - -int QSGD3D12ShaderEffectMaterial::constantBufferSize() const -{ - return QSGD3D12Engine::alignedConstantBufferSize(linker.constantBufferSize); -} - -void QSGD3D12ShaderEffectMaterial::preparePipeline(QSGD3D12PipelineState *pipelineState) -{ - pipelineState->shaders.vs = reinterpret_cast(linker.vs.constData()); - pipelineState->shaders.vsSize = linker.vs.size(); - pipelineState->shaders.ps = reinterpret_cast(linker.fs.constData()); - pipelineState->shaders.psSize = linker.fs.size(); - - pipelineState->shaders.rootSig.textureViewCount = textureProviders.count(); -} - -static inline QColor qsg_premultiply_color(const QColor &c) -{ - return QColor::fromRgbF(c.redF() * c.alphaF(), c.greenF() * c.alphaF(), c.blueF() * c.alphaF(), c.alphaF()); -} - -QSGD3D12Material::UpdateResults QSGD3D12ShaderEffectMaterial::updatePipeline(const QSGD3D12MaterialRenderState &state, - QSGD3D12PipelineState *pipelineState, - ExtraState *, - quint8 *constantBuffer) -{ - QSGD3D12Material::UpdateResults r = 0; - quint8 *p = constantBuffer; - - for (auto it = linker.constants.constBegin(), itEnd = linker.constants.constEnd(); it != itEnd; ++it) { - quint8 *dst = p + it.key(); - const QSGD3D12ShaderLinker::Constant &c(it.value()); - if (c.specialType == QSGShaderEffectNode::VariableData::Opacity) { - if (state.isOpacityDirty()) { - const float f = state.opacity(); - Q_ASSERT(sizeof(f) == c.size); - memcpy(dst, &f, sizeof(f)); - r |= UpdatedConstantBuffer; - } - } else if (c.specialType == QSGShaderEffectNode::VariableData::Matrix) { - if (state.isMatrixDirty()) { - const int sz = 16 * sizeof(float); - Q_ASSERT(sz == c.size); - memcpy(dst, state.combinedMatrix().constData(), sz); - r |= UpdatedConstantBuffer; - } - } else if (c.specialType == QSGShaderEffectNode::VariableData::SubRect) { - // float4 - QRectF subRect(0, 0, 1, 1); - int srcBindPoint = c.value.toInt(); // filled in by linkTextureSubRects - if (QSGTexture *t = textureProviders.at(srcBindPoint)->texture()) - subRect = t->normalizedTextureSubRect(); - const float f[4] = { float(subRect.x()), float(subRect.y()), - float(subRect.width()), float(subRect.height()) }; - Q_ASSERT(sizeof(f) == c.size); - memcpy(dst, f, sizeof(f)); - } else if (c.specialType == QSGShaderEffectNode::VariableData::None) { - r |= UpdatedConstantBuffer; - switch (c.value.type()) { - case QMetaType::QColor: { - const QColor v = qsg_premultiply_color(qvariant_cast(c.value)); - const float f[4] = { float(v.redF()), float(v.greenF()), float(v.blueF()), float(v.alphaF()) }; - Q_ASSERT(sizeof(f) == c.size); - memcpy(dst, f, sizeof(f)); - break; - } - case QMetaType::Float: { - const float f = qvariant_cast(c.value); - Q_ASSERT(sizeof(f) == c.size); - memcpy(dst, &f, sizeof(f)); - break; - } - case QMetaType::Double: { - const float f = float(qvariant_cast(c.value)); - Q_ASSERT(sizeof(f) == c.size); - memcpy(dst, &f, sizeof(f)); - break; - } - case QMetaType::Int: { - const int i = c.value.toInt(); - Q_ASSERT(sizeof(i) == c.size); - memcpy(dst, &i, sizeof(i)); - break; - } - case QMetaType::Bool: { - const bool b = c.value.toBool(); - Q_ASSERT(sizeof(b) == c.size); - memcpy(dst, &b, sizeof(b)); - break; - } - case QMetaType::QTransform: { // float3x3 - const QTransform v = qvariant_cast(c.value); - const float m[3][3] = { - { float(v.m11()), float(v.m12()), float(v.m13()) }, - { float(v.m21()), float(v.m22()), float(v.m23()) }, - { float(v.m31()), float(v.m32()), float(v.m33()) } - }; - Q_ASSERT(sizeof(m) == c.size); - memcpy(dst, m[0], sizeof(m)); - break; - } - case QMetaType::QSize: - case QMetaType::QSizeF: { // float2 - const QSizeF v = c.value.toSizeF(); - const float f[2] = { float(v.width()), float(v.height()) }; - Q_ASSERT(sizeof(f) == c.size); - memcpy(dst, f, sizeof(f)); - break; - } - case QMetaType::QPoint: - case QMetaType::QPointF: { // float2 - const QPointF v = c.value.toPointF(); - const float f[2] = { float(v.x()), float(v.y()) }; - Q_ASSERT(sizeof(f) == c.size); - memcpy(dst, f, sizeof(f)); - break; - } - case QMetaType::QRect: - case QMetaType::QRectF: { // float4 - const QRectF v = c.value.toRectF(); - const float f[4] = { float(v.x()), float(v.y()), float(v.width()), float(v.height()) }; - Q_ASSERT(sizeof(f) == c.size); - memcpy(dst, f, sizeof(f)); - break; - } - case QMetaType::QVector2D: { // float2 - const QVector2D v = qvariant_cast(c.value); - const float f[2] = { float(v.x()), float(v.y()) }; - Q_ASSERT(sizeof(f) == c.size); - memcpy(dst, f, sizeof(f)); - break; - } - case QMetaType::QVector3D: { // float3 - const QVector3D v = qvariant_cast(c.value); - const float f[3] = { float(v.x()), float(v.y()), float(v.z()) }; - Q_ASSERT(sizeof(f) == c.size); - memcpy(dst, f, sizeof(f)); - break; - } - case QMetaType::QVector4D: { // float4 - const QVector4D v = qvariant_cast(c.value); - const float f[4] = { float(v.x()), float(v.y()), float(v.z()), float(v.w()) }; - Q_ASSERT(sizeof(f) == c.size); - memcpy(dst, f, sizeof(f)); - break; - } - case QMetaType::QQuaternion: { // float4 - const QQuaternion v = qvariant_cast(c.value); - const float f[4] = { float(v.x()), float(v.y()), float(v.z()), float(v.scalar()) }; - Q_ASSERT(sizeof(f) == c.size); - memcpy(dst, f, sizeof(f)); - break; - } - case QMetaType::QMatrix4x4: { // float4x4 - const QMatrix4x4 v = qvariant_cast(c.value); - const int sz = 16 * sizeof(float); - Q_ASSERT(sz == c.size); - memcpy(dst, v.constData(), sz); - break; - } - default: - break; - } - } - } - - for (int i = 0; i < textureProviders.count(); ++i) { - QSGTextureProvider *tp = textureProviders[i]; - QSGD3D12TextureView &tv(pipelineState->shaders.rootSig.textureViews[i]); - if (tp) { - if (QSGTexture *t = tp->texture()) { - if (t->isAtlasTexture() && !geometryUsesTextureSubRect) { - QSGTexture *newTexture = t->removedFromAtlas(); - if (newTexture) - t = newTexture; - } - tv.filter = t->filtering() == QSGTexture::Linear - ? QSGD3D12TextureView::FilterLinear : QSGD3D12TextureView::FilterNearest; - tv.addressModeHoriz = t->horizontalWrapMode() == QSGTexture::ClampToEdge - ? QSGD3D12TextureView::AddressClamp : QSGD3D12TextureView::AddressWrap; - tv.addressModeVert = t->verticalWrapMode() == QSGTexture::ClampToEdge - ? QSGD3D12TextureView::AddressClamp : QSGD3D12TextureView::AddressWrap; - t->bind(); - continue; - } - } - if (!dummy) { - dummy = new QSGD3D12Texture(node->renderContext()->engine()); - QImage img(128, 128, QImage::Format_ARGB32_Premultiplied); - img.fill(0); - dummy->create(img, QSGRenderContext::CreateTexture_Alpha); - } - tv.filter = QSGD3D12TextureView::FilterNearest; - tv.addressModeHoriz = QSGD3D12TextureView::AddressWrap; - tv.addressModeVert = QSGD3D12TextureView::AddressWrap; - dummy->bind(); - } - - switch (cullMode) { - case QSGShaderEffectNode::FrontFaceCulling: - pipelineState->cullMode = QSGD3D12PipelineState::CullFront; - break; - case QSGShaderEffectNode::BackFaceCulling: - pipelineState->cullMode = QSGD3D12PipelineState::CullBack; - break; - default: - pipelineState->cullMode = QSGD3D12PipelineState::CullNone; - break; - } - - return r; -} - -void QSGD3D12ShaderEffectMaterial::updateTextureProviders(bool layoutChange) -{ - if (layoutChange) { - for (QSGTextureProvider *tp : textureProviders) { - if (tp) { - QObject::disconnect(tp, SIGNAL(textureChanged()), node, - SLOT(handleTextureChange())); - QObject::disconnect(tp, SIGNAL(destroyed(QObject*)), node, - SLOT(handleTextureProviderDestroyed(QObject*))); - } - } - - textureProviders.fill(nullptr, linker.textures.count()); - } - - for (auto it = linker.textures.constBegin(), itEnd = linker.textures.constEnd(); it != itEnd; ++it) { - const int bindPoint = it.key(); - // Now that the linker has merged the textures, we can switch over to a - // simple vector indexed by the binding point for textureProviders. - Q_ASSERT(bindPoint >= 0 && bindPoint < textureProviders.count()); - QQuickItem *source = qobject_cast(qvariant_cast(it.value())); - QSGTextureProvider *newProvider = source && source->isTextureProvider() ? source->textureProvider() : nullptr; - QSGTextureProvider *&activeProvider(textureProviders[bindPoint]); - if (newProvider != activeProvider) { - if (activeProvider) { - QObject::disconnect(activeProvider, SIGNAL(textureChanged()), node, - SLOT(handleTextureChange())); - QObject::disconnect(activeProvider, SIGNAL(destroyed(QObject*)), node, - SLOT(handleTextureProviderDestroyed(QObject*))); - } - if (newProvider) { - Q_ASSERT_X(newProvider->thread() == QThread::currentThread(), - "QSGD3D12ShaderEffectMaterial::updateTextureProviders", - "Texture provider must belong to the rendering thread"); - QObject::connect(newProvider, SIGNAL(textureChanged()), node, SLOT(handleTextureChange())); - QObject::connect(newProvider, SIGNAL(destroyed(QObject*)), node, - SLOT(handleTextureProviderDestroyed(QObject*))); - } else { - const char *typeName = source ? source->metaObject()->className() : it.value().typeName(); - qWarning("ShaderEffect: Texture t%d is not assigned a valid texture provider (%s).", - bindPoint, typeName); - } - activeProvider = newProvider; - } - } -} - -QSGD3D12ShaderEffectNode::QSGD3D12ShaderEffectNode(QSGD3D12RenderContext *rc, QSGD3D12GuiThreadShaderEffectManager *mgr) - : QSGShaderEffectNode(mgr), - m_rc(rc), - m_mgr(mgr), - m_material(this) -{ - setFlag(UsePreprocess, true); - setMaterial(&m_material); -} - -QRectF QSGD3D12ShaderEffectNode::updateNormalizedTextureSubRect(bool supportsAtlasTextures) -{ - QRectF srcRect(0, 0, 1, 1); - bool geometryUsesTextureSubRect = false; - if (supportsAtlasTextures && m_material.textureProviders.count() == 1) { - QSGTextureProvider *provider = m_material.textureProviders.at(0); - if (provider->texture()) { - srcRect = provider->texture()->normalizedTextureSubRect(); - geometryUsesTextureSubRect = true; - } - } - - if (m_material.geometryUsesTextureSubRect != geometryUsesTextureSubRect) { - m_material.geometryUsesTextureSubRect = geometryUsesTextureSubRect; - markDirty(QSGNode::DirtyMaterial); - } - - return srcRect; -} - -void QSGD3D12ShaderEffectNode::syncMaterial(SyncData *syncData) -{ - if (Q_UNLIKELY(debug_shader())) - qDebug() << "shadereffect node sync" << syncData->dirty; - - if (bool(m_material.flags() & QSGMaterial::Blending) != syncData->blending) { - m_material.setFlag(QSGMaterial::Blending, syncData->blending); - markDirty(QSGNode::DirtyMaterial); - } - - if (m_material.cullMode != syncData->cullMode) { - m_material.cullMode = syncData->cullMode; - markDirty(QSGNode::DirtyMaterial); - } - - if (syncData->dirty & QSGShaderEffectNode::DirtyShaders) { - QByteArray vertBlob, fragBlob; - - m_material.hasCustomVertexShader = syncData->vertex.shader->hasShaderCode; - if (m_material.hasCustomVertexShader) { - vertBlob = syncData->vertex.shader->shaderInfo.blob; - } else { - vertBlob = QByteArray::fromRawData(reinterpret_cast(g_VS_DefaultShaderEffect), - sizeof(g_VS_DefaultShaderEffect)); - } - - m_material.hasCustomFragmentShader = syncData->fragment.shader->hasShaderCode; - if (m_material.hasCustomFragmentShader) { - fragBlob = syncData->fragment.shader->shaderInfo.blob; - } else { - fragBlob = QByteArray::fromRawData(reinterpret_cast(g_PS_DefaultShaderEffect), - sizeof(g_PS_DefaultShaderEffect)); - } - - m_material.mtype = shaderMaterialTypeCache()->get(vertBlob, fragBlob); - m_material.linker.reset(vertBlob, fragBlob); - - if (m_material.hasCustomVertexShader) { - m_material.linker.feedConstants(*syncData->vertex.shader); - } else { - QSGShaderEffectNode::ShaderData defaultSD; - defaultSD.shaderInfo.blob = vertBlob; - defaultSD.shaderInfo.type = QSGGuiThreadShaderEffectManager::ShaderInfo::TypeVertex; - - // { float4x4 qt_Matrix; float qt_Opacity; } where only the matrix is used - QSGGuiThreadShaderEffectManager::ShaderInfo::Variable v; - v.name = QByteArrayLiteral("qt_Matrix"); - v.offset = 0; - v.size = 16 * sizeof(float); - defaultSD.shaderInfo.variables.append(v); - QSGShaderEffectNode::VariableData vd; - vd.specialType = QSGShaderEffectNode::VariableData::Matrix; - defaultSD.varData.append(vd); - defaultSD.shaderInfo.constantDataSize = (16 + 1) * sizeof(float); - m_material.linker.feedConstants(defaultSD); - } - - m_material.linker.feedSamplers(*syncData->vertex.shader); - m_material.linker.feedTextures(*syncData->vertex.shader); - - if (m_material.hasCustomFragmentShader) { - m_material.linker.feedConstants(*syncData->fragment.shader); - } else { - QSGShaderEffectNode::ShaderData defaultSD; - defaultSD.shaderInfo.blob = fragBlob; - defaultSD.shaderInfo.type = QSGGuiThreadShaderEffectManager::ShaderInfo::TypeFragment; - - // { float4x4 qt_Matrix; float qt_Opacity; } where only the opacity is used - QSGGuiThreadShaderEffectManager::ShaderInfo::Variable v; - v.name = QByteArrayLiteral("qt_Opacity"); - v.offset = 16 * sizeof(float); - v.size = sizeof(float); - defaultSD.shaderInfo.variables.append(v); - QSGShaderEffectNode::VariableData vd; - vd.specialType = QSGShaderEffectNode::VariableData::Opacity; - defaultSD.varData.append(vd); - - v.name = QByteArrayLiteral("source"); - v.bindPoint = 0; - v.type = QSGGuiThreadShaderEffectManager::ShaderInfo::Texture; - defaultSD.shaderInfo.variables.append(v); - vd.specialType = QSGShaderEffectNode::VariableData::Source; - defaultSD.varData.append(vd); - - v.name = QByteArrayLiteral("sourceSampler"); - v.bindPoint = 0; - v.type = QSGGuiThreadShaderEffectManager::ShaderInfo::Sampler; - defaultSD.shaderInfo.variables.append(v); - vd.specialType = QSGShaderEffectNode::VariableData::Unused; - defaultSD.varData.append(vd); - - defaultSD.shaderInfo.constantDataSize = (16 + 1) * sizeof(float); - - m_material.linker.feedConstants(defaultSD); - m_material.linker.feedSamplers(defaultSD); - m_material.linker.feedTextures(defaultSD); - } - - // While this may seem unnecessary for the built-in shaders, the value - // of 'source' is still in there and we have to process it. - m_material.linker.feedSamplers(*syncData->fragment.shader); - m_material.linker.feedTextures(*syncData->fragment.shader); - - m_material.linker.linkTextureSubRects(); - - m_material.updateTextureProviders(true); - - markDirty(QSGNode::DirtyMaterial); - - if (Q_UNLIKELY(debug_shader())) - m_material.linker.dump(); - } else { - if (syncData->dirty & QSGShaderEffectNode::DirtyShaderConstant) { - if (!syncData->vertex.dirtyConstants->isEmpty()) - m_material.linker.feedConstants(*syncData->vertex.shader, syncData->vertex.dirtyConstants); - if (!syncData->fragment.dirtyConstants->isEmpty()) - m_material.linker.feedConstants(*syncData->fragment.shader, syncData->fragment.dirtyConstants); - markDirty(QSGNode::DirtyMaterial); - if (Q_UNLIKELY(debug_shader())) - m_material.linker.dump(); - } - - if (syncData->dirty & QSGShaderEffectNode::DirtyShaderTexture) { - if (!syncData->vertex.dirtyTextures->isEmpty()) - m_material.linker.feedTextures(*syncData->vertex.shader, syncData->vertex.dirtyTextures); - if (!syncData->fragment.dirtyTextures->isEmpty()) - m_material.linker.feedTextures(*syncData->fragment.shader, syncData->fragment.dirtyTextures); - m_material.linker.linkTextureSubRects(); - m_material.updateTextureProviders(false); - markDirty(QSGNode::DirtyMaterial); - if (Q_UNLIKELY(debug_shader())) - m_material.linker.dump(); - } - } - - if (bool(m_material.flags() & QSGMaterial::RequiresFullMatrix) != m_material.hasCustomVertexShader) { - m_material.setFlag(QSGMaterial::RequiresFullMatrix, m_material.hasCustomVertexShader); - markDirty(QSGNode::DirtyMaterial); - } -} - -void QSGD3D12ShaderEffectNode::handleTextureChange() -{ - markDirty(QSGNode::DirtyMaterial); - emit m_mgr->textureChanged(); -} - -void QSGD3D12ShaderEffectNode::handleTextureProviderDestroyed(QObject *object) -{ - for (QSGTextureProvider *&tp : m_material.textureProviders) { - if (tp == object) - tp = nullptr; - } -} - -void QSGD3D12ShaderEffectNode::preprocess() -{ - for (QSGTextureProvider *tp : m_material.textureProviders) { - if (tp) { - if (QSGDynamicTexture *texture = qobject_cast(tp->texture())) - texture->updateTexture(); - } - } -} - -bool QSGD3D12GuiThreadShaderEffectManager::hasSeparateSamplerAndTextureObjects() const -{ - return true; -} - -QString QSGD3D12GuiThreadShaderEffectManager::log() const -{ - return m_log; -} - -QSGGuiThreadShaderEffectManager::Status QSGD3D12GuiThreadShaderEffectManager::status() const -{ - return m_status; -} - -struct RefGuard { - RefGuard(IUnknown *p) : p(p) { } - ~RefGuard() { p->Release(); } - IUnknown *p; -}; - -class QSGD3D12ShaderCompileTask : public QRunnable -{ -public: - QSGD3D12ShaderCompileTask(QSGD3D12GuiThreadShaderEffectManager *mgr, - QSGD3D12GuiThreadShaderEffectManager::ShaderInfo::Type typeHint, - const QByteArray &src, - QSGD3D12GuiThreadShaderEffectManager::ShaderInfo *result) - : mgr(mgr), typeHint(typeHint), src(src), result(result) { } - - void run() override; - -private: - QSGD3D12GuiThreadShaderEffectManager *mgr; - QSGD3D12GuiThreadShaderEffectManager::ShaderInfo::Type typeHint; - QByteArray src; - QSGD3D12GuiThreadShaderEffectManager::ShaderInfo *result; -}; - -void QSGD3D12ShaderCompileTask::run() -{ - const char *target = typeHint == QSGD3D12GuiThreadShaderEffectManager::ShaderInfo::TypeVertex ? "vs_5_0" : "ps_5_0"; - ID3DBlob *bytecode = nullptr; - ID3DBlob *errors = nullptr; - HRESULT hr = D3DCompile(src.constData(), src.size(), nullptr, nullptr, nullptr, - "main", target, 0, 0, &bytecode, &errors); - if (FAILED(hr) || !bytecode) { - qWarning("HLSL shader compilation failed: 0x%x", hr); - if (errors) { - mgr->m_log += QString::fromUtf8(static_cast(errors->GetBufferPointer()), errors->GetBufferSize()); - errors->Release(); - } - mgr->m_status = QSGGuiThreadShaderEffectManager::Error; - emit mgr->shaderCodePrepared(false, typeHint, src, result); - emit mgr->logAndStatusChanged(); - return; - } - - result->blob.resize(bytecode->GetBufferSize()); - memcpy(result->blob.data(), bytecode->GetBufferPointer(), result->blob.size()); - bytecode->Release(); - - const bool ok = mgr->reflect(result); - mgr->m_status = ok ? QSGGuiThreadShaderEffectManager::Compiled : QSGGuiThreadShaderEffectManager::Error; - emit mgr->shaderCodePrepared(ok, typeHint, src, result); - emit mgr->logAndStatusChanged(); -} - -static const int BYTECODE_MAGIC = 0x43425844; // 'DXBC' - -void QSGD3D12GuiThreadShaderEffectManager::prepareShaderCode(ShaderInfo::Type typeHint, const QByteArray &src, ShaderInfo *result) -{ - // The D3D12 backend's ShaderEffect implementation supports both HLSL - // source strings and bytecode or source in files as input. Bytecode is - // strongly recommended, but in order to make ShaderEffect users' (and - // anything that stiches shader strings together dynamically, e.g. - // qtgraphicaleffects) life easier, and since we link to d3dcompiler - // anyways, compiling from source is also supported. - - QByteArray shaderSourceCode = src; - QUrl srcUrl(QString::fromUtf8(src)); - if (!srcUrl.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) || srcUrl.isLocalFile()) { - if (!m_fileSelector) { - m_fileSelector = new QFileSelector(this); - m_fileSelector->setExtraSelectors(QStringList() << QStringLiteral("hlsl")); - } - const QString fn = m_fileSelector->select(QQmlFile::urlToLocalFileOrQrc(srcUrl)); - QFile f(fn); - if (!f.open(QIODevice::ReadOnly)) { - qWarning("ShaderEffect: Failed to read %s", qPrintable(fn)); - emit shaderCodePrepared(false, typeHint, src, result); - return; - } - QByteArray blob = f.readAll(); - f.close(); - if (blob.size() > 4) { - const quint32 *p = reinterpret_cast(blob.constData()); - if (*p == BYTECODE_MAGIC) { - // already compiled D3D bytecode, skip straight to reflection - result->blob = blob; - const bool ok = reflect(result); - m_status = ok ? Compiled : Error; - emit shaderCodePrepared(ok, typeHint, src, result); - emit logAndStatusChanged(); - return; - } - // assume the file contained HLSL source code - shaderSourceCode = blob; - } - } - - QThreadPool::globalInstance()->start(new QSGD3D12ShaderCompileTask(this, typeHint, shaderSourceCode, result)); -} - -bool QSGD3D12GuiThreadShaderEffectManager::reflect(ShaderInfo *result) -{ - ID3D12ShaderReflection *reflector; - HRESULT hr = D3DReflect(result->blob.constData(), result->blob.size(), IID_PPV_ARGS(&reflector)); - if (FAILED(hr)) { - qWarning("D3D shader reflection failed: 0x%x", hr); - return false; - } - RefGuard rg(reflector); - - D3D12_SHADER_DESC shaderDesc; - reflector->GetDesc(&shaderDesc); - - const uint progType = (shaderDesc.Version & 0xFFFF0000) >> 16; - const uint major = (shaderDesc.Version & 0x000000F0) >> 4; - const uint minor = (shaderDesc.Version & 0x0000000F); - - switch (progType) { - case D3D12_SHVER_VERTEX_SHADER: - result->type = ShaderInfo::TypeVertex; - break; - case D3D12_SHVER_PIXEL_SHADER: - result->type = ShaderInfo::TypeFragment; - break; - default: - result->type = ShaderInfo::TypeOther; - qWarning("D3D shader is of unknown type 0x%x", shaderDesc.Version); - return false; - } - - if (major < 5) { - qWarning("D3D shader model version %u.%u is too low", major, minor); - return false; - } - - const int ieCount = shaderDesc.InputParameters; - const int cbufferCount = shaderDesc.ConstantBuffers; - const int boundResCount = shaderDesc.BoundResources; - - result->constantDataSize = 0; - - if (ieCount < 1) { - qWarning("Invalid shader: Not enough input parameters (%d)", ieCount); - return false; - } - if (cbufferCount < 1) { - qWarning("Invalid shader: Shader has no constant buffers"); - return false; - } - if (boundResCount < 1) { - qWarning("Invalid shader: No resources bound. Expected to have at least a constant buffer bound."); - return false; - } - - if (Q_UNLIKELY(debug_shader())) - qDebug("Shader reflection size %d type %d v%u.%u input elems %d cbuffers %d boundres %d", - result->blob.size(), result->type, major, minor, ieCount, cbufferCount, boundResCount); - - for (int i = 0; i < boundResCount; ++i) { - D3D12_SHADER_INPUT_BIND_DESC desc; - if (FAILED(reflector->GetResourceBindingDesc(i, &desc))) { - qWarning("D3D reflection: Failed to query resource binding %d", i); - continue; - } - bool gotCBuffer = false; - if (desc.Type == D3D_SIT_CBUFFER) { - ID3D12ShaderReflectionConstantBuffer *cbuf = reflector->GetConstantBufferByName(desc.Name); - D3D12_SHADER_BUFFER_DESC bufDesc; - if (FAILED(cbuf->GetDesc(&bufDesc))) { - qWarning("D3D reflection: Failed to query constant buffer description"); - continue; - } - if (gotCBuffer) { - qWarning("D3D reflection: Found more than one constant buffers. Only the first one is used."); - continue; - } - gotCBuffer = true; - result->constantDataSize = bufDesc.Size; - for (uint cbIdx = 0; cbIdx < bufDesc.Variables; ++cbIdx) { - ID3D12ShaderReflectionVariable *cvar = cbuf->GetVariableByIndex(cbIdx); - D3D12_SHADER_VARIABLE_DESC varDesc; - if (FAILED(cvar->GetDesc(&varDesc))) { - qWarning("D3D reflection: Failed to query constant buffer variable %d", cbIdx); - return false; - } - // we report the full size of the buffer but only return variables that are actually used by this shader - if (!(varDesc.uFlags & D3D_SVF_USED)) - continue; - ShaderInfo::Variable v; - v.type = ShaderInfo::Constant; - v.name = QByteArray(varDesc.Name); - v.offset = varDesc.StartOffset; - v.size = varDesc.Size; - result->variables.append(v); - } - } else if (desc.Type == D3D_SIT_TEXTURE) { - if (desc.Dimension != D3D_SRV_DIMENSION_TEXTURE2D) { - qWarning("D3D reflection: Texture %s is not a 2D texture, ignoring.", qPrintable(desc.Name)); - continue; - } - if (desc.NumSamples != (UINT) -1) { - qWarning("D3D reflection: Texture %s is multisample (%u), ignoring.", qPrintable(desc.Name), desc.NumSamples); - continue; - } - if (desc.BindCount != 1) { - qWarning("D3D reflection: Texture %s is an array, ignoring.", qPrintable(desc.Name)); - continue; - } - if (desc.Space != 0) { - qWarning("D3D reflection: Texture %s is not using register space 0, ignoring.", qPrintable(desc.Name)); - continue; - } - ShaderInfo::Variable v; - v.type = ShaderInfo::Texture; - v.name = QByteArray(desc.Name); - v.bindPoint = desc.BindPoint; - result->variables.append(v); - } else if (desc.Type == D3D_SIT_SAMPLER) { - if (desc.BindCount != 1) { - qWarning("D3D reflection: Sampler %s is an array, ignoring.", qPrintable(desc.Name)); - continue; - } - if (desc.Space != 0) { - qWarning("D3D reflection: Sampler %s is not using register space 0, ignoring.", qPrintable(desc.Name)); - continue; - } - ShaderInfo::Variable v; - v.type = ShaderInfo::Sampler; - v.name = QByteArray(desc.Name); - v.bindPoint = desc.BindPoint; - result->variables.append(v); - } else { - qWarning("D3D reflection: Resource binding %d has an unknown type of %d and will be ignored.", i, desc.Type); - continue; - } - } - - if (Q_UNLIKELY(debug_shader())) - qDebug() << "Variables:" << result->variables << "cbuffer size" << result->constantDataSize; - - return true; -} - -QT_END_NAMESPACE diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12shadereffectnode_p.h b/src/plugins/scenegraph/d3d12/qsgd3d12shadereffectnode_p.h deleted file mode 100644 index dec85fd782..0000000000 --- a/src/plugins/scenegraph/d3d12/qsgd3d12shadereffectnode_p.h +++ /dev/null @@ -1,176 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#ifndef QSGD3D12SHADEREFFECTNODE_P_H -#define QSGD3D12SHADEREFFECTNODE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include -#include "qsgd3d12material_p.h" - -QT_BEGIN_NAMESPACE - -class QSGD3D12RenderContext; -class QSGD3D12GuiThreadShaderEffectManager; -class QSGD3D12ShaderEffectNode; -class QSGD3D12Texture; -class QFileSelector; - -class QSGD3D12ShaderLinker -{ -public: - void reset(const QByteArray &vertBlob, const QByteArray &fragBlob); - - void feedConstants(const QSGShaderEffectNode::ShaderData &shader, const QSet *dirtyIndices = nullptr); - void feedSamplers(const QSGShaderEffectNode::ShaderData &shader); - void feedTextures(const QSGShaderEffectNode::ShaderData &shader, const QSet *dirtyIndices = nullptr); - void linkTextureSubRects(); - - void dump(); - - struct Constant { - uint size; - QSGShaderEffectNode::VariableData::SpecialType specialType; - QVariant value; - bool operator==(const Constant &other) const { - return size == other.size && specialType == other.specialType - && (specialType == QSGShaderEffectNode::VariableData::None ? value == other.value : true); - } - }; - - bool error; - QByteArray vs; - QByteArray fs; - uint constantBufferSize; - QHash constants; // offset -> Constant - QSet samplers; // bindpoint - QHash textures; // bindpoint -> value (source ref) - QHash textureNameMap; // name -> bindpoint -}; - -QDebug operator<<(QDebug debug, const QSGD3D12ShaderLinker::Constant &c); - -class QSGD3D12ShaderEffectMaterial : public QSGD3D12Material -{ -public: - QSGD3D12ShaderEffectMaterial(QSGD3D12ShaderEffectNode *node); - ~QSGD3D12ShaderEffectMaterial(); - - QSGMaterialType *type() const override; - int compare(const QSGMaterial *other) const override; - - int constantBufferSize() const override; - void preparePipeline(QSGD3D12PipelineState *pipelineState) override; - UpdateResults updatePipeline(const QSGD3D12MaterialRenderState &state, - QSGD3D12PipelineState *pipelineState, - ExtraState *extraState, - quint8 *constantBuffer) override; - - void updateTextureProviders(bool layoutChange); - - QSGD3D12ShaderEffectNode *node; - bool valid = false; - QSGShaderEffectNode::CullMode cullMode = QSGShaderEffectNode::NoCulling; - bool hasCustomVertexShader = false; - bool hasCustomFragmentShader = false; - QSGD3D12ShaderLinker linker; - QSGMaterialType *mtype = nullptr; - QVector textureProviders; - QSGD3D12Texture *dummy = nullptr; - bool geometryUsesTextureSubRect = false; -}; - -class QSGD3D12ShaderEffectNode : public QObject, public QSGShaderEffectNode -{ - Q_OBJECT - -public: - QSGD3D12ShaderEffectNode(QSGD3D12RenderContext *rc, QSGD3D12GuiThreadShaderEffectManager *mgr); - - QRectF updateNormalizedTextureSubRect(bool supportsAtlasTextures) override; - void syncMaterial(SyncData *syncData) override; - - static void cleanupMaterialTypeCache(); - - void preprocess() override; - - QSGD3D12RenderContext *renderContext() { return m_rc; } - -private Q_SLOTS: - void handleTextureChange(); - void handleTextureProviderDestroyed(QObject *object); - -private: - QSGD3D12RenderContext *m_rc; - QSGD3D12GuiThreadShaderEffectManager *m_mgr; - QSGD3D12ShaderEffectMaterial m_material; -}; - -class QSGD3D12GuiThreadShaderEffectManager : public QSGGuiThreadShaderEffectManager -{ -public: - bool hasSeparateSamplerAndTextureObjects() const override; - - QString log() const override; - Status status() const override; - - void prepareShaderCode(ShaderInfo::Type typeHint, const QByteArray &src, ShaderInfo *result) override; - -private: - bool reflect(ShaderInfo *result); - QString m_log; - Status m_status = Uncompiled; - QFileSelector *m_fileSelector = nullptr; - - friend class QSGD3D12ShaderCompileTask; -}; - -QT_END_NAMESPACE - -#endif // QSGD3D12SHADEREFFECTNODE_P_H diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12spritenode.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12spritenode.cpp deleted file mode 100644 index 807fbcdcec..0000000000 --- a/src/plugins/scenegraph/d3d12/qsgd3d12spritenode.cpp +++ /dev/null @@ -1,314 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include "qsgd3d12spritenode_p.h" -#include "qsgd3d12material_p.h" - -#include "vs_sprite.hlslh" -#include "ps_sprite.hlslh" - -QT_BEGIN_NAMESPACE - -struct SpriteVertex -{ - float x; - float y; - float tx; - float ty; -}; - -struct SpriteVertices -{ - SpriteVertex v1; - SpriteVertex v2; - SpriteVertex v3; - SpriteVertex v4; -}; - -class QSGD3D12SpriteMaterial : public QSGD3D12Material -{ -public: - QSGD3D12SpriteMaterial(); - ~QSGD3D12SpriteMaterial(); - - QSGMaterialType *type() const override { static QSGMaterialType type; return &type; } - - int compare(const QSGMaterial *other) const override - { - return this - static_cast(other); - } - - int constantBufferSize() const override; - void preparePipeline(QSGD3D12PipelineState *pipelineState) override; - UpdateResults updatePipeline(const QSGD3D12MaterialRenderState &state, - QSGD3D12PipelineState *pipelineState, - ExtraState *extraState, - quint8 *constantBuffer) override; - - QSGTexture *texture; - - float animT; - float animX1; - float animY1; - float animX2; - float animY2; - float animW; - float animH; -}; - -QSGD3D12SpriteMaterial::QSGD3D12SpriteMaterial() - : texture(nullptr), - animT(0.0f), - animX1(0.0f), - animY1(0.0f), - animX2(0.0f), - animY2(0.0f), - animW(1.0f), - animH(1.0f) -{ - setFlag(Blending, true); -} - -QSGD3D12SpriteMaterial::~QSGD3D12SpriteMaterial() -{ - delete texture; -} - -static const int SPRITE_CB_SIZE_0 = 16 * sizeof(float); // float4x4 -static const int SPRITE_CB_SIZE_1 = 4 * sizeof(float); // float4 -static const int SPRITE_CB_SIZE_2 = 3 * sizeof(float); // float3 -static const int SPRITE_CB_SIZE_3 = sizeof(float); // float -static const int SPRITE_CB_SIZE = SPRITE_CB_SIZE_0 + SPRITE_CB_SIZE_1 + SPRITE_CB_SIZE_2 + SPRITE_CB_SIZE_3; - -int QSGD3D12SpriteMaterial::constantBufferSize() const -{ - return QSGD3D12Engine::alignedConstantBufferSize(SPRITE_CB_SIZE); -} - -void QSGD3D12SpriteMaterial::preparePipeline(QSGD3D12PipelineState *pipelineState) -{ - pipelineState->shaders.vs = g_VS_Sprite; - pipelineState->shaders.vsSize = sizeof(g_VS_Sprite); - pipelineState->shaders.ps = g_PS_Sprite; - pipelineState->shaders.psSize = sizeof(g_PS_Sprite); - - pipelineState->shaders.rootSig.textureViewCount = 1; -} - -QSGD3D12Material::UpdateResults QSGD3D12SpriteMaterial::updatePipeline(const QSGD3D12MaterialRenderState &state, - QSGD3D12PipelineState *, - ExtraState *, - quint8 *constantBuffer) -{ - QSGD3D12Material::UpdateResults r = UpdatedConstantBuffer; - quint8 *p = constantBuffer; - - if (state.isMatrixDirty()) - memcpy(p, state.combinedMatrix().constData(), SPRITE_CB_SIZE_0); - p += SPRITE_CB_SIZE_0; - - { - const float v[] = { animX1, animY1, animX2, animY2 }; - memcpy(p, v, SPRITE_CB_SIZE_1); - } - p += SPRITE_CB_SIZE_1; - - { - const float v[] = { animW, animH, animT }; - memcpy(p, v, SPRITE_CB_SIZE_2); - } - p += SPRITE_CB_SIZE_2; - - if (state.isOpacityDirty()) { - const float opacity = state.opacity(); - memcpy(p, &opacity, SPRITE_CB_SIZE_3); - } - - texture->bind(); - - return r; -} - -static QSGGeometry::Attribute Sprite_Attributes[] = { - QSGGeometry::Attribute::createWithAttributeType(0, 2, QSGGeometry::FloatType, QSGGeometry::PositionAttribute), - QSGGeometry::Attribute::createWithAttributeType(1, 2, QSGGeometry::FloatType, QSGGeometry::TexCoordAttribute), -}; - -static QSGGeometry::AttributeSet Sprite_AttributeSet = { 2, 4 * sizeof(float), Sprite_Attributes }; - -QSGD3D12SpriteNode::QSGD3D12SpriteNode() - : m_material(new QSGD3D12SpriteMaterial) - , m_geometryDirty(true) - , m_sheetSize(QSize(64, 64)) -{ - m_geometry = new QSGGeometry(Sprite_AttributeSet, 4, 6); - m_geometry->setDrawingMode(QSGGeometry::DrawTriangles); - - quint16 *indices = m_geometry->indexDataAsUShort(); - indices[0] = 0; - indices[1] = 1; - indices[2] = 2; - indices[3] = 1; - indices[4] = 3; - indices[5] = 2; - - setGeometry(m_geometry); - setMaterial(m_material); - setFlag(OwnsGeometry, true); - setFlag(OwnsMaterial, true); -} - -void QSGD3D12SpriteNode::setTexture(QSGTexture *texture) -{ - m_material->texture = texture; - m_geometryDirty = true; - markDirty(DirtyMaterial); -} - -void QSGD3D12SpriteNode::setTime(float time) -{ - m_material->animT = time; - markDirty(DirtyMaterial); -} - -void QSGD3D12SpriteNode::setSourceA(const QPoint &source) -{ - if (m_sourceA != source) { - m_sourceA = source; - m_material->animX1 = static_cast(source.x()) / m_sheetSize.width(); - m_material->animY1 = static_cast(source.y()) / m_sheetSize.height(); - markDirty(DirtyMaterial); - } -} - -void QSGD3D12SpriteNode::setSourceB(const QPoint &source) -{ - if (m_sourceB != source) { - m_sourceB = source; - m_material->animX2 = static_cast(source.x()) / m_sheetSize.width(); - m_material->animY2 = static_cast(source.y()) / m_sheetSize.height(); - markDirty(DirtyMaterial); - } -} - -void QSGD3D12SpriteNode::setSpriteSize(const QSize &size) -{ - if (m_spriteSize != size) { - m_spriteSize = size; - m_material->animW = static_cast(size.width()) / m_sheetSize.width(); - m_material->animH = static_cast(size.height()) / m_sheetSize.height(); - markDirty(DirtyMaterial); - } -} - -void QSGD3D12SpriteNode::setSheetSize(const QSize &size) -{ - if (m_sheetSize != size) { - m_sheetSize = size; - - // Update all dependent properties - m_material->animX1 = static_cast(m_sourceA.x()) / m_sheetSize.width(); - m_material->animY1 = static_cast(m_sourceA.y()) / m_sheetSize.height(); - m_material->animX2 = static_cast(m_sourceB.x()) / m_sheetSize.width(); - m_material->animY2 = static_cast(m_sourceB.y()) / m_sheetSize.height(); - m_material->animW = static_cast(m_spriteSize.width()) / m_sheetSize.width(); - m_material->animH = static_cast(m_spriteSize.height()) / m_sheetSize.height(); - - markDirty(DirtyMaterial); - } -} - -void QSGD3D12SpriteNode::setSize(const QSizeF &size) -{ - if (m_size != size) { - m_size = size; - m_geometryDirty = true; - } -} - -void QSGD3D12SpriteNode::setFiltering(QSGTexture::Filtering filtering) -{ - m_material->texture->setFiltering(filtering); - markDirty(DirtyMaterial); -} - -void QSGD3D12SpriteNode::update() -{ - if (m_geometryDirty) { - m_geometryDirty = false; - updateGeometry(); - } -} - -void QSGD3D12SpriteNode::updateGeometry() -{ - if (!m_material->texture) - return; - - SpriteVertices *p = static_cast(m_geometry->vertexData()); - const QRectF texRect = m_material->texture->normalizedTextureSubRect(); - - p->v1.tx = texRect.topLeft().x(); - p->v1.ty = texRect.topLeft().y(); - - p->v2.tx = texRect.topRight().x(); - p->v2.ty = texRect.topRight().y(); - - p->v3.tx = texRect.bottomLeft().x(); - p->v3.ty = texRect.bottomLeft().y(); - - p->v4.tx = texRect.bottomRight().x(); - p->v4.ty = texRect.bottomRight().y(); - - p->v1.x = 0; - p->v1.y = 0; - - p->v2.x = m_size.width(); - p->v2.y = 0; - - p->v3.x = 0; - p->v3.y = m_size.height(); - - p->v4.x = m_size.width(); - p->v4.y = m_size.height(); - - markDirty(DirtyGeometry); -} - -QT_END_NAMESPACE diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12spritenode_p.h b/src/plugins/scenegraph/d3d12/qsgd3d12spritenode_p.h deleted file mode 100644 index 265bec7c78..0000000000 --- a/src/plugins/scenegraph/d3d12/qsgd3d12spritenode_p.h +++ /dev/null @@ -1,90 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#ifndef QSGD3D12SPRITENODE_H -#define QSGD3D12SPRITENODE_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include - -QT_BEGIN_NAMESPACE - -class QSGD3D12SpriteMaterial; - -class QSGD3D12SpriteNode : public QSGSpriteNode -{ -public: - QSGD3D12SpriteNode(); - - void setTexture(QSGTexture *texture) override; - void setTime(float time) override; - void setSourceA(const QPoint &source) override; - void setSourceB(const QPoint &source) override; - void setSpriteSize(const QSize &size) override; - void setSheetSize(const QSize &size) override; - void setSize(const QSizeF &size) override; - void setFiltering(QSGTexture::Filtering filtering) override; - void update() override; - -private: - void updateGeometry(); - - QSGD3D12SpriteMaterial *m_material; - QSGGeometry *m_geometry; - bool m_geometryDirty; - QPoint m_sourceA; - QPoint m_sourceB; - QSize m_spriteSize; - QSize m_sheetSize; - QSizeF m_size; -}; - -QT_END_NAMESPACE - -#endif // QSGD3D12SPRITENODE_H diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12texture.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12texture.cpp deleted file mode 100644 index b49b851c23..0000000000 --- a/src/plugins/scenegraph/d3d12/qsgd3d12texture.cpp +++ /dev/null @@ -1,157 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include "qsgd3d12texture_p.h" -#include "qsgd3d12engine_p.h" -#include - -QT_BEGIN_NAMESPACE - -#define RETAIN_IMAGE - -void QSGD3D12Texture::create(const QImage &image, uint flags) -{ - // ### atlas? - - const bool alphaRequest = flags & QSGRenderContext::CreateTexture_Alpha; - m_alphaWanted = alphaRequest && image.hasAlphaChannel(); - - // The engine maps 8-bit formats to R8. This is fine for glyphs and such - // but may not be what apps expect for ordinary image data. The OpenGL - // implementation maps these to ARGB32_Pre so let's follow suit. - if (image.depth() != 8) - m_image = image; - else - m_image = image.convertToFormat(m_alphaWanted ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32); - - m_id = m_engine->genTexture(); - Q_ASSERT(m_id); - - // We could kick off the texture creation and the async upload right here. - // Unfortunately we cannot tell at this stage if mipmaps will be enabled - // via an Image element's mipmap property...so defer to bind(). - m_createPending = true; -} - -QSGD3D12Texture::QSGD3D12Texture(QSGD3D12Engine *engine) - : QSGTexture(*(new QSGD3D12TexturePrivate)), - m_engine(engine) -{ -} - -QSGD3D12Texture::~QSGD3D12Texture() -{ - if (m_id) - m_engine->releaseTexture(m_id); -} - -int QSGD3D12Texture::textureId() const -{ - return m_id; -} - -int QSGD3D12TexturePrivate::comparisonKey() const -{ - Q_Q(const QSGD3D12Texture); - return q->m_id; -} - -QSize QSGD3D12Texture::textureSize() const -{ - return m_image.size(); -} - -bool QSGD3D12Texture::hasAlphaChannel() const -{ - return m_alphaWanted; -} - -bool QSGD3D12Texture::hasMipmaps() const -{ - return mipmapFiltering() != QSGTexture::None; -} - -QRectF QSGD3D12Texture::normalizedTextureSubRect() const -{ - return QRectF(0, 0, 1, 1); -} - -void QSGD3D12Texture::bind() -{ - // Called when the texture material updates the pipeline state. - - if (!m_createPending && hasMipmaps() != m_createdWithMipMaps) { -#ifdef RETAIN_IMAGE - m_engine->releaseTexture(m_id); - m_id = m_engine->genTexture(); - Q_ASSERT(m_id); - m_createPending = true; -#else - // ### this can be made working some day (something similar to - // queueTextureResize) but skip for now - qWarning("D3D12: mipmap property cannot be changed once the texture is created"); -#endif - } - - if (m_createPending) { - m_createPending = false; - - QSGD3D12Engine::TextureCreateFlags createFlags = 0; - if (m_alphaWanted) - createFlags |= QSGD3D12Engine::TextureWithAlpha; - - m_createdWithMipMaps = hasMipmaps(); - if (m_createdWithMipMaps) - createFlags |= QSGD3D12Engine::TextureWithMipMaps; - - m_engine->createTexture(m_id, m_image.size(), m_image.format(), createFlags); - m_engine->queueTextureUpload(m_id, m_image); - -#ifndef RETAIN_IMAGE - m_image = QImage(); -#endif - } - - // Here we know that the texture is going to be used in the current frame - // by the next draw call. Notify the engine so that it can wait for - // possible pending uploads and set up the pipeline accordingly. - m_engine->useTexture(m_id); -} - -QT_END_NAMESPACE diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12texture_p.h b/src/plugins/scenegraph/d3d12/qsgd3d12texture_p.h deleted file mode 100644 index f6a5257773..0000000000 --- a/src/plugins/scenegraph/d3d12/qsgd3d12texture_p.h +++ /dev/null @@ -1,96 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#ifndef QSGD3D12TEXTURE_P_H -#define QSGD3D12TEXTURE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include -#include - -QT_BEGIN_NAMESPACE - -class QSGD3D12Engine; -class QSGD3D12TexturePrivate; - -class QSGD3D12Texture : public QSGTexture -{ - Q_DECLARE_PRIVATE(QSGD3D12Texture) -public: - QSGD3D12Texture(QSGD3D12Engine *engine); - ~QSGD3D12Texture(); - - void create(const QImage &image, uint flags); - - int textureId() const override; - QSize textureSize() const override; - bool hasAlphaChannel() const override; - bool hasMipmaps() const override; - QRectF normalizedTextureSubRect() const override; - void bind() override; - -protected: - QSGD3D12Engine *m_engine; - QImage m_image; - bool m_createPending = false; - bool m_createdWithMipMaps = false; - uint m_id = 0; - bool m_alphaWanted = false; -}; - -class QSGD3D12TexturePrivate : public QSGTexturePrivate -{ - Q_DECLARE_PUBLIC(QSGD3D12Texture) -public: - int comparisonKey() const override; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12threadedrenderloop.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12threadedrenderloop.cpp deleted file mode 100644 index 91a35627ea..0000000000 --- a/src/plugins/scenegraph/d3d12/qsgd3d12threadedrenderloop.cpp +++ /dev/null @@ -1,1208 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include "qsgd3d12threadedrenderloop_p.h" -#include "qsgd3d12engine_p.h" -#include "qsgd3d12context_p.h" -#include "qsgd3d12rendercontext_p.h" -#include "qsgd3d12shadereffectnode_p.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -QT_BEGIN_NAMESPACE - -// NOTE: Avoid categorized logging. It is slow. - -#define DECLARE_DEBUG_VAR(variable) \ - static bool debug_ ## variable() \ - { static bool value = qgetenv("QSG_RENDERER_DEBUG").contains(QT_STRINGIFY(variable)); return value; } - -DECLARE_DEBUG_VAR(loop) -DECLARE_DEBUG_VAR(time) - - -// NOTE: The threaded renderloop is not currently safe to use in practice as it -// is prone to deadlocks, in particular when multiple windows are active. This -// is because DXGI's limitation of relying on the gui message pump in certain -// cases. See -// https://msdn.microsoft.com/en-us/library/windows/desktop/ee417025(v=vs.85).aspx#multithreading_and_dxgi -// -// This means that if swap chain functions like create, release, and -// potentially even Present, are called outside the gui thread, then the -// application must ensure the gui thread does not ever block and wait for the -// render thread - since on the render thread a DXGI call may be in turn -// waiting for the gui thread to deliver a window message... -// -// Ensuring this is impossible with the current design where the gui thread -// must block at certain points, waiting for the render thread. Qt moves out -// rendering from the main thread, in order to make application's life easier, -// whereas the typical DXGI-compatible model would require moving work, but not -// windowing and presenting, out to additional threads. - - -/* - The D3D render loop mostly mirrors the threaded OpenGL render loop. - - There are two classes here. QSGD3D12ThreadedRenderLoop and - QSGD3D12RenderThread. All communication between the two is based on event - passing and we have a number of custom events. - - Render loop is per process, render thread is per window. The - QSGD3D12RenderContext and QSGD3D12Engine are per window as well. The former - is created (but not owned) by QQuickWindow. The D3D device is per process. - - In this implementation, the render thread is never blocked and the GUI - thread will initiate a polishAndSync which will block and wait for the - render thread to pick it up and release the block only after the render - thread is done syncing. The reason for this is: - - 1. Clear blocking paradigm. We only have one real "block" point - (polishAndSync()) and all blocking is initiated by GUI and picked up by - Render at specific times based on events. This makes the execution - deterministic. - - 2. Render does not have to interact with GUI. This is done so that the - render thread can run its own animation system which stays alive even when - the GUI thread is blocked doing I/O, object instantiation, QPainter-painting - or any other non-trivial task. - - The render thread has affinity to the GUI thread until a window is shown. - From that moment and until the window is destroyed, it will have affinity to - the render thread. (moved back at the end of run for cleanup). - */ - -// Passed from the RL to the RT when a window is removed obscured and should be -// removed from the render loop. -const QEvent::Type WM_Obscure = QEvent::Type(QEvent::User + 1); - -// Passed from the RL to RT when GUI has been locked, waiting for sync. -const QEvent::Type WM_RequestSync = QEvent::Type(QEvent::User + 2); - -// Passed by the RL to the RT to maybe release resource if no windows are -// rendering. -const QEvent::Type WM_TryRelease = QEvent::Type(QEvent::User + 4); - -// Passed by the RL to the RT when a QQuickWindow::grabWindow() is called. -const QEvent::Type WM_Grab = QEvent::Type(QEvent::User + 5); - -// Passed by the window when there is a render job to run. -const QEvent::Type WM_PostJob = QEvent::Type(QEvent::User + 6); - -class QSGD3D12WindowEvent : public QEvent -{ -public: - QSGD3D12WindowEvent(QQuickWindow *c, QEvent::Type type) : QEvent(type), window(c) { } - QQuickWindow *window; -}; - -class QSGD3D12TryReleaseEvent : public QSGD3D12WindowEvent -{ -public: - QSGD3D12TryReleaseEvent(QQuickWindow *win, bool destroy) - : QSGD3D12WindowEvent(win, WM_TryRelease), destroying(destroy) { } - bool destroying; -}; - -class QSGD3D12SyncEvent : public QSGD3D12WindowEvent -{ -public: - QSGD3D12SyncEvent(QQuickWindow *c, bool inExpose, bool force) - : QSGD3D12WindowEvent(c, WM_RequestSync) - , size(c->size()) - , dpr(c->effectiveDevicePixelRatio()) - , syncInExpose(inExpose) - , forceRenderPass(force) { } - QSize size; - float dpr; - bool syncInExpose; - bool forceRenderPass; -}; - -class QSGD3D12GrabEvent : public QSGD3D12WindowEvent -{ -public: - QSGD3D12GrabEvent(QQuickWindow *c, QImage *result) - : QSGD3D12WindowEvent(c, WM_Grab), image(result) { } - QImage *image; -}; - -class QSGD3D12JobEvent : public QSGD3D12WindowEvent -{ -public: - QSGD3D12JobEvent(QQuickWindow *c, QRunnable *postedJob) - : QSGD3D12WindowEvent(c, WM_PostJob), job(postedJob) { } - ~QSGD3D12JobEvent() { delete job; } - QRunnable *job; -}; - -class QSGD3D12EventQueue : public QQueue -{ -public: - void addEvent(QEvent *e) { - mutex.lock(); - enqueue(e); - if (waiting) - condition.wakeOne(); - mutex.unlock(); - } - - QEvent *takeEvent(bool wait) { - mutex.lock(); - if (isEmpty() && wait) { - waiting = true; - condition.wait(&mutex); - waiting = false; - } - QEvent *e = dequeue(); - mutex.unlock(); - return e; - } - - bool hasMoreEvents() { - mutex.lock(); - bool has = !isEmpty(); - mutex.unlock(); - return has; - } - -private: - QMutex mutex; - QWaitCondition condition; - bool waiting = false; -}; - -static inline int qsgrl_animation_interval() -{ - const qreal refreshRate = QGuiApplication::primaryScreen() ? QGuiApplication::primaryScreen()->refreshRate() : 0; - return refreshRate < 1 ? 16 : int(1000 / refreshRate); -} - -class QSGD3D12RenderThread : public QThread -{ - Q_OBJECT - -public: - QSGD3D12RenderThread(QSGD3D12ThreadedRenderLoop *rl, QSGRenderContext *renderContext) - : renderLoop(rl) - { - rc = static_cast(renderContext); - vsyncDelta = qsgrl_animation_interval(); - } - - ~QSGD3D12RenderThread() - { - delete rc; - } - - bool event(QEvent *e); - void run(); - - void syncAndRender(); - void sync(bool inExpose); - - void requestRepaint() - { - if (sleeping) - stopEventProcessing = true; - if (exposedWindow) - pendingUpdate |= RepaintRequest; - } - - void processEventsAndWaitForMore(); - void processEvents(); - void postEvent(QEvent *e); - - enum UpdateRequest { - SyncRequest = 0x01, - RepaintRequest = 0x02, - ExposeRequest = 0x04 | RepaintRequest | SyncRequest - }; - - QSGD3D12Engine *engine = nullptr; - QSGD3D12ThreadedRenderLoop *renderLoop; - QSGD3D12RenderContext *rc; - QAnimationDriver *rtAnim = nullptr; - volatile bool active = false; - uint pendingUpdate = 0; - bool sleeping = false; - bool syncResultedInChanges = false; - float vsyncDelta; - QMutex mutex; - QWaitCondition waitCondition; - QQuickWindow *exposedWindow = nullptr; - bool stopEventProcessing = false; - QSGD3D12EventQueue eventQueue; - QElapsedTimer threadTimer; - qint64 syncTime; - qint64 renderTime; - qint64 sinceLastTime; - -public slots: - void onSceneGraphChanged() { - syncResultedInChanges = true; - } -}; - -bool QSGD3D12RenderThread::event(QEvent *e) -{ - switch (e->type()) { - - case WM_Obscure: - Q_ASSERT(!exposedWindow || exposedWindow == static_cast(e)->window); - if (Q_UNLIKELY(debug_loop())) - qDebug() << "RT - WM_Obscure" << exposedWindow; - mutex.lock(); - if (exposedWindow) { - QQuickWindowPrivate::get(exposedWindow)->fireAboutToStop(); - if (Q_UNLIKELY(debug_loop())) - qDebug("RT - WM_Obscure - window removed"); - exposedWindow = nullptr; - } - waitCondition.wakeOne(); - mutex.unlock(); - return true; - - case WM_RequestSync: { - QSGD3D12SyncEvent *wme = static_cast(e); - if (sleeping) - stopEventProcessing = true; - // One thread+engine for each window. However, the native window may - // change in some (quite artificial) cases, e.g. due to a hide - - // destroy - show on the QWindow. - bool needsWindow = !engine->window(); - if (engine->window() && engine->window() != wme->window->winId()) { - if (Q_UNLIKELY(debug_loop())) - qDebug("RT - WM_RequestSync - native window handle changes for active engine"); - engine->waitGPU(); - QQuickWindowPrivate::get(wme->window)->cleanupNodesOnShutdown(); - QSGD3D12ShaderEffectNode::cleanupMaterialTypeCache(); - rc->invalidate(); - engine->releaseResources(); - needsWindow = true; - } - if (needsWindow) { - // Must only ever get here when there is no window or releaseResources() has been called. - const int samples = wme->window->format().samples(); - const bool alpha = wme->window->format().alphaBufferSize() > 0; - if (Q_UNLIKELY(debug_loop())) - qDebug() << "RT - WM_RequestSync - initializing D3D12 engine" << wme->window - << wme->size << wme->dpr << samples << alpha; - engine->attachToWindow(wme->window->winId(), wme->size, wme->dpr, samples, alpha); - } - exposedWindow = wme->window; - engine->setWindowSize(wme->size, wme->dpr); - if (Q_UNLIKELY(debug_loop())) - qDebug() << "RT - WM_RequestSync" << exposedWindow; - pendingUpdate |= SyncRequest; - if (wme->syncInExpose) { - if (Q_UNLIKELY(debug_loop())) - qDebug("RT - WM_RequestSync - triggered from expose"); - pendingUpdate |= ExposeRequest; - } - if (wme->forceRenderPass) { - if (Q_UNLIKELY(debug_loop())) - qDebug("RT - WM_RequestSync - repaint regardless"); - pendingUpdate |= RepaintRequest; - } - return true; - } - - case WM_TryRelease: { - if (Q_UNLIKELY(debug_loop())) - qDebug("RT - WM_TryRelease"); - mutex.lock(); - renderLoop->lockedForSync = true; - QSGD3D12TryReleaseEvent *wme = static_cast(e); - // Only when no windows are exposed anymore or we are shutting down. - if (!exposedWindow || wme->destroying) { - if (Q_UNLIKELY(debug_loop())) - qDebug("RT - WM_TryRelease - invalidating rc"); - if (wme->window) { - QQuickWindowPrivate *wd = QQuickWindowPrivate::get(wme->window); - if (wme->destroying) { - // QSGNode destruction may release graphics resources in use so wait first. - engine->waitGPU(); - // Bye bye nodes... - wd->cleanupNodesOnShutdown(); - QSGD3D12ShaderEffectNode::cleanupMaterialTypeCache(); - } - rc->invalidate(); - QCoreApplication::processEvents(); - QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); - if (wme->destroying) - wd->animationController.reset(); - } - if (wme->destroying) - active = false; - if (sleeping) - stopEventProcessing = true; - } else { - if (Q_UNLIKELY(debug_loop())) - qDebug("RT - WM_TryRelease - not releasing because window is still active"); - } - waitCondition.wakeOne(); - renderLoop->lockedForSync = false; - mutex.unlock(); - return true; - } - - case WM_Grab: { - if (Q_UNLIKELY(debug_loop())) - qDebug("RT - WM_Grab"); - QSGD3D12GrabEvent *wme = static_cast(e); - Q_ASSERT(wme->window); - Q_ASSERT(wme->window == exposedWindow || !exposedWindow); - mutex.lock(); - if (wme->window) { - // Grabbing is generally done by rendering a frame and reading the - // color buffer contents back, without presenting, and then - // creating a QImage from the returned data. It is terribly - // inefficient since it involves a full blocking wait for the GPU. - // However, our hands are tied by the existing, synchronous APIs of - // QQuickWindow and such. - QQuickWindowPrivate *wd = QQuickWindowPrivate::get(wme->window); - rc->initialize(nullptr); - wd->syncSceneGraph(); - rc->endSync(); - wd->renderSceneGraph(wme->window->size()); - *wme->image = engine->executeAndWaitReadbackRenderTarget(); - } - if (Q_UNLIKELY(debug_loop())) - qDebug("RT - WM_Grab - waking gui to handle result"); - waitCondition.wakeOne(); - mutex.unlock(); - return true; - } - - case WM_PostJob: { - if (Q_UNLIKELY(debug_loop())) - qDebug("RT - WM_PostJob"); - QSGD3D12JobEvent *wme = static_cast(e); - Q_ASSERT(wme->window == exposedWindow); - if (exposedWindow) { - wme->job->run(); - delete wme->job; - wme->job = nullptr; - if (Q_UNLIKELY(debug_loop())) - qDebug("RT - WM_PostJob - job done"); - } - return true; - } - - default: - break; - } - - return QThread::event(e); -} - -void QSGD3D12RenderThread::postEvent(QEvent *e) -{ - eventQueue.addEvent(e); -} - -void QSGD3D12RenderThread::processEvents() -{ - while (eventQueue.hasMoreEvents()) { - QEvent *e = eventQueue.takeEvent(false); - event(e); - delete e; - } -} - -void QSGD3D12RenderThread::processEventsAndWaitForMore() -{ - stopEventProcessing = false; - while (!stopEventProcessing) { - QEvent *e = eventQueue.takeEvent(true); - event(e); - delete e; - } -} - -void QSGD3D12RenderThread::run() -{ - if (Q_UNLIKELY(debug_loop())) - qDebug("RT - run()"); - - engine = new QSGD3D12Engine; - rc->setEngine(engine); - - rtAnim = rc->sceneGraphContext()->createAnimationDriver(nullptr); - rtAnim->install(); - - if (QQmlDebugConnector::service()) - QQuickProfiler::registerAnimationCallback(); - - while (active) { - if (exposedWindow) - syncAndRender(); - - processEvents(); - QCoreApplication::processEvents(); - - if (pendingUpdate == 0 || !exposedWindow) { - if (Q_UNLIKELY(debug_loop())) - qDebug("RT - done drawing, sleep"); - sleeping = true; - processEventsAndWaitForMore(); - sleeping = false; - } - } - - if (Q_UNLIKELY(debug_loop())) - qDebug("RT - run() exiting"); - - delete rtAnim; - rtAnim = nullptr; - - rc->moveToThread(renderLoop->thread()); - moveToThread(renderLoop->thread()); - - rc->setEngine(nullptr); - delete engine; - engine = nullptr; -} - -void QSGD3D12RenderThread::sync(bool inExpose) -{ - if (Q_UNLIKELY(debug_loop())) - qDebug("RT - sync"); - - mutex.lock(); - Q_ASSERT_X(renderLoop->lockedForSync, "QSGD3D12RenderThread::sync()", "sync triggered with gui not locked"); - - // Recover from device loss. - if (!engine->hasResources()) { - if (Q_UNLIKELY(debug_loop())) - qDebug("RT - sync - device was lost, resetting scenegraph"); - QQuickWindowPrivate::get(exposedWindow)->cleanupNodesOnShutdown(); - QSGD3D12ShaderEffectNode::cleanupMaterialTypeCache(); - rc->invalidate(); - } - - if (engine->window()) { - QQuickWindowPrivate *wd = QQuickWindowPrivate::get(exposedWindow); - bool hadRenderer = wd->renderer != nullptr; - // If the scene graph was touched since the last sync() make sure it sends the - // changed signal. - if (wd->renderer) - wd->renderer->clearChangedFlag(); - - rc->initialize(nullptr); - wd->syncSceneGraph(); - rc->endSync(); - - if (!hadRenderer && wd->renderer) { - if (Q_UNLIKELY(debug_loop())) - qDebug("RT - created renderer"); - syncResultedInChanges = true; - connect(wd->renderer, &QSGRenderer::sceneGraphChanged, this, - &QSGD3D12RenderThread::onSceneGraphChanged, Qt::DirectConnection); - } - - // Process deferred deletes now, directly after the sync as deleteLater - // on the GUI must now also have resulted in SG changes and the delete - // is a safe operation. - QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); - } - - if (!inExpose) { - if (Q_UNLIKELY(debug_loop())) - qDebug("RT - sync complete, waking gui"); - waitCondition.wakeOne(); - mutex.unlock(); - } -} - -void QSGD3D12RenderThread::syncAndRender() -{ - Q_TRACE_SCOPE(QSG_syncAndRender); - if (Q_UNLIKELY(debug_time())) { - sinceLastTime = threadTimer.nsecsElapsed(); - threadTimer.start(); - } - Q_QUICK_SG_PROFILE_START(QQuickProfiler::SceneGraphRenderLoopFrame); - Q_TRACE(QSG_sync_entry); - - QElapsedTimer waitTimer; - waitTimer.start(); - - if (Q_UNLIKELY(debug_loop())) - qDebug("RT - syncAndRender()"); - - syncResultedInChanges = false; - QQuickWindowPrivate *wd = QQuickWindowPrivate::get(exposedWindow); - - const bool repaintRequested = (pendingUpdate & RepaintRequest) || wd->customRenderStage; - const bool syncRequested = pendingUpdate & SyncRequest; - const bool exposeRequested = (pendingUpdate & ExposeRequest) == ExposeRequest; - pendingUpdate = 0; - - if (syncRequested) - sync(exposeRequested); - -#ifndef QSG_NO_RENDER_TIMING - if (Q_UNLIKELY(debug_time())) - syncTime = threadTimer.nsecsElapsed(); -#endif - Q_TRACE(QSG_sync_exit); - Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame, - QQuickProfiler::SceneGraphRenderLoopSync); - - if (!syncResultedInChanges && !repaintRequested) { - if (Q_UNLIKELY(debug_loop())) - qDebug("RT - no changes, render aborted"); - int waitTime = vsyncDelta - (int) waitTimer.elapsed(); - if (waitTime > 0) - msleep(waitTime); - return; - } - Q_TRACE(QSG_render_entry); - - if (Q_UNLIKELY(debug_loop())) - qDebug("RT - rendering started"); - - if (rtAnim->isRunning()) { - wd->animationController->lock(); - rtAnim->advance(); - wd->animationController->unlock(); - } - - bool canRender = wd->renderer != nullptr; - // Recover from device loss. - if (!engine->hasResources()) { - if (Q_UNLIKELY(debug_loop())) - qDebug("RT - syncAndRender - device was lost, posting FullUpdateRequest"); - // Cannot do anything here because gui is not locked. Request a new - // sync+render round on the gui thread and let the sync handle it. - QCoreApplication::postEvent(exposedWindow, new QEvent(QEvent::Type(QQuickWindowPrivate::FullUpdateRequest))); - canRender = false; - } - - if (canRender) { - wd->renderSceneGraph(engine->windowSize()); - if (Q_UNLIKELY(debug_time())) - renderTime = threadTimer.nsecsElapsed(); - Q_TRACE(QSG_render_exit); - Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame, - QQuickProfiler::SceneGraphRenderLoopRender); - Q_TRACE(QSG_swap_entry); - - // The engine is able to have multiple frames in flight. This in effect is - // similar to BufferQueueingOpenGL. Provide an env var to force the - // traditional blocking swap behavior, just in case. - static bool blockOnEachFrame = qEnvironmentVariableIntValue("QT_D3D_BLOCKING_PRESENT") != 0; - - if (!wd->customRenderStage || !wd->customRenderStage->swap()) - engine->present(); - - if (blockOnEachFrame) - engine->waitGPU(); - - // The concept of "frame swaps" is quite misleading by default, when - // blockOnEachFrame is not used, but emit it for compatibility. - wd->fireFrameSwapped(); - } else { - Q_TRACE(QSG_render_exit); - Q_QUICK_SG_PROFILE_SKIP(QQuickProfiler::SceneGraphRenderLoopFrame, - QQuickProfiler::SceneGraphRenderLoopSync, 1); - Q_TRACE(QSG_swap_entry); - if (Q_UNLIKELY(debug_loop())) - qDebug("RT - window not ready, skipping render"); - } - - if (Q_UNLIKELY(debug_loop())) - qDebug("RT - rendering done"); - - if (exposeRequested) { - if (Q_UNLIKELY(debug_loop())) - qDebug("RT - wake gui after initial expose"); - waitCondition.wakeOne(); - mutex.unlock(); - } - - if (Q_UNLIKELY(debug_time())) - qDebug("Frame rendered with 'd3d12' renderloop in %dms, sync=%d, render=%d, swap=%d - (on render thread)", - int(threadTimer.elapsed()), - int((syncTime/1000000)), - int((renderTime - syncTime) / 1000000), - int(threadTimer.elapsed() - renderTime / 1000000)); - - Q_TRACE(QSG_swap_exit); - Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphRenderLoopFrame, - QQuickProfiler::SceneGraphRenderLoopSwap); - - static int devLossTest = qEnvironmentVariableIntValue("QT_D3D_TEST_DEVICE_LOSS"); - if (devLossTest > 0) { - static QElapsedTimer kt; - static bool timerRunning = false; - if (!timerRunning) { - kt.start(); - timerRunning = true; - } else if (kt.elapsed() > 5000) { - --devLossTest; - kt.restart(); - engine->simulateDeviceLoss(); - } - } -} - -template T *windowFor(const QVector &list, QQuickWindow *window) -{ - for (const T &t : list) { - if (t.window == window) - return const_cast(&t); - } - return nullptr; -} - -QSGD3D12ThreadedRenderLoop::QSGD3D12ThreadedRenderLoop() -{ - if (Q_UNLIKELY(debug_loop())) - qDebug("d3d12 THREADED render loop ctor"); - - sg = new QSGD3D12Context; - - anim = sg->createAnimationDriver(this); - connect(anim, &QAnimationDriver::started, this, &QSGD3D12ThreadedRenderLoop::onAnimationStarted); - connect(anim, &QAnimationDriver::stopped, this, &QSGD3D12ThreadedRenderLoop::onAnimationStopped); - anim->install(); -} - -QSGD3D12ThreadedRenderLoop::~QSGD3D12ThreadedRenderLoop() -{ - if (Q_UNLIKELY(debug_loop())) - qDebug("d3d12 THREADED render loop dtor"); - - delete sg; -} - -void QSGD3D12ThreadedRenderLoop::show(QQuickWindow *window) -{ - if (Q_UNLIKELY(debug_loop())) - qDebug() << "show" << window; -} - -void QSGD3D12ThreadedRenderLoop::hide(QQuickWindow *window) -{ - if (Q_UNLIKELY(debug_loop())) - qDebug() << "hide" << window; - - if (window->isExposed()) - handleObscurity(windowFor(windows, window)); - - releaseResources(window); -} - -void QSGD3D12ThreadedRenderLoop::resize(QQuickWindow *window) -{ - if (!window->isExposed() || window->size().isEmpty()) - return; - - if (Q_UNLIKELY(debug_loop())) - qDebug() << "resize" << window << window->size(); -} - -void QSGD3D12ThreadedRenderLoop::windowDestroyed(QQuickWindow *window) -{ - if (Q_UNLIKELY(debug_loop())) - qDebug() << "window destroyed" << window; - - WindowData *w = windowFor(windows, window); - if (!w) - return; - - handleObscurity(w); - handleResourceRelease(w, true); - - QSGD3D12RenderThread *thread = w->thread; - while (thread->isRunning()) - QThread::yieldCurrentThread(); - - Q_ASSERT(thread->thread() == QThread::currentThread()); - delete thread; - - for (int i = 0; i < windows.size(); ++i) { - if (windows.at(i).window == window) { - windows.removeAt(i); - break; - } - } - - // Now that we altered the window list, we may need to stop the animation - // timer even if we didn't via handleObscurity. This covers the case where - // we destroy a visible & exposed QQuickWindow. - startOrStopAnimationTimer(); -} - -void QSGD3D12ThreadedRenderLoop::exposureChanged(QQuickWindow *window) -{ - if (Q_UNLIKELY(debug_loop())) - qDebug() << "exposure changed" << window; - - if (window->isExposed()) { - handleExposure(window); - } else { - WindowData *w = windowFor(windows, window); - if (w) - handleObscurity(w); - } -} - -QImage QSGD3D12ThreadedRenderLoop::grab(QQuickWindow *window) -{ - if (Q_UNLIKELY(debug_loop())) - qDebug() << "grab" << window; - - WindowData *w = windowFor(windows, window); - // Have to support invisible (but created()'ed) windows as well. - // Unlike with GL, leaving that case for QQuickWindow to handle is not feasible. - const bool tempExpose = !w; - if (tempExpose) { - handleExposure(window); - w = windowFor(windows, window); - Q_ASSERT(w); - } - - if (!w->thread->isRunning()) - return QImage(); - - if (!window->handle()) - window->create(); - - QQuickWindowPrivate *wd = QQuickWindowPrivate::get(window); - wd->polishItems(); - - QImage result; - w->thread->mutex.lock(); - lockedForSync = true; - w->thread->postEvent(new QSGD3D12GrabEvent(window, &result)); - w->thread->waitCondition.wait(&w->thread->mutex); - lockedForSync = false; - w->thread->mutex.unlock(); - - result.setDevicePixelRatio(window->effectiveDevicePixelRatio()); - - if (tempExpose) - handleObscurity(w); - - return result; -} - -void QSGD3D12ThreadedRenderLoop::update(QQuickWindow *window) -{ - WindowData *w = windowFor(windows, window); - if (!w) - return; - - if (w->thread == QThread::currentThread()) { - w->thread->requestRepaint(); - return; - } - - // We set forceRenderPass because we want to make sure the QQuickWindow - // actually does a full render pass after the next sync. - w->forceRenderPass = true; - scheduleUpdate(w); -} - -void QSGD3D12ThreadedRenderLoop::maybeUpdate(QQuickWindow *window) -{ - WindowData *w = windowFor(windows, window); - if (w) - scheduleUpdate(w); -} - -// called in response to window->requestUpdate() -void QSGD3D12ThreadedRenderLoop::handleUpdateRequest(QQuickWindow *window) -{ - if (Q_UNLIKELY(debug_loop())) - qDebug() << "handleUpdateRequest" << window; - - WindowData *w = windowFor(windows, window); - if (w) - polishAndSync(w, false); -} - -QAnimationDriver *QSGD3D12ThreadedRenderLoop::animationDriver() const -{ - return anim; -} - -QSGContext *QSGD3D12ThreadedRenderLoop::sceneGraphContext() const -{ - return sg; -} - -QSGRenderContext *QSGD3D12ThreadedRenderLoop::createRenderContext(QSGContext *) const -{ - return sg->createRenderContext(); -} - -void QSGD3D12ThreadedRenderLoop::releaseResources(QQuickWindow *window) -{ - if (Q_UNLIKELY(debug_loop())) - qDebug() << "releaseResources" << window; - - WindowData *w = windowFor(windows, window); - if (w) - handleResourceRelease(w, false); -} - -void QSGD3D12ThreadedRenderLoop::postJob(QQuickWindow *window, QRunnable *job) -{ - WindowData *w = windowFor(windows, window); - if (w && w->thread && w->thread->exposedWindow) - w->thread->postEvent(new QSGD3D12JobEvent(window, job)); - else - delete job; -} - -QSurface::SurfaceType QSGD3D12ThreadedRenderLoop::windowSurfaceType() const -{ - return QSurface::OpenGLSurface; -} - -bool QSGD3D12ThreadedRenderLoop::interleaveIncubation() const -{ - bool somethingVisible = false; - for (const WindowData &w : windows) { - if (w.window->isVisible() && w.window->isExposed()) { - somethingVisible = true; - break; - } - } - return somethingVisible && anim->isRunning(); -} - -int QSGD3D12ThreadedRenderLoop::flags() const -{ - return SupportsGrabWithoutExpose; -} - -bool QSGD3D12ThreadedRenderLoop::event(QEvent *e) -{ - if (e->type() == QEvent::Timer) { - QTimerEvent *te = static_cast(e); - if (te->timerId() == animationTimer) { - anim->advance(); - emit timeToIncubate(); - return true; - } - } - - return QObject::event(e); -} - -void QSGD3D12ThreadedRenderLoop::onAnimationStarted() -{ - startOrStopAnimationTimer(); - - for (const WindowData &w : qAsConst(windows)) - w.window->requestUpdate(); -} - -void QSGD3D12ThreadedRenderLoop::onAnimationStopped() -{ - startOrStopAnimationTimer(); -} - -void QSGD3D12ThreadedRenderLoop::startOrStopAnimationTimer() -{ - int exposedWindowCount = 0; - const WindowData *exposed = nullptr; - - for (int i = 0; i < windows.size(); ++i) { - const WindowData &w(windows[i]); - if (w.window->isVisible() && w.window->isExposed()) { - ++exposedWindowCount; - exposed = &w; - } - } - - if (animationTimer && (exposedWindowCount == 1 || !anim->isRunning())) { - killTimer(animationTimer); - animationTimer = 0; - // If animations are running, make sure we keep on animating - if (anim->isRunning()) - exposed->window->requestUpdate(); - } else if (!animationTimer && exposedWindowCount != 1 && anim->isRunning()) { - animationTimer = startTimer(qsgrl_animation_interval()); - } -} - -void QSGD3D12ThreadedRenderLoop::handleExposure(QQuickWindow *window) -{ - if (Q_UNLIKELY(debug_loop())) - qDebug() << "handleExposure" << window; - - WindowData *w = windowFor(windows, window); - if (!w) { - if (Q_UNLIKELY(debug_loop())) - qDebug("adding window to list"); - WindowData win; - win.window = window; - QSGRenderContext *rc = QQuickWindowPrivate::get(window)->context; // will transfer ownership - win.thread = new QSGD3D12RenderThread(this, rc); - win.updateDuringSync = false; - win.forceRenderPass = true; // also covered by polishAndSync(inExpose=true), but doesn't hurt - windows.append(win); - w = &windows.last(); - } - - // set this early as we'll be rendering shortly anyway and this avoids - // special casing exposure in polishAndSync. - w->thread->exposedWindow = window; - - if (w->window->size().isEmpty() - || (w->window->isTopLevel() && !w->window->geometry().intersects(w->window->screen()->availableGeometry()))) { -#ifndef QT_NO_DEBUG - qWarning().noquote().nospace() << "QSGD3D12ThreadedRenderLoop: expose event received for window " - << w->window << " with invalid geometry: " << w->window->geometry() - << " on " << w->window->screen(); -#endif - } - - if (!w->window->handle()) - w->window->create(); - - // Start render thread if it is not running - if (!w->thread->isRunning()) { - if (Q_UNLIKELY(debug_loop())) - qDebug("starting render thread"); - // Push a few things to the render thread. - QQuickAnimatorController *controller = QQuickWindowPrivate::get(w->window)->animationController.data(); - if (controller->thread() != w->thread) - controller->moveToThread(w->thread); - if (w->thread->thread() == QThread::currentThread()) { - w->thread->rc->moveToThread(w->thread); - w->thread->moveToThread(w->thread); - } - - w->thread->active = true; - w->thread->start(); - - if (!w->thread->isRunning()) - qFatal("Render thread failed to start, aborting application."); - } - - polishAndSync(w, true); - - startOrStopAnimationTimer(); -} - -void QSGD3D12ThreadedRenderLoop::handleObscurity(WindowData *w) -{ - if (Q_UNLIKELY(debug_loop())) - qDebug() << "handleObscurity" << w->window; - - if (w->thread->isRunning()) { - w->thread->mutex.lock(); - w->thread->postEvent(new QSGD3D12WindowEvent(w->window, WM_Obscure)); - w->thread->waitCondition.wait(&w->thread->mutex); - w->thread->mutex.unlock(); - } - - startOrStopAnimationTimer(); -} - -void QSGD3D12ThreadedRenderLoop::scheduleUpdate(WindowData *w) -{ - if (!QCoreApplication::instance()) - return; - - if (!w || !w->thread->isRunning()) - return; - - QThread *current = QThread::currentThread(); - if (current != QCoreApplication::instance()->thread() && (current != w->thread || !lockedForSync)) { - qWarning() << "Updates can only be scheduled from GUI thread or from QQuickItem::updatePaintNode()"; - return; - } - - if (current == w->thread) { - w->updateDuringSync = true; - return; - } - - w->window->requestUpdate(); -} - -void QSGD3D12ThreadedRenderLoop::handleResourceRelease(WindowData *w, bool destroying) -{ - if (Q_UNLIKELY(debug_loop())) - qDebug() << "handleResourceRelease" << (destroying ? "destroying" : "hide/releaseResources") << w->window; - - w->thread->mutex.lock(); - if (w->thread->isRunning() && w->thread->active) { - QQuickWindow *window = w->window; - - // Note that window->handle() is typically null by this time because - // the platform window is already destroyed. This should not be a - // problem for the D3D cleanup. - - w->thread->postEvent(new QSGD3D12TryReleaseEvent(window, destroying)); - w->thread->waitCondition.wait(&w->thread->mutex); - - // Avoid a shutdown race condition. - // If SG is invalidated and 'active' becomes false, the thread's run() - // method will exit. handleExposure() relies on QThread::isRunning() (because it - // potentially needs to start the thread again) and our mutex cannot be used to - // track the thread stopping, so we wait a few nanoseconds extra so the thread - // can exit properly. - if (!w->thread->active) - w->thread->wait(); - } - w->thread->mutex.unlock(); -} - -void QSGD3D12ThreadedRenderLoop::polishAndSync(WindowData *w, bool inExpose) -{ - if (Q_UNLIKELY(debug_loop())) - qDebug() << "polishAndSync" << (inExpose ? "(in expose)" : "(normal)") << w->window; - - QQuickWindow *window = w->window; - if (!w->thread || !w->thread->exposedWindow) { - if (Q_UNLIKELY(debug_loop())) - qDebug("polishAndSync - not exposed, abort"); - return; - } - - Q_TRACE_SCOPE(QSG_polishAndSync); - - // Flush pending touch events. - QQuickWindowPrivate::get(window)->flushFrameSynchronousEvents(); - // The delivery of the event might have caused the window to stop rendering - w = windowFor(windows, window); - if (!w || !w->thread || !w->thread->exposedWindow) { - if (Q_UNLIKELY(debug_loop())) - qDebug("polishAndSync - removed after touch event flushing, abort"); - return; - } - - QElapsedTimer timer; - qint64 polishTime = 0; - qint64 waitTime = 0; - qint64 syncTime = 0; - if (Q_UNLIKELY(debug_time())) - timer.start(); - Q_QUICK_SG_PROFILE_START(QQuickProfiler::SceneGraphPolishAndSync); - Q_TRACE(QSG_polishItems_entry); - - QQuickWindowPrivate *wd = QQuickWindowPrivate::get(window); - wd->polishItems(); - - if (Q_UNLIKELY(debug_time())) - polishTime = timer.nsecsElapsed(); - Q_TRACE(QSG_polishItems_exit); - Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphPolishAndSync, - QQuickProfiler::SceneGraphPolishAndSyncPolish); - Q_TRACE(QSG_wait_entry); - - w->updateDuringSync = false; - - emit window->afterAnimating(); - - if (Q_UNLIKELY(debug_loop())) - qDebug("polishAndSync - lock for sync"); - w->thread->mutex.lock(); - lockedForSync = true; - w->thread->postEvent(new QSGD3D12SyncEvent(window, inExpose, w->forceRenderPass)); - w->forceRenderPass = false; - - if (Q_UNLIKELY(debug_loop())) - qDebug("polishAndSync - wait for sync"); - if (Q_UNLIKELY(debug_time())) - waitTime = timer.nsecsElapsed(); - Q_TRACE(QSG_wait_exit); - Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphPolishAndSync, - QQuickProfiler::SceneGraphPolishAndSyncWait); - Q_TRACE(QSG_sync_entry); - - w->thread->waitCondition.wait(&w->thread->mutex); - lockedForSync = false; - w->thread->mutex.unlock(); - if (Q_UNLIKELY(debug_loop())) - qDebug("polishAndSync - unlock after sync"); - - if (Q_UNLIKELY(debug_time())) - syncTime = timer.nsecsElapsed(); - Q_TRACE(QSG_sync_exit); - Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphPolishAndSync, - QQuickProfiler::SceneGraphPolishAndSyncSync); - Q_TRACE(QSG_animations_entry); - - if (!animationTimer && anim->isRunning()) { - if (Q_UNLIKELY(debug_loop())) - qDebug("polishAndSync - advancing animations"); - anim->advance(); - // We need to trigger another sync to keep animations running... - w->window->requestUpdate(); - emit timeToIncubate(); - } else if (w->updateDuringSync) { - w->window->requestUpdate(); - } - - if (Q_UNLIKELY(debug_time())) - qDebug().nospace() - << "Frame prepared with 'd3d12' renderloop" - << ", polish=" << (polishTime / 1000000) - << ", lock=" << (waitTime - polishTime) / 1000000 - << ", blockedForSync=" << (syncTime - waitTime) / 1000000 - << ", animations=" << (timer.nsecsElapsed() - syncTime) / 1000000 - << " - (on gui thread) " << window; - - Q_TRACE(QSG_animations_exit); - Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphPolishAndSync, - QQuickProfiler::SceneGraphPolishAndSyncAnimations); -} - -#include "qsgd3d12threadedrenderloop.moc" - -QT_END_NAMESPACE diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12threadedrenderloop_p.h b/src/plugins/scenegraph/d3d12/qsgd3d12threadedrenderloop_p.h deleted file mode 100644 index 46f62948f1..0000000000 --- a/src/plugins/scenegraph/d3d12/qsgd3d12threadedrenderloop_p.h +++ /dev/null @@ -1,129 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#ifndef QSGD3D12THREADEDRENDERLOOP_P_H -#define QSGD3D12THREADEDRENDERLOOP_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include - -QT_BEGIN_NAMESPACE - -class QSGD3D12Engine; -class QSGD3D12Context; -class QSGD3D12RenderContext; -class QSGD3D12RenderThread; - -class QSGD3D12ThreadedRenderLoop : public QSGRenderLoop -{ - Q_OBJECT - -public: - QSGD3D12ThreadedRenderLoop(); - ~QSGD3D12ThreadedRenderLoop(); - - void show(QQuickWindow *window) override; - void hide(QQuickWindow *window) override; - void resize(QQuickWindow *window) override; - - void windowDestroyed(QQuickWindow *window) override; - - void exposureChanged(QQuickWindow *window) override; - - QImage grab(QQuickWindow *window) override; - - void update(QQuickWindow *window) override; - void maybeUpdate(QQuickWindow *window) override; - void handleUpdateRequest(QQuickWindow *window) override; - - QAnimationDriver *animationDriver() const override; - - QSGContext *sceneGraphContext() const override; - QSGRenderContext *createRenderContext(QSGContext *) const override; - - void releaseResources(QQuickWindow *window) override; - void postJob(QQuickWindow *window, QRunnable *job) override; - - QSurface::SurfaceType windowSurfaceType() const override; - bool interleaveIncubation() const override; - int flags() const override; - - bool event(QEvent *e) override; - -public Q_SLOTS: - void onAnimationStarted(); - void onAnimationStopped(); - -private: - struct WindowData { - QQuickWindow *window; - QSGD3D12RenderThread *thread; - uint updateDuringSync : 1; - uint forceRenderPass : 1; - }; - - void startOrStopAnimationTimer(); - void handleExposure(QQuickWindow *window); - void handleObscurity(WindowData *w); - void scheduleUpdate(WindowData *w); - void handleResourceRelease(WindowData *w, bool destroying); - void polishAndSync(WindowData *w, bool inExpose); - - QSGD3D12Context *sg; - QAnimationDriver *anim; - int animationTimer = 0; - bool lockedForSync = false; - QVector windows; - - friend class QSGD3D12RenderThread; -}; - -QT_END_NAMESPACE - -#endif // QSGD3D12THREADEDRENDERLOOP_P_H diff --git a/src/plugins/scenegraph/d3d12/shaders/flatcolor.hlsl b/src/plugins/scenegraph/d3d12/shaders/flatcolor.hlsl deleted file mode 100644 index 034b51435a..0000000000 --- a/src/plugins/scenegraph/d3d12/shaders/flatcolor.hlsl +++ /dev/null @@ -1,27 +0,0 @@ -struct VSInput -{ - float4 position : POSITION; -}; - -cbuffer ConstantBuffer : register(b0) -{ - float4x4 mvp; - float4 color; -}; - -struct PSInput -{ - float4 position : SV_POSITION; -}; - -PSInput VS_FlatColor(VSInput input) -{ - PSInput result; - result.position = mul(mvp, input.position); - return result; -} - -float4 PS_FlatColor(PSInput input) : SV_TARGET -{ - return color; -} diff --git a/src/plugins/scenegraph/d3d12/shaders/mipmapgen.hlsl b/src/plugins/scenegraph/d3d12/shaders/mipmapgen.hlsl deleted file mode 100644 index 6793b534b0..0000000000 --- a/src/plugins/scenegraph/d3d12/shaders/mipmapgen.hlsl +++ /dev/null @@ -1,60 +0,0 @@ -static const uint GROUP_DIM = 8; // 2 ^ (out_mip_count - 1) - -Texture2D tex : register(t0); -SamplerState samp : register(s0); - -cbuffer ConstantBuffer : register(b0) -{ - uint2 mip1Size; - uint sampleLevel; - uint totalMips; -} - -RWTexture2D mip1 : register(u0); -RWTexture2D mip2 : register(u1); -RWTexture2D mip3 : register(u2); -RWTexture2D mip4 : register(u3); - -groupshared float4 groupColor[GROUP_DIM][GROUP_DIM]; - -[numthreads(GROUP_DIM, GROUP_DIM, 1)] -void CS_Generate4MipMaps(uint3 localId: SV_GroupThreadId, uint3 globalId: SV_DispatchThreadID) -{ - const float2 coord = float2(1.0f / float(mip1Size.x), 1.0f / float(mip1Size.y)) * (globalId.xy + 0.5); - float4 c = tex.SampleLevel(samp, coord, sampleLevel); - - mip1[globalId.xy] = c; - groupColor[localId.y][localId.x] = c; - - if (sampleLevel + 1 >= totalMips) - return; - - GroupMemoryBarrierWithGroupSync(); - - if ((localId.x & 1) == 0 && (localId.y & 1) == 0) { - c = (c + groupColor[localId.y][localId.x + 1] + groupColor[localId.y + 1][localId.x] + groupColor[localId.y + 1][localId.x + 1]) / 4.0; - mip2[globalId.xy / 2] = c; - groupColor[localId.y][localId.x] = c; - } - - if (sampleLevel + 2 >= totalMips) - return; - - GroupMemoryBarrierWithGroupSync(); - - if ((localId.x & 3) == 0 && (localId.y & 3) == 0) { - c = (c + groupColor[localId.y][localId.x + 2] + groupColor[localId.y + 2][localId.x] + groupColor[localId.y + 2][localId.x + 2]) / 4.0; - mip3[globalId.xy / 4] = c; - groupColor[localId.y][localId.x] = c; - } - - if (sampleLevel + 3 >= totalMips) - return; - - GroupMemoryBarrierWithGroupSync(); - - if ((localId.x & 7) == 0 && (localId.y & 7) == 0) { - c = (c + groupColor[localId.y][localId.x + 3] + groupColor[localId.y + 3][localId.x] + groupColor[localId.y + 3][localId.x + 3]) / 4.0; - mip4[globalId.xy / 8] = c; - } -} diff --git a/src/plugins/scenegraph/d3d12/shaders/shadereffectdefault.hlsl b/src/plugins/scenegraph/d3d12/shaders/shadereffectdefault.hlsl deleted file mode 100644 index 94672d6267..0000000000 --- a/src/plugins/scenegraph/d3d12/shaders/shadereffectdefault.hlsl +++ /dev/null @@ -1,27 +0,0 @@ -cbuffer ConstantBuffer : register(b0) -{ - float4x4 qt_Matrix; - float qt_Opacity; -}; - -struct PSInput -{ - float4 position : SV_POSITION; - float2 coord : TEXCOORD0; -}; - -Texture2D source : register(t0); -SamplerState sourceSampler : register(s0); - -PSInput VS_DefaultShaderEffect(float4 position : POSITION, float2 coord : TEXCOORD0) -{ - PSInput result; - result.position = mul(qt_Matrix, position); - result.coord = coord; - return result; -} - -float4 PS_DefaultShaderEffect(PSInput input) : SV_TARGET -{ - return source.Sample(sourceSampler, input.coord) * qt_Opacity; -} diff --git a/src/plugins/scenegraph/d3d12/shaders/shaders.pri b/src/plugins/scenegraph/d3d12/shaders/shaders.pri deleted file mode 100644 index 963f4c5d8c..0000000000 --- a/src/plugins/scenegraph/d3d12/shaders/shaders.pri +++ /dev/null @@ -1,141 +0,0 @@ -vertexcolor_VSPS = $$PWD/vertexcolor.hlsl -vertexcolor_vshader.input = vertexcolor_VSPS -vertexcolor_vshader.header = vs_vertexcolor.hlslh -vertexcolor_vshader.entry = VS_VertexColor -vertexcolor_vshader.type = vs_5_0 -vertexcolor_pshader.input = vertexcolor_VSPS -vertexcolor_pshader.header = ps_vertexcolor.hlslh -vertexcolor_pshader.entry = PS_VertexColor -vertexcolor_pshader.type = ps_5_0 - -flatcolor_VSPS = $$PWD/flatcolor.hlsl -flatcolor_vshader.input = flatcolor_VSPS -flatcolor_vshader.header = vs_flatcolor.hlslh -flatcolor_vshader.entry = VS_FlatColor -flatcolor_vshader.type = vs_5_0 -flatcolor_pshader.input = flatcolor_VSPS -flatcolor_pshader.header = ps_flatcolor.hlslh -flatcolor_pshader.entry = PS_FlatColor -flatcolor_pshader.type = ps_5_0 - -stencilclip_VSPS = $$PWD/stencilclip.hlsl -stencilclip_vshader.input = stencilclip_VSPS -stencilclip_vshader.header = vs_stencilclip.hlslh -stencilclip_vshader.entry = VS_StencilClip -stencilclip_vshader.type = vs_5_0 -stencilclip_pshader.input = stencilclip_VSPS -stencilclip_pshader.header = ps_stencilclip.hlslh -stencilclip_pshader.entry = PS_StencilClip -stencilclip_pshader.type = ps_5_0 - -smoothcolor_VSPS = $$PWD/smoothcolor.hlsl -smoothcolor_vshader.input = smoothcolor_VSPS -smoothcolor_vshader.header = vs_smoothcolor.hlslh -smoothcolor_vshader.entry = VS_SmoothColor -smoothcolor_vshader.type = vs_5_0 -smoothcolor_pshader.input = smoothcolor_VSPS -smoothcolor_pshader.header = ps_smoothcolor.hlslh -smoothcolor_pshader.entry = PS_SmoothColor -smoothcolor_pshader.type = ps_5_0 - -texture_VSPS = $$PWD/texture.hlsl -texture_vshader.input = texture_VSPS -texture_vshader.header = vs_texture.hlslh -texture_vshader.entry = VS_Texture -texture_vshader.type = vs_5_0 -texture_pshader.input = texture_VSPS -texture_pshader.header = ps_texture.hlslh -texture_pshader.entry = PS_Texture -texture_pshader.type = ps_5_0 - -smoothtexture_VSPS = $$PWD/smoothtexture.hlsl -smoothtexture_vshader.input = smoothtexture_VSPS -smoothtexture_vshader.header = vs_smoothtexture.hlslh -smoothtexture_vshader.entry = VS_SmoothTexture -smoothtexture_vshader.type = vs_5_0 -smoothtexture_pshader.input = smoothtexture_VSPS -smoothtexture_pshader.header = ps_smoothtexture.hlslh -smoothtexture_pshader.entry = PS_SmoothTexture -smoothtexture_pshader.type = ps_5_0 - -mipmapgen_CS = $$PWD/mipmapgen.hlsl -mipmapgen_cshader.input = mipmapgen_CS -mipmapgen_cshader.header = cs_mipmapgen.hlslh -mipmapgen_cshader.entry = CS_Generate4MipMaps -mipmapgen_cshader.type = cs_5_0 - -textmask_VSPS = $$PWD/textmask.hlsl -textmask_vshader.input = textmask_VSPS -textmask_vshader.header = vs_textmask.hlslh -textmask_vshader.entry = VS_TextMask -textmask_vshader.type = vs_5_0 -textmask_pshader24.input = textmask_VSPS -textmask_pshader24.header = ps_textmask24.hlslh -textmask_pshader24.entry = PS_TextMask24 -textmask_pshader24.type = ps_5_0 -textmask_pshader32.input = textmask_VSPS -textmask_pshader32.header = ps_textmask32.hlslh -textmask_pshader32.entry = PS_TextMask32 -textmask_pshader32.type = ps_5_0 -textmask_pshader8.input = textmask_VSPS -textmask_pshader8.header = ps_textmask8.hlslh -textmask_pshader8.entry = PS_TextMask8 -textmask_pshader8.type = ps_5_0 -styledtext_vshader.input = textmask_VSPS -styledtext_vshader.header = vs_styledtext.hlslh -styledtext_vshader.entry = VS_StyledText -styledtext_vshader.type = vs_5_0 -styledtext_pshader.input = textmask_VSPS -styledtext_pshader.header = ps_styledtext.hlslh -styledtext_pshader.entry = PS_StyledText -styledtext_pshader.type = ps_5_0 -outlinedtext_vshader.input = textmask_VSPS -outlinedtext_vshader.header = vs_outlinedtext.hlslh -outlinedtext_vshader.entry = VS_OutlinedText -outlinedtext_vshader.type = vs_5_0 -outlinedtext_pshader.input = textmask_VSPS -outlinedtext_pshader.header = ps_outlinedtext.hlslh -outlinedtext_pshader.entry = PS_OutlinedText -outlinedtext_pshader.type = ps_5_0 - -shadereffectdefault_VSPS = $$PWD/shadereffectdefault.hlsl -shadereffectdefault_vshader.input = shadereffectdefault_VSPS -shadereffectdefault_vshader.header = vs_shadereffectdefault.hlslh -shadereffectdefault_vshader.entry = VS_DefaultShaderEffect -shadereffectdefault_vshader.type = vs_5_0 -shadereffectdefault_pshader.input = shadereffectdefault_VSPS -shadereffectdefault_pshader.header = ps_shadereffectdefault.hlslh -shadereffectdefault_pshader.entry = PS_DefaultShaderEffect -shadereffectdefault_pshader.type = ps_5_0 - -sprite_VSPS = $$PWD/sprite.hlsl -sprite_vshader.input = sprite_VSPS -sprite_vshader.header = vs_sprite.hlslh -sprite_vshader.entry = VS_Sprite -sprite_vshader.type = vs_5_0 -sprite_pshader.input = sprite_VSPS -sprite_pshader.header = ps_sprite.hlslh -sprite_pshader.entry = PS_Sprite -sprite_pshader.type = ps_5_0 - -tdr_CS = $$PWD/tdr.hlsl -tdr_cshader.input = tdr_CS -tdr_cshader.header = cs_tdr.hlslh -tdr_cshader.entry = timeout -tdr_cshader.type = cs_5_0 - -HLSL_SHADERS = \ - vertexcolor_vshader vertexcolor_pshader \ - flatcolor_vshader flatcolor_pshader \ - stencilclip_vshader stencilclip_pshader \ - smoothcolor_vshader smoothcolor_pshader \ - texture_vshader texture_pshader \ - smoothtexture_vshader smoothtexture_pshader \ - mipmapgen_cshader \ - textmask_vshader textmask_pshader24 textmask_pshader32 textmask_pshader8 \ - styledtext_vshader styledtext_pshader outlinedtext_vshader outlinedtext_pshader \ - shadereffectdefault_vshader shadereffectdefault_pshader \ - sprite_vshader sprite_pshader \ - tdr_cshader - -load(hlsl_bytecode_header) diff --git a/src/plugins/scenegraph/d3d12/shaders/smoothcolor.hlsl b/src/plugins/scenegraph/d3d12/shaders/smoothcolor.hlsl deleted file mode 100644 index 4f69eea60f..0000000000 --- a/src/plugins/scenegraph/d3d12/shaders/smoothcolor.hlsl +++ /dev/null @@ -1,64 +0,0 @@ -struct VSInput -{ - float4 position : POSITION; - float4 color : COLOR; - float2 offset : TEXCOORD0; -}; - -cbuffer ConstantBuffer : register(b0) -{ - float4x4 mvp; - float opacity; - float2 pixelSize; -}; - -struct PSInput -{ - float4 position : SV_POSITION; - float4 color : COLOR; -}; - -PSInput VS_SmoothColor(VSInput input) -{ - PSInput result; - - float4 pos = mul(mvp, input.position); - - if (input.offset.x != 0.0) { - // In HLSL matrix packing is column-major by default (which is good) but the math is row-major (unlike GLSL). - float4 delta = float4(mvp._11, mvp._21, mvp._31, mvp._41) * input.offset.x; - float2 dir = delta.xy * pos.w - pos.xy * delta.w; - float2 ndir = 0.5 * pixelSize * normalize(dir / pixelSize); - dir -= ndir * delta.w * pos.w; - float numerator = dot(dir, ndir * pos.w * pos.w); - float scale = 0.0; - if (numerator < 0.0) - scale = 1.0; - else - scale = min(1.0, numerator / dot(dir, dir)); - pos += scale * delta; - } - - if (input.offset.y != 0.0) { - float4 delta = float4(mvp._12, mvp._22, mvp._32, mvp._42) * input.offset.y; - float2 dir = delta.xy * pos.w - pos.xy * delta.w; - float2 ndir = 0.5 * pixelSize * normalize(dir / pixelSize); - dir -= ndir * delta.w * pos.w; - float numerator = dot(dir, ndir * pos.w * pos.w); - float scale = 0.0; - if (numerator < 0.0) - scale = 1.0; - else - scale = min(1.0, numerator / dot(dir, dir)); - pos += scale * delta; - } - - result.position = pos; - result.color = input.color * opacity; - return result; -} - -float4 PS_SmoothColor(PSInput input) : SV_TARGET -{ - return input.color; -} diff --git a/src/plugins/scenegraph/d3d12/shaders/smoothtexture.hlsl b/src/plugins/scenegraph/d3d12/shaders/smoothtexture.hlsl deleted file mode 100644 index 05b1c6e9d4..0000000000 --- a/src/plugins/scenegraph/d3d12/shaders/smoothtexture.hlsl +++ /dev/null @@ -1,77 +0,0 @@ -struct VSInput -{ - float4 position : POSITION; - float2 coord : TEXCOORD0; - float2 offset : TEXCOORD1; - float2 coordOffset : TEXCOORD2; -}; - -cbuffer ConstantBuffer : register(b0) -{ - float4x4 mvp; - float opacity; - float2 pixelSize; -}; - -struct PSInput -{ - float4 position : SV_POSITION; - float2 coord : TEXCOORD0; - float vertexOpacity : TEXCOORD3; -}; - -Texture2D tex : register(t0); -SamplerState samp : register(s0); - -PSInput VS_SmoothTexture(VSInput input) -{ - PSInput result; - - float4 pos = mul(mvp, input.position); - float2 coord = input.coord; - - if (input.offset.x != 0.0) { - // In HLSL matrix packing is column-major by default (which is good) but the math is row-major (unlike GLSL). - float4 delta = float4(mvp._11, mvp._21, mvp._31, mvp._41) * input.offset.x; - float2 dir = delta.xy * pos.w - pos.xy * delta.w; - float2 ndir = 0.5 * pixelSize * normalize(dir / pixelSize); - dir -= ndir * delta.w * pos.w; - float numerator = dot(dir, ndir * pos.w * pos.w); - float scale = 0.0; - if (numerator < 0.0) - scale = 1.0; - else - scale = min(1.0, numerator / dot(dir, dir)); - pos += scale * delta; - coord.x += scale * input.coordOffset.x; - } - - if (input.offset.y != 0.0) { - float4 delta = float4(mvp._12, mvp._22, mvp._32, mvp._42) * input.offset.y; - float2 dir = delta.xy * pos.w - pos.xy * delta.w; - float2 ndir = 0.5 * pixelSize * normalize(dir / pixelSize); - dir -= ndir * delta.w * pos.w; - float numerator = dot(dir, ndir * pos.w * pos.w); - float scale = 0.0; - if (numerator < 0.0) - scale = 1.0; - else - scale = min(1.0, numerator / dot(dir, dir)); - pos += scale * delta; - coord.y += scale * input.coordOffset.y; - } - - if ((input.offset.x != 0.0 || input.offset.y != 0.0) && (input.coordOffset.x == 0.0 && input.coordOffset.y == 0.0)) - result.vertexOpacity = 0.0; - else - result.vertexOpacity = opacity; - - result.position = pos; - result.coord = coord; - return result; -} - -float4 PS_SmoothTexture(PSInput input) : SV_TARGET -{ - return tex.Sample(samp, input.coord) * input.vertexOpacity; -} diff --git a/src/plugins/scenegraph/d3d12/shaders/sprite.hlsl b/src/plugins/scenegraph/d3d12/shaders/sprite.hlsl deleted file mode 100644 index d4e3b066ee..0000000000 --- a/src/plugins/scenegraph/d3d12/shaders/sprite.hlsl +++ /dev/null @@ -1,43 +0,0 @@ -struct VSInput -{ - float4 position : POSITION; - float2 coord : TEXCOORD0; -}; - -cbuffer ConstantBuffer : register(b0) -{ - float4x4 mvp; - float4 animPos; - float3 animData; - float opacity; -}; - -struct PSInput -{ - float4 position : SV_POSITION; - float4 fTexS : TEXCOORD0; - float progress : TEXCOORD1; -}; - -Texture2D tex : register(t0); -SamplerState samp : register(s0); - -PSInput VS_Sprite(VSInput input) -{ - PSInput result; - - result.position = mul(mvp, input.position); - result.progress = animData.z; - - // Calculate frame location in texture - result.fTexS.xy = animPos.xy + input.coord.xy * animData.xy; - // Next frame is also passed, for interpolation - result.fTexS.zw = animPos.zw + input.coord.xy * animData.xy; - - return result; -} - -float4 PS_Sprite(PSInput input) : SV_TARGET -{ - return lerp(tex.Sample(samp, input.fTexS.xy), tex.Sample(samp, input.fTexS.zw), input.progress) * opacity; -} diff --git a/src/plugins/scenegraph/d3d12/shaders/stencilclip.hlsl b/src/plugins/scenegraph/d3d12/shaders/stencilclip.hlsl deleted file mode 100644 index 9aff84d261..0000000000 --- a/src/plugins/scenegraph/d3d12/shaders/stencilclip.hlsl +++ /dev/null @@ -1,26 +0,0 @@ -struct VSInput -{ - float4 position : POSITION; -}; - -cbuffer ConstantBuffer : register(b0) -{ - float4x4 mvp; -}; - -struct PSInput -{ - float4 position : SV_POSITION; -}; - -PSInput VS_StencilClip(VSInput input) -{ - PSInput result; - result.position = mul(mvp, input.position); - return result; -} - -float4 PS_StencilClip(PSInput input) : SV_TARGET -{ - return float4(0.81, 0.83, 0.12, 1.0); // Trolltech green ftw! -} diff --git a/src/plugins/scenegraph/d3d12/shaders/tdr.hlsl b/src/plugins/scenegraph/d3d12/shaders/tdr.hlsl deleted file mode 100644 index f32d4fbace..0000000000 --- a/src/plugins/scenegraph/d3d12/shaders/tdr.hlsl +++ /dev/null @@ -1,11 +0,0 @@ -// http://gamedev.stackexchange.com/questions/108141/how-can-i-test-dxgi-error-device-removed-error-handling - -RWBuffer uav; -cbuffer ConstantBuffer { uint zero; } - -[numthreads(256, 1, 1)] -void timeout(uint3 id: SV_DispatchThreadID) -{ - while (zero == 0) - uav[id.x] = zero; -} diff --git a/src/plugins/scenegraph/d3d12/shaders/textmask.hlsl b/src/plugins/scenegraph/d3d12/shaders/textmask.hlsl deleted file mode 100644 index bb9381e7c0..0000000000 --- a/src/plugins/scenegraph/d3d12/shaders/textmask.hlsl +++ /dev/null @@ -1,104 +0,0 @@ -struct VSInput -{ - float4 position : POSITION; - float2 coord : TEXCOORD0; -}; - -cbuffer ConstantBuffer : register(b0) -{ - float4x4 mvp; - float2 textureScale; - float dpr; - float color; // for TextMask24 and 32 - float4 colorVec; // for TextMask8 and Styled and Outlined - float2 shift; // for Styled - float4 styleColor; // for Styled and Outlined -}; - -struct PSInput -{ - float4 position : SV_POSITION; - float2 coord : TEXCOORD0; -}; - -Texture2D tex : register(t0); -SamplerState samp : register(s0); - -PSInput VS_TextMask(VSInput input) -{ - PSInput result; - result.position = mul(mvp, floor(input.position * dpr + 0.5) / dpr); - result.coord = input.coord * textureScale; - return result; -} - -float4 PS_TextMask24(PSInput input) : SV_TARGET -{ - float4 glyph = tex.Sample(samp, input.coord); - return float4(glyph.rgb * color, glyph.a); -} - -float4 PS_TextMask32(PSInput input) : SV_TARGET -{ - return tex.Sample(samp, input.coord) * color; -} - -float4 PS_TextMask8(PSInput input) : SV_TARGET -{ - return colorVec * tex.Sample(samp, input.coord).a; -} - -struct StyledPSInput -{ - float4 position : SV_POSITION; - float2 coord : TEXCOORD0; - float2 shiftedCoord : TEXCOORD1; -}; - -StyledPSInput VS_StyledText(VSInput input) -{ - StyledPSInput result; - result.position = mul(mvp, floor(input.position * dpr + 0.5) / dpr); - result.coord = input.coord * textureScale; - result.shiftedCoord = (input.coord - shift) * textureScale; - return result; -} - -float4 PS_StyledText(StyledPSInput input) : SV_TARGET -{ - float glyph = tex.Sample(samp, input.coord).a; - float style = clamp(tex.Sample(samp, input.shiftedCoord).a - glyph, 0.0, 1.0); - return style * styleColor + glyph * colorVec; -} - -struct OutlinedPSInput -{ - float4 position : SV_POSITION; - float2 coord : TEXCOORD0; - float2 coordUp : TEXCOORD1; - float2 coordDown : TEXCOORD2; - float2 coordLeft : TEXCOORD3; - float2 coordRight : TEXCOORD4; -}; - -OutlinedPSInput VS_OutlinedText(VSInput input) -{ - OutlinedPSInput result; - result.position = mul(mvp, floor(input.position * dpr + 0.5) / dpr); - result.coord = input.coord * textureScale; - result.coordUp = (input.coord - float2(0.0, -1.0)) * textureScale; - result.coordDown = (input.coord - float2(0.0, 1.0)) * textureScale; - result.coordLeft = (input.coord - float2(-1.0, 0.0)) * textureScale; - result.coordRight = (input.coord - float2(1.0, 0.0)) * textureScale; - return result; -} - -float4 PS_OutlinedText(OutlinedPSInput input) : SV_TARGET -{ - float glyph = tex.Sample(samp, input.coord).a; - float outline = clamp(clamp(tex.Sample(samp, input.coordUp).a - + tex.Sample(samp, input.coordDown).a - + tex.Sample(samp, input.coordLeft).a - + tex.Sample(samp, input.coordRight).a, 0.0, 1.0) - glyph, 0.0, 1.0); - return outline * styleColor + glyph * colorVec; -} diff --git a/src/plugins/scenegraph/d3d12/shaders/texture.hlsl b/src/plugins/scenegraph/d3d12/shaders/texture.hlsl deleted file mode 100644 index 1ae6579e8d..0000000000 --- a/src/plugins/scenegraph/d3d12/shaders/texture.hlsl +++ /dev/null @@ -1,33 +0,0 @@ -struct VSInput -{ - float4 position : POSITION; - float2 coord : TEXCOORD0; -}; - -cbuffer ConstantBuffer : register(b0) -{ - float4x4 mvp; - float opacity; -}; - -struct PSInput -{ - float4 position : SV_POSITION; - float2 coord : TEXCOORD0; -}; - -Texture2D tex : register(t0); -SamplerState samp : register(s0); - -PSInput VS_Texture(VSInput input) -{ - PSInput result; - result.position = mul(mvp, input.position); - result.coord = input.coord; - return result; -} - -float4 PS_Texture(PSInput input) : SV_TARGET -{ - return tex.Sample(samp, input.coord) * opacity; -} diff --git a/src/plugins/scenegraph/d3d12/shaders/vertexcolor.hlsl b/src/plugins/scenegraph/d3d12/shaders/vertexcolor.hlsl deleted file mode 100644 index a0569bb5c1..0000000000 --- a/src/plugins/scenegraph/d3d12/shaders/vertexcolor.hlsl +++ /dev/null @@ -1,32 +0,0 @@ -struct VSInput -{ - float4 position : POSITION; - float4 color : COLOR; -}; - -cbuffer ConstantBuffer : register(b0) -{ - float4x4 mvp; - float opacity; -}; - -struct PSInput -{ - float4 position : SV_POSITION; - float4 color : COLOR; -}; - -PSInput VS_VertexColor(VSInput input) -{ - PSInput result; - - result.position = mul(mvp, input.position); - result.color = input.color * opacity; - - return result; -} - -float4 PS_VertexColor(PSInput input) : SV_TARGET -{ - return input.color; -} diff --git a/src/plugins/scenegraph/scenegraph.pro b/src/plugins/scenegraph/scenegraph.pro index 39c0c0815c..9cc521a191 100644 --- a/src/plugins/scenegraph/scenegraph.pro +++ b/src/plugins/scenegraph/scenegraph.pro @@ -1,5 +1,4 @@ TEMPLATE = subdirs QT_FOR_CONFIG += quick -qtConfig(d3d12): SUBDIRS += d3d12 qtConfig(openvg): SUBDIRS += openvg -- cgit v1.2.3