65 int jsonStart = 0, jsonEnd = 0;
74 if (jsonStart <= 0 || jsonEnd <= 0)
77 const int size = jsonEnd - jsonStart;
80 qWarning(
"Shader metadata section found, but content to small to be valid!");
84 QByteArray jsonData = data.mid(jsonStart, size).trimmed();
85 if (!jsonData.startsWith(QByteArrayLiteral(
"/*{"))) {
86 qWarning(
"Missing /*{ prefix");
89 if (!jsonData.endsWith(QByteArrayLiteral(
"}*/"))) {
90 qWarning(
"Missing }*/ suffix");
93 jsonData = jsonData.mid(2, jsonData.size() - 4);
95 QJsonParseError error;
96 const auto doc = QJsonDocument::fromJson(jsonData, &error);
97 if (error.error != QJsonParseError::NoError) {
98 qWarning() <<
"Shader metadata parse error at offset: " << error.offset;
102 static const auto toUniform = [](
const QJsonObject &uObj) {
104 auto it = uObj.constBegin();
105 const auto end = uObj.constEnd();
107 it = uObj.constFind(QLatin1String(
"type"));
108 uniform.type = (it != end) ? it->toString().toLatin1() : QByteArray();
109 it = uObj.constFind(QLatin1String(
"name"));
110 uniform.name = (it != end) ? it->toString().toLatin1() : QByteArray();
111 it = uObj.constFind(QLatin1String(
"multiview_dependent"));
112 uniform
.multiview = (it != end) ? it->toBool() :
false;
114 it = uObj.constFind(QLatin1String(
"condition"));
115 const QString conditionString = (it != end) ? it->toString() : QString();
116 uniform.condition = Uniform::conditionFromString(conditionString);
118 uniform.conditionName = conditionString.mid(1).toLatin1();
120 uniform.conditionName = conditionString.toLatin1();
125 static const auto toImage = [](
const QJsonObject &uObj,
const Uniform &uniform)
128 auto it = uObj.constBegin();
129 const auto end = uObj.constEnd();
131 it = uObj.constFind(QLatin1String(
"imgtype"));
132 img.imageType = (it != end) ? it->toString().toLatin1() : QByteArray();
133 it = uObj.constFind(QLatin1String(
"qualifiers"));
134 img.qualifiers = (it != end) ? it->toString().toLatin1() : QByteArray();
139 static const auto toInputOutput = [](
const QJsonObject &uObj) {
141 auto it = uObj.constBegin();
142 const auto end = uObj.constEnd();
144 it = uObj.constFind(QLatin1String(
"type"));
145 inOutVar.type = (it != end) ? it->toString().toLatin1() : QByteArray();
146 it = uObj.constFind(QLatin1String(
"name"));
147 inOutVar.name = (it != end) ? it->toString().toLatin1() : QByteArray();
148 it = uObj.constFind(QLatin1String(
"stage"));
149 inOutVar.stage = InputOutput::stageFromString((it != end) ? it->toString() : QString());
150 it = uObj.constFind(QLatin1String(
"flat"));
151 inOutVar
.flat = (it != end) ? it->toBool() :
false;
156 const QJsonObject obj = doc.object();
157 auto it = obj.constBegin();
158 const auto end = obj.constEnd();
161 it = obj.constFind(QLatin1String(
"uniforms"));
162 if (it != obj.constEnd()) {
164 if (it->type() == QJsonValue::Array) {
165 const auto uniformArray = it->toArray();
166 for (
const auto valueRef : uniformArray) {
167 if (!valueRef.isObject())
170 const QJsonObject obj = valueRef.toObject();
171 const auto uniform = toUniform(obj);
172 if (!uniform.type.isEmpty() && !uniform.name.isEmpty()) {
173 if (obj.constFind(QLatin1String(
"imgtype")) != obj.constEnd())
174 result.images.push_back(toImage(obj, uniform));
176 result.uniforms.push_back(uniform);
178 qWarning(
"Invalid uniform, skipping");
181 }
else if (it->type() == QJsonValue::Object) {
182 const auto uniform = toUniform(it->toObject());
183 if (!uniform.type.isEmpty() && !uniform.name.isEmpty()) {
184 if (obj.constFind(QLatin1String(
"imgtype")) != obj.constEnd())
185 result.images.push_back(toImage(obj, uniform));
187 result.uniforms.push_back(uniform);
189 qWarning(
"Invalid uniform, skipping");
195 it = obj.constFind(QLatin1String(
"inputs"));
197 if (it->type() == QJsonValue::Array) {
198 const auto array = it->toArray();
199 for (
const auto &valueRef : array) {
200 if (!valueRef.isObject())
202 const auto inOutVar = toInputOutput(valueRef.toObject());
203 if (!inOutVar.type.isEmpty() && !inOutVar.name.isEmpty())
204 result.inputs.push_back(inOutVar);
206 qWarning(
"Invalid input variable, skipping");
208 }
else if (it->type() == QJsonValue::Object) {
209 const QJsonObject obj = it->toObject();
210 const auto inOutVar = toInputOutput(obj);
211 if (!inOutVar.type.isEmpty() && !inOutVar.name.isEmpty()) {
212 result.inputs.push_back(inOutVar);
214 qWarning(
"Invalid input variable, skipping");
220 it = obj.constFind(QLatin1String(
"outputs"));
222 if (it->type() == QJsonValue::Array) {
223 const auto array = it->toArray();
224 for (
const auto &valueRef : array) {
225 if (!valueRef.isObject())
227 const auto inOutVar = toInputOutput(valueRef.toObject());
228 if (!inOutVar.type.isEmpty() && !inOutVar.name.isEmpty())
229 result.outputs.push_back(inOutVar);
231 qWarning(
"Invalid output variable, skipping");
233 }
else if (it->type() == QJsonValue::Object) {
234 const QJsonObject inputJObj = it->toObject();
235 const auto inOutVar = toInputOutput(inputJObj);
236 if (!inOutVar.type.isEmpty() && !inOutVar.name.isEmpty()) {
237 result.outputs.push_back(inOutVar);
239 qWarning(
"Invalid output variable, skipping");