diff options
Diffstat (limited to 'src/gui/rhi/qshaderdescription.cpp')
-rw-r--r-- | src/gui/rhi/qshaderdescription.cpp | 498 |
1 files changed, 430 insertions, 68 deletions
diff --git a/src/gui/rhi/qshaderdescription.cpp b/src/gui/rhi/qshaderdescription.cpp index ca697d8edb..f64daf02ef 100644 --- a/src/gui/rhi/qshaderdescription.cpp +++ b/src/gui/rhi/qshaderdescription.cpp @@ -1,8 +1,8 @@ -// Copyright (C) 2019 The Qt Company Ltd. +// Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only -#include "qshaderdescription_p_p.h" -#include "qshader_p_p.h" +#include "qshaderdescription_p.h" +#include "qshader_p.h" #include <QDebug> #include <QDataStream> #include <QJsonObject> @@ -12,11 +12,22 @@ QT_BEGIN_NAMESPACE /*! \class QShaderDescription - \internal + \ingroup painting-3D \inmodule QtGui + \since 6.6 \brief Describes the interface of a shader. + \warning The QRhi family of classes in the Qt Gui module, including QShader + and QShaderDescription, offer limited compatibility guarantees. There are + no source or binary compatibility guarantees for these classes, meaning the + API is only guaranteed to work with the Qt version the application was + developed against. Source incompatible changes are however aimed to be kept + at a minimum and will only be made in minor releases (6.7, 6.8, and so on). + To use these classes in an application, link to + \c{Qt::GuiPrivate} (if using CMake), and include the headers with the \c + rhi prefix, for example \c{#include <rhi/qshaderdescription.h>}. + A shader typically has a set of inputs and outputs. A vertex shader for example has a number of input variables and may use one or more uniform buffers to access data (e.g. a modelview matrix) provided by the @@ -51,8 +62,6 @@ QT_BEGIN_NAMESPACE float opacity; } ubuf; - out gl_PerVertex { vec4 gl_Position; }; - void main() { v_color = color; @@ -200,28 +209,179 @@ QT_BEGIN_NAMESPACE \value ImageRect \value ImageBuffer \value Struct + \value Half + \value Half2 + \value Half3 + \value Half4 */ /*! - \class QShaderDescription::InOutVariable - \internal + \enum QShaderDescription::ImageFormat + Image format. + + \value ImageFormatUnknown + \value ImageFormatRgba32f + \value ImageFormatRgba16f + \value ImageFormatR32f + \value ImageFormatRgba8 + \value ImageFormatRgba8Snorm + \value ImageFormatRg32f + \value ImageFormatRg16f + \value ImageFormatR11fG11fB10f + \value ImageFormatR16f + \value ImageFormatRgba16 + \value ImageFormatRgb10A2 + \value ImageFormatRg16 + \value ImageFormatRg8 + \value ImageFormatR16 + \value ImageFormatR8 + \value ImageFormatRgba16Snorm + \value ImageFormatRg16Snorm + \value ImageFormatRg8Snorm + \value ImageFormatR16Snorm + \value ImageFormatR8Snorm + \value ImageFormatRgba32i + \value ImageFormatRgba16i + \value ImageFormatRgba8i + \value ImageFormatR32i + \value ImageFormatRg32i + \value ImageFormatRg16i + \value ImageFormatRg8i + \value ImageFormatR16i + \value ImageFormatR8i + \value ImageFormatRgba32ui + \value ImageFormatRgba16ui + \value ImageFormatRgba8ui + \value ImageFormatR32ui + \value ImageFormatRgb10a2ui + \value ImageFormatRg32ui + \value ImageFormatRg16ui + \value ImageFormatRg8ui + \value ImageFormatR16ui + \value ImageFormatR8ui + */ + +/*! + \enum QShaderDescription::ImageFlag + Image flags. + + \value ReadOnlyImage + \value WriteOnlyImage + */ + +/*! + \enum QShaderDescription::QualifierFlag + Qualifier flags. + + \value QualifierReadOnly + \value QualifierWriteOnly + \value QualifierCoherent + \value QualifierVolatile + \value QualifierRestrict + */ + +/*! + \struct QShaderDescription::InOutVariable \inmodule QtGui + \since 6.6 \brief Describes an input or output variable in the shader. + + \note This is a RHI API with limited compatibility guarantees, see \l QShaderDescription + for details. */ /*! - \class QShaderDescription::BlockVariable - \internal + \variable QShaderDescription::InOutVariable::name + */ + +/*! + \variable QShaderDescription::InOutVariable::type + */ + +/*! + \variable QShaderDescription::InOutVariable::location + */ + +/*! + \variable QShaderDescription::InOutVariable::binding + */ + +/*! + \variable QShaderDescription::InOutVariable::descriptorSet + */ + +/*! + \variable QShaderDescription::InOutVariable::imageFormat + */ + +/*! + \variable QShaderDescription::InOutVariable::imageFlags + */ + +/*! + \variable QShaderDescription::InOutVariable::arrayDims + */ + +/*! + \variable QShaderDescription::InOutVariable::perPatch + */ + +/*! + \variable QShaderDescription::InOutVariable::structMembers + */ + +/*! + \struct QShaderDescription::BlockVariable \inmodule QtGui + \since 6.6 \brief Describes a member of a uniform or push constant block. + + \note This is a RHI API with limited compatibility guarantees, see \l QShaderDescription + for details. */ /*! - \class QShaderDescription::UniformBlock - \internal + \variable QShaderDescription::BlockVariable::name + */ + +/*! + \variable QShaderDescription::BlockVariable::type + */ + +/*! + \variable QShaderDescription::BlockVariable::offset + */ + +/*! + \variable QShaderDescription::BlockVariable::size + */ + +/*! + \variable QShaderDescription::BlockVariable::arrayDims + */ + +/*! + \variable QShaderDescription::BlockVariable::arrayStride + */ + +/*! + \variable QShaderDescription::BlockVariable::matrixStride + */ + +/*! + \variable QShaderDescription::BlockVariable::matrixIsRowMajor + */ + +/*! + \variable QShaderDescription::BlockVariable::structMembers + */ + +/*! + \struct QShaderDescription::UniformBlock \inmodule QtGui + \since 6.6 \brief Describes a uniform block. @@ -229,22 +389,157 @@ QT_BEGIN_NAMESPACE (like GLSL 120 or GLSL/ES 100), uniform blocks are replaced with ordinary uniforms in a struct. The name of the struct, and so the prefix for the uniforms generated from the block members, is given by structName. + + \note This is a RHI API with limited compatibility guarantees, see \l QShaderDescription + for details. */ /*! - \class QShaderDescription::PushConstantBlock - \internal + \variable QShaderDescription::UniformBlock::blockName + */ + +/*! + \variable QShaderDescription::UniformBlock::structName + */ + +/*! + \variable QShaderDescription::UniformBlock::size + */ + +/*! + \variable QShaderDescription::UniformBlock::binding + */ + +/*! + \variable QShaderDescription::UniformBlock::descriptorSet + */ + +/*! + \variable QShaderDescription::UniformBlock::members + */ + +/*! + \struct QShaderDescription::PushConstantBlock \inmodule QtGui + \since 6.6 \brief Describes a push constant block. + + \note This is a RHI API with limited compatibility guarantees, see \l QShaderDescription + for details. */ /*! - \class QShaderDescription::StorageBlock - \internal + \variable QShaderDescription::PushConstantBlock::name + */ + +/*! + \variable QShaderDescription::PushConstantBlock::size + */ + +/*! + \variable QShaderDescription::PushConstantBlock::members + */ + +/*! + \struct QShaderDescription::StorageBlock \inmodule QtGui + \since 6.6 \brief Describes a shader storage block. + + \note This is a RHI API with limited compatibility guarantees, see \l QShaderDescription + for details. + */ + +/*! + \variable QShaderDescription::StorageBlock::blockName + */ + +/*! + \variable QShaderDescription::StorageBlock::instanceName + */ + +/*! + \variable QShaderDescription::StorageBlock::knownSize + */ + +/*! + \variable QShaderDescription::StorageBlock::binding + */ + +/*! + \variable QShaderDescription::StorageBlock::descriptorSet + */ + +/*! + \variable QShaderDescription::StorageBlock::members + */ + +/*! + \variable QShaderDescription::StorageBlock::runtimeArrayStride + */ + +/*! + \variable QShaderDescription::StorageBlock::qualifierFlags + */ + +/*! + \struct QShaderDescription::BuiltinVariable + \inmodule QtGui + \since 6.6 + + \brief Describes a built-in variable. + + \note This is a RHI API with limited compatibility guarantees, see \l QShaderDescription + for details. + */ + +/*! + \variable QShaderDescription::BuiltinVariable::type + */ + +/*! + \variable QShaderDescription::BuiltinVariable::varType + */ + +/*! + \variable QShaderDescription::BuiltinVariable::arrayDims + */ + +/*! + \enum QShaderDescription::BuiltinType + Built-in variable type. + + \value PositionBuiltin + \value PointSizeBuiltin + \value ClipDistanceBuiltin + \value CullDistanceBuiltin + \value VertexIdBuiltin + \value InstanceIdBuiltin + \value PrimitiveIdBuiltin + \value InvocationIdBuiltin + \value LayerBuiltin + \value ViewportIndexBuiltin + \value TessLevelOuterBuiltin + \value TessLevelInnerBuiltin + \value TessCoordBuiltin + \value PatchVerticesBuiltin + \value FragCoordBuiltin + \value PointCoordBuiltin + \value FrontFacingBuiltin + \value SampleIdBuiltin + \value SamplePositionBuiltin + \value SampleMaskBuiltin + \value FragDepthBuiltin + \value NumWorkGroupsBuiltin + \value WorkgroupSizeBuiltin + \value WorkgroupIdBuiltin + \value LocalInvocationIdBuiltin + \value GlobalInvocationIdBuiltin + \value LocalInvocationIndexBuiltin + \value VertexIndexBuiltin + \value InstanceIndexBuiltin */ /*! @@ -267,7 +562,7 @@ void QShaderDescription::detach() } /*! - \internal + Constructs a copy of \a other. */ QShaderDescription::QShaderDescription(const QShaderDescription &other) : d(other.d) @@ -276,7 +571,7 @@ QShaderDescription::QShaderDescription(const QShaderDescription &other) } /*! - \internal + Assigns \a other to this object. */ QShaderDescription &QShaderDescription::operator=(const QShaderDescription &other) { @@ -574,7 +869,7 @@ uint QShaderDescription::tessellationOutputVertexCount() const \value UnknownTessellationMode \value TrianglesTessellationMode \value QuadTessellationMode - \value IsolinesTessellationMode + \value IsolineTessellationMode */ /*! @@ -724,8 +1019,12 @@ static const struct TypeTab { { "image3DArray", QShaderDescription::Image3DArray }, { "imageCubeArray", QShaderDescription::ImageCubeArray }, { "imageRect", QShaderDescription::ImageRect }, - { "imageBuffer", QShaderDescription::ImageBuffer } -}; + { "imageBuffer", QShaderDescription::ImageBuffer }, + + { "half", QShaderDescription::Half }, + { "half2", QShaderDescription::Half2 }, + { "half3", QShaderDescription::Half3 }, + { "half4", QShaderDescription::Half4 } }; static QLatin1StringView typeStr(QShaderDescription::VariableType t) { @@ -936,6 +1235,8 @@ QDebug operator<<(QDebug dbg, const QShaderDescription::InOutVariable &var) dbg.nospace() << " imageFlags=" << var.imageFlags; if (!var.arrayDims.isEmpty()) dbg.nospace() << " array=" << var.arrayDims; + if (!var.structMembers.isEmpty()) + dbg.nospace() << " structMembers=" << var.structMembers; dbg.nospace() << ')'; return dbg; } @@ -943,8 +1244,10 @@ QDebug operator<<(QDebug dbg, const QShaderDescription::InOutVariable &var) QDebug operator<<(QDebug dbg, const QShaderDescription::BlockVariable &var) { QDebugStateSaver saver(dbg); - dbg.nospace() << "BlockVariable(" << typeStr(var.type) << ' ' << var.name - << " offset=" << var.offset << " size=" << var.size; + dbg.nospace() << "BlockVariable(" << typeStr(var.type) << ' ' << var.name; + if (var.offset != -1) + dbg.nospace() << " offset=" << var.offset; + dbg.nospace() << " size=" << var.size; if (!var.arrayDims.isEmpty()) dbg.nospace() << " array=" << var.arrayDims; if (var.arrayStride) @@ -1000,7 +1303,11 @@ QDebug operator<<(QDebug dbg, const QShaderDescription::StorageBlock &blk) QDebug operator<<(QDebug dbg, const QShaderDescription::BuiltinVariable &builtin) { QDebugStateSaver saver(dbg); - dbg.nospace() << "BuiltinVariable(type=" << builtinTypeStr(builtin.type) << ")"; + dbg.nospace() << "BuiltinVariable(type=" << builtinTypeStr(builtin.type); + dbg.nospace() << " varType=" << typeStr(builtin.varType); + if (!builtin.arrayDims.isEmpty()) + dbg.nospace() << " array=" << builtin.arrayDims; + dbg.nospace() << ")"; return dbg; } #endif @@ -1082,20 +1389,15 @@ static void serializeDecorations(QDataStream *stream, const QShaderDescription:: (*stream) << quint8(v.perPatch); } -static QJsonObject inOutObject(const QShaderDescription::InOutVariable &v) +static void serializeBuiltinVar(QDataStream *stream, const QShaderDescription::BuiltinVariable &v, int version) { - QJsonObject obj; - obj[nameKey()] = QString::fromUtf8(v.name); - obj[typeKey()] = typeStr(v.type); - addDeco(&obj, v); - return obj; -} - -static void serializeInOutVar(QDataStream *stream, const QShaderDescription::InOutVariable &v, int version) -{ - (*stream) << QString::fromUtf8(v.name); (*stream) << int(v.type); - serializeDecorations(stream, v, version); + if (version > QShaderPrivate::QSB_VERSION_WITHOUT_INPUT_OUTPUT_INTERFACE_BLOCKS) { + (*stream) << int(v.varType); + (*stream) << int(v.arrayDims.size()); + for (int dim : v.arrayDims) + (*stream) << dim; + } } static QJsonObject blockMemberObject(const QShaderDescription::BlockVariable &v) @@ -1103,7 +1405,8 @@ static QJsonObject blockMemberObject(const QShaderDescription::BlockVariable &v) QJsonObject obj; obj[nameKey()] = QString::fromUtf8(v.name); obj[typeKey()] = typeStr(v.type); - obj[offsetKey()] = v.offset; + if (v.offset != -1) + obj[offsetKey()] = v.offset; obj[sizeKey()] = v.size; if (!v.arrayDims.isEmpty()) { QJsonArray dimArr; @@ -1126,6 +1429,36 @@ static QJsonObject blockMemberObject(const QShaderDescription::BlockVariable &v) return obj; } +static QJsonObject inOutObject(const QShaderDescription::InOutVariable &v) +{ + QJsonObject obj; + obj[nameKey()] = QString::fromUtf8(v.name); + obj[typeKey()] = typeStr(v.type); + addDeco(&obj, v); + if (!v.structMembers.isEmpty()) { + QJsonArray arr; + for (const QShaderDescription::BlockVariable &sv : v.structMembers) + arr.append(blockMemberObject(sv)); + obj[structMembersKey()] = arr; + } + return obj; +} + +static QJsonObject builtinObject(const QShaderDescription::BuiltinVariable &v) +{ + QJsonObject obj; + + obj[nameKey()] = builtinTypeStr(v.type); + obj[typeKey()] = typeStr(v.varType); + if (!v.arrayDims.isEmpty()) { + QJsonArray dimArr; + for (int dim : v.arrayDims) + dimArr.append(dim); + obj[arrayDimsKey()] = dimArr; + } + return obj; +} + static void serializeBlockMemberVar(QDataStream *stream, const QShaderDescription::BlockVariable &v) { (*stream) << QString::fromUtf8(v.name); @@ -1143,6 +1476,19 @@ static void serializeBlockMemberVar(QDataStream *stream, const QShaderDescriptio serializeBlockMemberVar(stream, sv); } +static void serializeInOutVar(QDataStream *stream, const QShaderDescription::InOutVariable &v, + int version) +{ + (*stream) << QString::fromUtf8(v.name); + (*stream) << int(v.type); + serializeDecorations(stream, v, version); + if (version > QShaderPrivate::QSB_VERSION_WITHOUT_INPUT_OUTPUT_INTERFACE_BLOCKS) { + (*stream) << int(v.structMembers.size()); + for (const QShaderDescription::BlockVariable &sv : v.structMembers) + serializeBlockMemberVar(stream, sv); + } +} + QJsonDocument QShaderDescriptionPrivate::makeDoc() { QJsonObject root; @@ -1238,20 +1584,14 @@ QJsonDocument QShaderDescriptionPrivate::makeDoc() root[storageImagesKey()] = jstorageImages; QJsonArray jinBuiltins; - for (const QShaderDescription::BuiltinVariable &v : std::as_const(inBuiltins)) { - QJsonObject builtin; - builtin[typeKey()] = builtinTypeStr(v.type); - jinBuiltins.append(builtin); - } + for (const QShaderDescription::BuiltinVariable &v : std::as_const(inBuiltins)) + jinBuiltins.append(builtinObject(v)); if (!jinBuiltins.isEmpty()) root[inBuiltinsKey()] = jinBuiltins; QJsonArray joutBuiltins; - for (const QShaderDescription::BuiltinVariable &v : std::as_const(outBuiltins)) { - QJsonObject builtin; - builtin[typeKey()] = builtinTypeStr(v.type); - joutBuiltins.append(builtin); - } + for (const QShaderDescription::BuiltinVariable &v : std::as_const(outBuiltins)) + joutBuiltins.append(builtinObject(v)); if (!joutBuiltins.isEmpty()) root[outBuiltinsKey()] = joutBuiltins; @@ -1385,11 +1725,11 @@ void QShaderDescriptionPrivate::writeToStream(QDataStream *stream, int version) (*stream) << int(inBuiltins.size()); for (const QShaderDescription::BuiltinVariable &v : std::as_const(inBuiltins)) - (*stream) << int(v.type); + serializeBuiltinVar(stream, v, version); (*stream) << int(outBuiltins.size()); for (const QShaderDescription::BuiltinVariable &v : std::as_const(outBuiltins)) - (*stream) << int(v.type); + serializeBuiltinVar(stream, v, version); } } @@ -1418,16 +1758,21 @@ static void deserializeDecorations(QDataStream *stream, int version, QShaderDesc } } -static QShaderDescription::InOutVariable deserializeInOutVar(QDataStream *stream, int version) +static QShaderDescription::BuiltinVariable deserializeBuiltinVar(QDataStream *stream, int version) { - QShaderDescription::InOutVariable var; - QString tmp; - (*stream) >> tmp; - var.name = tmp.toUtf8(); + QShaderDescription::BuiltinVariable var; int t; (*stream) >> t; - var.type = QShaderDescription::VariableType(t); - deserializeDecorations(stream, version, &var); + var.type = QShaderDescription::BuiltinType(t); + if (version > QShaderPrivate::QSB_VERSION_WITHOUT_INPUT_OUTPUT_INTERFACE_BLOCKS) { + (*stream) >> t; + var.varType = QShaderDescription::VariableType(t); + int count; + (*stream) >> count; + var.arrayDims.resize(count); + for (int i = 0; i < count; ++i) + (*stream) >> var.arrayDims[i]; + } return var; } @@ -1457,6 +1802,26 @@ static QShaderDescription::BlockVariable deserializeBlockMemberVar(QDataStream * return var; } +static QShaderDescription::InOutVariable deserializeInOutVar(QDataStream *stream, int version) +{ + QShaderDescription::InOutVariable var; + QString tmp; + (*stream) >> tmp; + var.name = tmp.toUtf8(); + int t; + (*stream) >> t; + var.type = QShaderDescription::VariableType(t); + deserializeDecorations(stream, version, &var); + if (version > QShaderPrivate::QSB_VERSION_WITHOUT_INPUT_OUTPUT_INTERFACE_BLOCKS) { + int count; + (*stream) >> count; + var.structMembers.resize(count); + for (int i = 0; i < count; ++i) + var.structMembers[i] = deserializeBlockMemberVar(stream, version); + } + return var; +} + void QShaderDescriptionPrivate::loadFromStream(QDataStream *stream, int version) { Q_ASSERT(ref.loadRelaxed() == 1); // must be detached @@ -1596,19 +1961,13 @@ void QShaderDescriptionPrivate::loadFromStream(QDataStream *stream, int version) (*stream) >> count; inBuiltins.resize(count); - for (int i = 0; i < count; ++i) { - int t; - (*stream) >> t; - inBuiltins[i].type = QShaderDescription::BuiltinType(t); - } + for (int i = 0; i < count; ++i) + inBuiltins[i] = deserializeBuiltinVar(stream, version); (*stream) >> count; outBuiltins.resize(count); - for (int i = 0; i < count; ++i) { - int t; - (*stream) >> t; - outBuiltins[i].type = QShaderDescription::BuiltinType(t); - } + for (int i = 0; i < count; ++i) + outBuiltins[i] = deserializeBuiltinVar(stream, version); } } @@ -1657,7 +2016,8 @@ bool operator==(const QShaderDescription::InOutVariable &lhs, const QShaderDescr && lhs.imageFormat == rhs.imageFormat && lhs.imageFlags == rhs.imageFlags && lhs.arrayDims == rhs.arrayDims - && lhs.perPatch == rhs.perPatch; + && lhs.perPatch == rhs.perPatch + && lhs.structMembers == rhs.structMembers; } /*! @@ -1734,7 +2094,9 @@ bool operator==(const QShaderDescription::StorageBlock &lhs, const QShaderDescri */ bool operator==(const QShaderDescription::BuiltinVariable &lhs, const QShaderDescription::BuiltinVariable &rhs) noexcept { - return lhs.type == rhs.type; + return lhs.type == rhs.type + && lhs.varType == rhs.varType + && lhs.arrayDims == rhs.arrayDims; } QT_END_NAMESPACE |