Support serializing the QShader for qsb version
Support serializing shaders with specific qsb version. The default behavior remains the same, using the latest version. Task-number: QTBUG-101062 Pick-to: 6.5 Change-Id: I090a88c1ccb3be4ac5eee1da4058afaa8bf3111c Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
This commit is contained in:
parent
90751ff13d
commit
df00f9ea86
@ -365,9 +365,12 @@ static void writeShaderKey(QDataStream *ds, const QShaderKey &k)
|
||||
\return a serialized binary version of all the data held by the
|
||||
QShader, suitable for writing to files or other I/O devices.
|
||||
|
||||
By default the latest serialization format is used. Use \a version
|
||||
parameter to serialize for a compatibility Qt version.
|
||||
|
||||
\sa fromSerialized()
|
||||
*/
|
||||
QByteArray QShader::serialized() const
|
||||
QByteArray QShader::serialized(SerializedFormatVersion version) const
|
||||
{
|
||||
static QShaderPrivate sd;
|
||||
QShaderPrivate *dd = d ? d : &sd;
|
||||
@ -378,9 +381,11 @@ QByteArray QShader::serialized() const
|
||||
if (!buf.open(QIODevice::WriteOnly))
|
||||
return QByteArray();
|
||||
|
||||
ds << QShaderPrivate::QSB_VERSION;
|
||||
const int qsbVersion = QShaderPrivate::qtQsbVersion(version);
|
||||
ds << qsbVersion;
|
||||
|
||||
ds << int(dd->stage);
|
||||
dd->desc.serialize(&ds);
|
||||
dd->desc.serialize(&ds, qsbVersion);
|
||||
ds << int(dd->shaders.size());
|
||||
for (auto it = dd->shaders.cbegin(), itEnd = dd->shaders.cend(); it != itEnd; ++it) {
|
||||
const QShaderKey &k(it.key());
|
||||
@ -413,17 +418,19 @@ QByteArray QShader::serialized() const
|
||||
ds << listIt->samplerBinding;
|
||||
}
|
||||
}
|
||||
ds << int(dd->nativeShaderInfoMap.size());
|
||||
for (auto it = dd->nativeShaderInfoMap.cbegin(), itEnd = dd->nativeShaderInfoMap.cend(); it != itEnd; ++it) {
|
||||
const QShaderKey &k(it.key());
|
||||
writeShaderKey(&ds, k);
|
||||
ds << it->flags;
|
||||
ds << int(it->extraBufferBindings.size());
|
||||
for (auto mapIt = it->extraBufferBindings.cbegin(), mapItEnd = it->extraBufferBindings.cend();
|
||||
mapIt != mapItEnd; ++mapIt)
|
||||
{
|
||||
ds << mapIt.key();
|
||||
ds << mapIt.value();
|
||||
if (qsbVersion > QShaderPrivate::QSB_VERSION_WITHOUT_NATIVE_SHADER_INFO) {
|
||||
ds << int(dd->nativeShaderInfoMap.size());
|
||||
for (auto it = dd->nativeShaderInfoMap.cbegin(), itEnd = dd->nativeShaderInfoMap.cend(); it != itEnd; ++it) {
|
||||
const QShaderKey &k(it.key());
|
||||
writeShaderKey(&ds, k);
|
||||
ds << it->flags;
|
||||
ds << int(it->extraBufferBindings.size());
|
||||
for (auto mapIt = it->extraBufferBindings.cbegin(), mapItEnd = it->extraBufferBindings.cend();
|
||||
mapIt != mapItEnd; ++mapIt)
|
||||
{
|
||||
ds << mapIt.key();
|
||||
ds << mapIt.value();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -110,6 +110,12 @@ public:
|
||||
NonIndexedVertexAsComputeShader
|
||||
};
|
||||
|
||||
enum class SerializedFormatVersion {
|
||||
Latest = 0,
|
||||
Qt_6_5,
|
||||
Qt_6_4
|
||||
};
|
||||
|
||||
QShader();
|
||||
QShader(const QShader &other);
|
||||
QShader &operator=(const QShader &other);
|
||||
@ -129,7 +135,7 @@ public:
|
||||
void setShader(const QShaderKey &key, const QShaderCode &shader);
|
||||
void removeShader(const QShaderKey &key);
|
||||
|
||||
QByteArray serialized() const;
|
||||
QByteArray serialized(SerializedFormatVersion version = SerializedFormatVersion::Latest) const;
|
||||
static QShader fromSerialized(const QByteArray &data);
|
||||
|
||||
using NativeResourceBindingMap = QMap<int, QPair<int, int> >; // binding -> native_binding[, native_binding]
|
||||
|
@ -61,6 +61,16 @@ struct Q_GUI_EXPORT QShaderPrivate
|
||||
|
||||
static QShaderPrivate *get(QShader *s) { return s->d; }
|
||||
static const QShaderPrivate *get(const QShader *s) { return s->d; }
|
||||
static int qtQsbVersion(QShader::SerializedFormatVersion qtVersion) {
|
||||
switch (qtVersion) {
|
||||
case QShader::SerializedFormatVersion::Qt_6_4:
|
||||
return (QShaderPrivate::QSB_VERSION_WITHOUT_SEPARATE_IMAGES_AND_SAMPLERS + 1);
|
||||
case QShader::SerializedFormatVersion::Qt_6_5:
|
||||
return (QShaderPrivate::QSB_VERSION_WITHOUT_EXTENDED_STORAGE_BUFFER_INFO + 1);
|
||||
default:
|
||||
return QShaderPrivate::QSB_VERSION;
|
||||
}
|
||||
}
|
||||
|
||||
QAtomicInt ref;
|
||||
int qsbVersion = QSB_VERSION;
|
||||
|
@ -319,13 +319,14 @@ QByteArray QShaderDescription::toJson() const
|
||||
}
|
||||
|
||||
/*!
|
||||
Serializes this QShaderDescription to \a stream.
|
||||
Serializes this QShaderDescription to \a stream. \a version specifies
|
||||
the qsb version.
|
||||
|
||||
\sa deserialize(), toJson()
|
||||
*/
|
||||
void QShaderDescription::serialize(QDataStream *stream) const
|
||||
void QShaderDescription::serialize(QDataStream *stream, int version) const
|
||||
{
|
||||
d->writeToStream(stream);
|
||||
d->writeToStream(stream, version);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -1067,7 +1068,7 @@ static void addDeco(QJsonObject *obj, const QShaderDescription::InOutVariable &v
|
||||
}
|
||||
}
|
||||
|
||||
static void serializeDecorations(QDataStream *stream, const QShaderDescription::InOutVariable &v)
|
||||
static void serializeDecorations(QDataStream *stream, const QShaderDescription::InOutVariable &v, int version)
|
||||
{
|
||||
(*stream) << v.location;
|
||||
(*stream) << v.binding;
|
||||
@ -1077,7 +1078,8 @@ static void serializeDecorations(QDataStream *stream, const QShaderDescription::
|
||||
(*stream) << int(v.arrayDims.size());
|
||||
for (int dim : v.arrayDims)
|
||||
(*stream) << dim;
|
||||
(*stream) << quint8(v.perPatch);
|
||||
if (version > QShaderPrivate::QSB_VERSION_WITHOUT_NATIVE_SHADER_INFO)
|
||||
(*stream) << quint8(v.perPatch);
|
||||
}
|
||||
|
||||
static QJsonObject inOutObject(const QShaderDescription::InOutVariable &v)
|
||||
@ -1089,11 +1091,11 @@ static QJsonObject inOutObject(const QShaderDescription::InOutVariable &v)
|
||||
return obj;
|
||||
}
|
||||
|
||||
static void serializeInOutVar(QDataStream *stream, const QShaderDescription::InOutVariable &v)
|
||||
static void serializeInOutVar(QDataStream *stream, const QShaderDescription::InOutVariable &v, int version)
|
||||
{
|
||||
(*stream) << QString::fromUtf8(v.name);
|
||||
(*stream) << int(v.type);
|
||||
serializeDecorations(stream, v);
|
||||
serializeDecorations(stream, v, version);
|
||||
}
|
||||
|
||||
static QJsonObject blockMemberObject(const QShaderDescription::BlockVariable &v)
|
||||
@ -1297,15 +1299,15 @@ QJsonDocument QShaderDescriptionPrivate::makeDoc()
|
||||
return QJsonDocument(root);
|
||||
}
|
||||
|
||||
void QShaderDescriptionPrivate::writeToStream(QDataStream *stream)
|
||||
void QShaderDescriptionPrivate::writeToStream(QDataStream *stream, int version)
|
||||
{
|
||||
(*stream) << int(inVars.size());
|
||||
for (const QShaderDescription::InOutVariable &v : std::as_const(inVars))
|
||||
serializeInOutVar(stream, v);
|
||||
serializeInOutVar(stream, v, version);
|
||||
|
||||
(*stream) << int(outVars.size());
|
||||
for (const QShaderDescription::InOutVariable &v : std::as_const(outVars))
|
||||
serializeInOutVar(stream, v);
|
||||
serializeInOutVar(stream, v, version);
|
||||
|
||||
(*stream) << int(uniformBlocks.size());
|
||||
for (const QShaderDescription::UniformBlock &b : uniformBlocks) {
|
||||
@ -1338,22 +1340,24 @@ void QShaderDescriptionPrivate::writeToStream(QDataStream *stream)
|
||||
(*stream) << int(b.members.size());
|
||||
for (const QShaderDescription::BlockVariable &v : b.members)
|
||||
serializeBlockMemberVar(stream, v);
|
||||
(*stream) << b.runtimeArrayStride;
|
||||
(*stream) << b.qualifierFlags;
|
||||
if (version > QShaderPrivate::QSB_VERSION_WITHOUT_EXTENDED_STORAGE_BUFFER_INFO) {
|
||||
(*stream) << b.runtimeArrayStride;
|
||||
(*stream) << b.qualifierFlags;
|
||||
}
|
||||
}
|
||||
|
||||
(*stream) << int(combinedImageSamplers.size());
|
||||
for (const QShaderDescription::InOutVariable &v : std::as_const(combinedImageSamplers)) {
|
||||
(*stream) << QString::fromUtf8(v.name);
|
||||
(*stream) << int(v.type);
|
||||
serializeDecorations(stream, v);
|
||||
serializeDecorations(stream, v, version);
|
||||
}
|
||||
|
||||
(*stream) << int(storageImages.size());
|
||||
for (const QShaderDescription::InOutVariable &v : std::as_const(storageImages)) {
|
||||
(*stream) << QString::fromUtf8(v.name);
|
||||
(*stream) << int(v.type);
|
||||
serializeDecorations(stream, v);
|
||||
serializeDecorations(stream, v, version);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < 3; ++i)
|
||||
@ -1363,28 +1367,30 @@ void QShaderDescriptionPrivate::writeToStream(QDataStream *stream)
|
||||
for (const QShaderDescription::InOutVariable &v : std::as_const(separateImages)) {
|
||||
(*stream) << QString::fromUtf8(v.name);
|
||||
(*stream) << int(v.type);
|
||||
serializeDecorations(stream, v);
|
||||
serializeDecorations(stream, v, version);
|
||||
}
|
||||
|
||||
(*stream) << int(separateSamplers.size());
|
||||
for (const QShaderDescription::InOutVariable &v : std::as_const(separateSamplers)) {
|
||||
(*stream) << QString::fromUtf8(v.name);
|
||||
(*stream) << int(v.type);
|
||||
serializeDecorations(stream, v);
|
||||
serializeDecorations(stream, v, version);
|
||||
}
|
||||
|
||||
(*stream) << quint32(tessOutVertCount);
|
||||
(*stream) << quint32(tessMode);
|
||||
(*stream) << quint32(tessWind);
|
||||
(*stream) << quint32(tessPart);
|
||||
if (version > QShaderPrivate::QSB_VERSION_WITHOUT_NATIVE_SHADER_INFO) {
|
||||
(*stream) << quint32(tessOutVertCount);
|
||||
(*stream) << quint32(tessMode);
|
||||
(*stream) << quint32(tessWind);
|
||||
(*stream) << quint32(tessPart);
|
||||
|
||||
(*stream) << int(inBuiltins.size());
|
||||
for (const QShaderDescription::BuiltinVariable &v : std::as_const(inBuiltins))
|
||||
(*stream) << int(v.type);
|
||||
(*stream) << int(inBuiltins.size());
|
||||
for (const QShaderDescription::BuiltinVariable &v : std::as_const(inBuiltins))
|
||||
(*stream) << int(v.type);
|
||||
|
||||
(*stream) << int(outBuiltins.size());
|
||||
for (const QShaderDescription::BuiltinVariable &v : std::as_const(outBuiltins))
|
||||
(*stream) << int(v.type);
|
||||
(*stream) << int(outBuiltins.size());
|
||||
for (const QShaderDescription::BuiltinVariable &v : std::as_const(outBuiltins))
|
||||
(*stream) << int(v.type);
|
||||
}
|
||||
}
|
||||
|
||||
static void deserializeDecorations(QDataStream *stream, int version, QShaderDescription::InOutVariable *v)
|
||||
|
@ -37,7 +37,7 @@ public:
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
void serialize(QDataStream *stream) const;
|
||||
void serialize(QDataStream *stream, int version) const;
|
||||
QByteArray toJson() const;
|
||||
|
||||
static QShaderDescription deserialize(QDataStream *stream, int version);
|
||||
|
@ -54,7 +54,7 @@ struct Q_GUI_EXPORT QShaderDescriptionPrivate
|
||||
static const QShaderDescriptionPrivate *get(const QShaderDescription *desc) { return desc->d; }
|
||||
|
||||
QJsonDocument makeDoc();
|
||||
void writeToStream(QDataStream *stream);
|
||||
void writeToStream(QDataStream *stream, int version);
|
||||
void loadFromStream(QDataStream *stream, int version);
|
||||
|
||||
QAtomicInt ref;
|
||||
|
@ -294,7 +294,7 @@ void tst_QShader::serializeShaderDesc()
|
||||
QBuffer buf(&data);
|
||||
QDataStream ds(&buf);
|
||||
QVERIFY(buf.open(QIODevice::WriteOnly));
|
||||
desc.serialize(&ds);
|
||||
desc.serialize(&ds, QShaderPrivate::QSB_VERSION);
|
||||
}
|
||||
QVERIFY(!data.isEmpty());
|
||||
|
||||
@ -319,7 +319,7 @@ void tst_QShader::serializeShaderDesc()
|
||||
QBuffer buf(&data);
|
||||
QDataStream ds(&buf);
|
||||
QVERIFY(buf.open(QIODevice::WriteOnly));
|
||||
desc.serialize(&ds);
|
||||
desc.serialize(&ds, QShaderPrivate::QSB_VERSION);
|
||||
}
|
||||
QVERIFY(!data.isEmpty());
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user