summaryrefslogtreecommitdiffstats
path: root/src/gui/rhi/qshaderdescription.cpp
diff options
context:
space:
mode:
authorBen Fletcher <ben.fletcher@me.com>2023-02-16 16:46:22 -0800
committerBen Fletcher <ben.fletcher@me.com>2023-03-09 15:24:45 +0000
commit4201cdab1886b5c39fe722a95e1b0ba462b63b71 (patch)
tree242bec9a73e8bb0e09fbdc74c8f2fabd98b7eba1 /src/gui/rhi/qshaderdescription.cpp
parent17c9001a53a2377cc38bdf4b1982cab2dca94573 (diff)
rhi: Metal tessellation shader input output interface blocks
Add support for shader input output interface blocks in Metal tessellation pipelines. This feature is builtin to other rhi supported tessellation backends (OpenGL/Vulkan). Metal tessellation is implemented as compute pipelines for vert and tesc, and a render pipeline for tese and frag. The shader conversion from GLSL is handled by SPIRV-Cross, which has a particular way of doing things. Rhi must setup the vertex inputs for the tese - frag render pipeline to read from buffers written by the tesc compute pipeline, following SPIRV-Cross conventions. This includes ensuring correct memory alignment per MSL Specification. In order to enable input output interface blocks, reflection of struct members of QShaderDescription::InOutVariable is required. Reflection of QShaderDescription::BuiltinVariable array dimensions is also required to support variable size tese builtin input gl_ClipDistance. An acompanying patch to QtShaderTools is required. Change-Id: Id94e86caef211485afc187bb79fe3d0619d02cf0 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
Diffstat (limited to 'src/gui/rhi/qshaderdescription.cpp')
-rw-r--r--src/gui/rhi/qshaderdescription.cpp165
1 files changed, 116 insertions, 49 deletions
diff --git a/src/gui/rhi/qshaderdescription.cpp b/src/gui/rhi/qshaderdescription.cpp
index ca697d8edb..44fcd936fd 100644
--- a/src/gui/rhi/qshaderdescription.cpp
+++ b/src/gui/rhi/qshaderdescription.cpp
@@ -724,8 +724,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 +940,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 +949,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 +1008,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 +1094,15 @@ static void serializeDecorations(QDataStream *stream, const QShaderDescription::
(*stream) << quint8(v.perPatch);
}
-static QJsonObject inOutObject(const QShaderDescription::InOutVariable &v)
-{
- 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)
+static void serializeBuiltinVar(QDataStream *stream, const QShaderDescription::BuiltinVariable &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 +1110,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 +1134,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 +1181,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 +1289,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 +1430,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 +1463,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 +1507,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 +1666,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 +1721,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 +1799,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