1 /****************************************************************************
2 **
3 ** Copyright (C) 2008-2012 NVIDIA Corporation.
4 ** Copyright (C) 2019 The Qt Company Ltd.
5 ** Contact: https://www.qt.io/licensing/
6 **
7 ** This file is part of Qt Quick 3D.
8 **
9 ** $QT_BEGIN_LICENSE:GPL$
10 ** Commercial License Usage
11 ** Licensees holding valid commercial Qt licenses may use this file in
12 ** accordance with the commercial license agreement provided with the
13 ** Software or, alternatively, in accordance with the terms contained in
14 ** a written agreement between you and The Qt Company. For licensing terms
15 ** and conditions see https://www.qt.io/terms-conditions. For further
16 ** information use the contact form at https://www.qt.io/contact-us.
17 **
18 ** GNU General Public License Usage
19 ** Alternatively, this file may be used under the terms of the GNU
20 ** General Public License version 3 or (at your option) any later version
21 ** approved by the KDE Free Qt Foundation. The licenses are as published by
22 ** the Free Software Foundation and appearing in the file LICENSE.GPL3
23 ** included in the packaging of this file. Please review the following
24 ** information to ensure the GNU General Public License requirements will
25 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
26 **
27 ** $QT_END_LICENSE$
28 **
29 ****************************************************************************/
30
31 #ifndef QSSG_RENDER_SHADER_KEY_H
32 #define QSSG_RENDER_SHADER_KEY_H
33
34 //
35 // W A R N I N G
36 // -------------
37 //
38 // This file is not part of the Qt API. It exists purely as an
39 // implementation detail. This header file may change from version to
40 // version without notice, or even be removed.
41 //
42 // We mean it.
43 //
44
45 #include <QtQuick3DUtils/private/qssgdataref_p.h>
46
47 #include <QtQuick3DRender/private/qssgrenderbasetypes_p.h>
48
49 #include <QtQuick3DRuntimeRender/private/qssgrenderdefaultmaterial_p.h>
50 #include <QtQuick3DRuntimeRender/private/qssgrendertessmodevalues_p.h>
51
52 QT_BEGIN_NAMESPACE
53 // We have an ever expanding set of properties we like to hash into one or more 32 bit
54 // quantities.
55 // Furthermore we would like this set of properties to be convertable to string
56 // So the shader cache file itself is somewhat human readable/diagnosable.
57 // To do this we create a set of objects that act as properties to the master shader key.
58 // These objects are tallied in order to figure out their actual offset into the shader key's
59 // data store. They are also run through in order to create the string shader cache key.
60
61 struct QSSGShaderKeyPropertyBase
62 {
63 const char *name;
64 quint32 offset;
nameQSSGShaderKeyPropertyBase65 QSSGShaderKeyPropertyBase(const char *inName = "") : name(inName), offset(0) {}
getOffsetQSSGShaderKeyPropertyBase66 quint32 getOffset() const { return offset; }
setOffsetQSSGShaderKeyPropertyBase67 void setOffset(quint32 of) { offset = of; }
68
69 template<quint32 TBitWidth>
getMaskTemplateQSSGShaderKeyPropertyBase70 quint32 getMaskTemplate() const
71 {
72 quint32 bit = offset % 32;
73 quint32 startValue = (1 << TBitWidth) - 1;
74 quint32 mask = startValue << bit;
75 return mask;
76 }
77
getIdxQSSGShaderKeyPropertyBase78 quint32 getIdx() const { return offset / 32; }
79
80 protected:
internalToStringQSSGShaderKeyPropertyBase81 void internalToString(QString &ioStr, const char *inBuffer) const
82 {
83 ioStr.append(QString::fromLocal8Bit(name));
84 ioStr.append(QStringLiteral("="));
85 ioStr.append(QString::fromLocal8Bit(inBuffer));
86 }
87
internalToStringQSSGShaderKeyPropertyBase88 static void internalToString(QString &ioStr, const char *name, bool inValue)
89 {
90 if (inValue) {
91 ioStr.append(QString::fromLocal8Bit(name));
92 ioStr.append(QStringLiteral("="));
93 ioStr.append(inValue ? QStringLiteral("true") : QStringLiteral("false"));
94 }
95 }
96 };
97
98 struct QSSGShaderKeyBoolean : public QSSGShaderKeyPropertyBase
99 {
100 enum {
101 BitWidth = 1,
102 };
103
QSSGShaderKeyPropertyBaseQSSGShaderKeyBoolean104 QSSGShaderKeyBoolean(const char *inName = "") : QSSGShaderKeyPropertyBase(inName) {}
105
getMaskQSSGShaderKeyBoolean106 quint32 getMask() const { return getMaskTemplate<BitWidth>(); }
setValueQSSGShaderKeyBoolean107 void setValue(QSSGDataRef<quint32> inDataStore, bool inValue) const
108 {
109 const qint32 idx = qint32(getIdx());
110 Q_ASSERT(idx >= 0 && idx <= INT32_MAX);
111 Q_ASSERT(inDataStore.size() > idx);
112 quint32 mask = getMask();
113 quint32 &target = inDataStore[idx];
114 if (inValue) {
115 target = target | mask;
116 } else {
117 mask = ~mask;
118 target = target & mask;
119 }
120 }
121
getValueQSSGShaderKeyBoolean122 bool getValue(QSSGDataView<quint32> inDataStore) const
123 {
124 quint32 idx = getIdx();
125 quint32 mask = getMask();
126 const quint32 &target = inDataStore[idx];
127 return (target & mask) ? true : false;
128 }
129
toStringQSSGShaderKeyBoolean130 void toString(QString &ioStr, QSSGDataView<quint32> inKeySet) const
131 {
132 bool isHigh = getValue(inKeySet);
133 internalToString(ioStr, name, isHigh);
134 }
135 };
136
137 template<quint32 TBitWidth>
138 struct QSSGShaderKeyUnsigned : public QSSGShaderKeyPropertyBase
139 {
140 enum {
141 BitWidth = TBitWidth,
142 };
QSSGShaderKeyPropertyBaseQSSGShaderKeyUnsigned143 QSSGShaderKeyUnsigned(const char *inName = "") : QSSGShaderKeyPropertyBase(inName) {}
getMaskQSSGShaderKeyUnsigned144 quint32 getMask() const { return getMaskTemplate<BitWidth>(); }
setValueQSSGShaderKeyUnsigned145 void setValue(QSSGDataRef<quint32> inDataStore, quint32 inValue) const
146 {
147 quint32 startValue = (1 << TBitWidth) - 1;
148 // Ensure inValue is within range of bit width.
149 inValue = inValue & startValue;
150 quint32 bit = offset % 32;
151 quint32 mask = getMask();
152 quint32 idx = getIdx();
153 inValue = inValue << bit;
154 quint32 &target = inDataStore[idx];
155 // Get rid of existing value
156 quint32 inverseMask = ~mask;
157 target = target & inverseMask;
158 target = target | inValue;
159 }
160
getValueQSSGShaderKeyUnsigned161 quint32 getValue(QSSGDataView<quint32> inDataStore) const
162 {
163 quint32 idx = getIdx();
164 quint32 bit = offset % 32;
165 quint32 mask = getMask();
166 const quint32 &target = inDataStore[idx];
167
168 quint32 retval = target & mask;
169 retval = retval >> bit;
170 return retval;
171 }
172
toStringQSSGShaderKeyUnsigned173 void toString(QString &ioStr, QSSGDataView<quint32> inKeySet) const
174 {
175 quint32 value = getValue(inKeySet);
176 char buf[64];
177 toStr(value, toDataRef(buf, 64));
178 internalToString(ioStr, buf);
179 }
180
181 private:
toStrQSSGShaderKeyUnsigned182 static quint32 toStr(quint32 item, QSSGDataRef<char> buffer)
183 {
184 // hope the buffer is big enough...
185 return static_cast<quint32>(::snprintf(buffer.begin(), buffer.size(), "%u", item));
186 }
187 };
188
189 struct QSSGShaderKeyTessellation : public QSSGShaderKeyUnsigned<4>
190 {
191 enum TessellationBits {
192 noTessellation = 1 << 0,
193 linearTessellation = 1 << 1,
194 phongTessellation = 1 << 2,
195 npatchTessellation = 1 << 3
196 };
197
198 QSSGShaderKeyTessellation(const char *inName = "") : QSSGShaderKeyUnsigned<4>(inName) {}
199
getBitValueQSSGShaderKeyTessellation200 bool getBitValue(TessellationBits swizzleBit, QSSGDataView<quint32> inKeySet) const
201 {
202 return (getValue(inKeySet) & swizzleBit) ? true : false;
203 }
204
setBitValueQSSGShaderKeyTessellation205 void setBitValue(TessellationBits swizzleBit, bool inValue, QSSGDataRef<quint32> inKeySet)
206 {
207 quint32 theValue = getValue(inKeySet);
208 quint32 mask = swizzleBit;
209 if (inValue) {
210 theValue = theValue | mask;
211 } else {
212 mask = ~mask;
213 theValue = theValue & mask;
214 }
215 setValue(inKeySet, theValue);
216 }
217
setTessellationModeQSSGShaderKeyTessellation218 void setTessellationMode(QSSGDataRef<quint32> inKeySet, TessellationModeValues tessellationMode, bool val)
219 {
220 switch (tessellationMode) {
221 case TessellationModeValues::NoTessellation:
222 setBitValue(noTessellation, val, inKeySet);
223 break;
224 case TessellationModeValues::Linear:
225 setBitValue(linearTessellation, val, inKeySet);
226 break;
227 case TessellationModeValues::NPatch:
228 setBitValue(npatchTessellation, val, inKeySet);
229 break;
230 case TessellationModeValues::Phong:
231 setBitValue(phongTessellation, val, inKeySet);
232 break;
233 }
234 }
235
isNoTessellationQSSGShaderKeyTessellation236 bool isNoTessellation(QSSGDataView<quint32> inKeySet) const { return getBitValue(noTessellation, inKeySet); }
setNoTessellationQSSGShaderKeyTessellation237 void setNoTessellation(QSSGDataRef<quint32> inKeySet, bool val) { setBitValue(noTessellation, val, inKeySet); }
238
isLinearTessellationQSSGShaderKeyTessellation239 bool isLinearTessellation(QSSGDataView<quint32> inKeySet) const
240 {
241 return getBitValue(linearTessellation, inKeySet);
242 }
setLinearTessellationQSSGShaderKeyTessellation243 void setLinearTessellation(QSSGDataRef<quint32> inKeySet, bool val)
244 {
245 setBitValue(linearTessellation, val, inKeySet);
246 }
247
isNPatchTessellationQSSGShaderKeyTessellation248 bool isNPatchTessellation(QSSGDataView<quint32> inKeySet) const
249 {
250 return getBitValue(npatchTessellation, inKeySet);
251 }
setNPatchTessellationQSSGShaderKeyTessellation252 void setNPatchTessellation(QSSGDataRef<quint32> inKeySet, bool val)
253 {
254 setBitValue(npatchTessellation, val, inKeySet);
255 }
256
isPhongTessellationQSSGShaderKeyTessellation257 bool isPhongTessellation(QSSGDataView<quint32> inKeySet) const
258 {
259 return getBitValue(phongTessellation, inKeySet);
260 }
setPhongTessellationQSSGShaderKeyTessellation261 void setPhongTessellation(QSSGDataRef<quint32> inKeySet, bool val)
262 {
263 setBitValue(phongTessellation, val, inKeySet);
264 }
265
toStringQSSGShaderKeyTessellation266 void toString(QString &ioStr, QSSGDataView<quint32> inKeySet) const
267 {
268 ioStr.append(QString::fromLocal8Bit(name));
269 ioStr.append(QStringLiteral("={"));
270 internalToString(ioStr, "noTessellation", isNoTessellation(inKeySet));
271 ioStr.append(QStringLiteral(";"));
272 internalToString(ioStr, "linearTessellation", isLinearTessellation(inKeySet));
273 ioStr.append(QStringLiteral(";"));
274 internalToString(ioStr, "npatchTessellation", isNPatchTessellation(inKeySet));
275 ioStr.append(QStringLiteral(";"));
276 internalToString(ioStr, "phongTessellation", isPhongTessellation(inKeySet));
277 ioStr.append(QStringLiteral("}"));
278 }
279 };
280
281 struct QSSGShaderKeyTextureChannel : public QSSGShaderKeyUnsigned<2>
282 {
283 enum TexturChannelBits {
284 R = 0,
285 G = 1,
286 B = 2,
287 A = 3,
288 };
289 QSSGShaderKeyTextureChannel(const char *inName = "") : QSSGShaderKeyUnsigned<2>(inName) {}
290
getTextureChannelQSSGShaderKeyTextureChannel291 TexturChannelBits getTextureChannel(QSSGDataView<quint32> inKeySet) const
292 {
293 return TexturChannelBits(getValue(inKeySet));
294 }
295
setTextureChannelQSSGShaderKeyTextureChannel296 void setTextureChannel(TexturChannelBits channel, QSSGDataRef<quint32> inKeySet)
297 {
298 setValue(inKeySet, quint32(channel));
299 }
300 const QString enumToStr[4] = {
301 QStringLiteral("R"),
302 QStringLiteral("G"),
303 QStringLiteral("B"),
304 QStringLiteral("A"),
305 };
toStringQSSGShaderKeyTextureChannel306 void toString(QString &ioStr, QSSGDataView<quint32> inKeySet) const
307 {
308 ioStr.append(QString::fromLocal8Bit(name));
309 ioStr.append(QStringLiteral("="));
310 ioStr.append(enumToStr[getTextureChannel(inKeySet)]);
311 }
312 };
313
314 struct QSSGShaderKeyTextureSwizzle : public QSSGShaderKeyUnsigned<5>
315 {
316 enum TextureSwizzleBits {
317 noSwizzle = 1 << 0,
318 L8toR8 = 1 << 1,
319 A8toR8 = 1 << 2,
320 L8A8toRG8 = 1 << 3,
321 L16toR16 = 1 << 4
322 };
323
324 QSSGShaderKeyTextureSwizzle(const char *inName = "") : QSSGShaderKeyUnsigned<5>(inName) {}
325
getBitValueQSSGShaderKeyTextureSwizzle326 bool getBitValue(TextureSwizzleBits swizzleBit, QSSGDataView<quint32> inKeySet) const
327 {
328 return (getValue(inKeySet) & swizzleBit) ? true : false;
329 }
330
setBitValueQSSGShaderKeyTextureSwizzle331 void setBitValue(TextureSwizzleBits swizzleBit, bool inValue, QSSGDataRef<quint32> inKeySet)
332 {
333 quint32 theValue = getValue(inKeySet);
334 quint32 mask = swizzleBit;
335 if (inValue) {
336 theValue = theValue | mask;
337 } else {
338 mask = ~mask;
339 theValue = theValue & mask;
340 }
341 setValue(inKeySet, theValue);
342 }
343
setSwizzleModeQSSGShaderKeyTextureSwizzle344 void setSwizzleMode(QSSGDataRef<quint32> inKeySet, QSSGRenderTextureSwizzleMode swizzleMode, bool val)
345 {
346 switch (swizzleMode) {
347 case QSSGRenderTextureSwizzleMode::NoSwizzle:
348 setBitValue(noSwizzle, val, inKeySet);
349 break;
350 case QSSGRenderTextureSwizzleMode::L8toR8:
351 setBitValue(L8toR8, val, inKeySet);
352 break;
353 case QSSGRenderTextureSwizzleMode::A8toR8:
354 setBitValue(A8toR8, val, inKeySet);
355 break;
356 case QSSGRenderTextureSwizzleMode::L8A8toRG8:
357 setBitValue(L8A8toRG8, val, inKeySet);
358 break;
359 case QSSGRenderTextureSwizzleMode::L16toR16:
360 setBitValue(L16toR16, val, inKeySet);
361 break;
362 }
363 }
364
isNoSwizzledQSSGShaderKeyTextureSwizzle365 bool isNoSwizzled(QSSGDataView<quint32> inKeySet) const { return getBitValue(noSwizzle, inKeySet); }
setNoSwizzledQSSGShaderKeyTextureSwizzle366 void setNoSwizzled(QSSGDataRef<quint32> inKeySet, bool val) { setBitValue(noSwizzle, val, inKeySet); }
367
isL8SwizzledQSSGShaderKeyTextureSwizzle368 bool isL8Swizzled(QSSGDataView<quint32> inKeySet) const { return getBitValue(L8toR8, inKeySet); }
setL8SwizzledQSSGShaderKeyTextureSwizzle369 void setL8Swizzled(QSSGDataRef<quint32> inKeySet, bool val) { setBitValue(L8toR8, val, inKeySet); }
370
isA8SwizzledQSSGShaderKeyTextureSwizzle371 bool isA8Swizzled(QSSGDataView<quint32> inKeySet) const { return getBitValue(A8toR8, inKeySet); }
setA8SwizzledQSSGShaderKeyTextureSwizzle372 void setA8Swizzled(QSSGDataRef<quint32> inKeySet, bool val) { setBitValue(A8toR8, val, inKeySet); }
373
isL8A8SwizzledQSSGShaderKeyTextureSwizzle374 bool isL8A8Swizzled(QSSGDataView<quint32> inKeySet) const { return getBitValue(L8A8toRG8, inKeySet); }
setL8A8SwizzledQSSGShaderKeyTextureSwizzle375 void setL8A8Swizzled(QSSGDataRef<quint32> inKeySet, bool val) { setBitValue(L8A8toRG8, val, inKeySet); }
376
isL16SwizzledQSSGShaderKeyTextureSwizzle377 bool isL16Swizzled(QSSGDataView<quint32> inKeySet) const { return getBitValue(L16toR16, inKeySet); }
setL16SwizzledQSSGShaderKeyTextureSwizzle378 void setL16Swizzled(QSSGDataRef<quint32> inKeySet, bool val) { setBitValue(L16toR16, val, inKeySet); }
379
toStringQSSGShaderKeyTextureSwizzle380 void toString(QString &ioStr, QSSGDataView<quint32> inKeySet) const
381 {
382 ioStr.append(QString::fromLocal8Bit(name));
383 ioStr.append(QStringLiteral("={"));
384 internalToString(ioStr, "noswizzle", isNoSwizzled(inKeySet));
385 ioStr.append(QStringLiteral(";"));
386 internalToString(ioStr, "l8swizzle", isL8Swizzled(inKeySet));
387 ioStr.append(QStringLiteral(";"));
388 internalToString(ioStr, "a8swizzle", isA8Swizzled(inKeySet));
389 ioStr.append(QStringLiteral(";"));
390 internalToString(ioStr, "l8a8swizzle", isL8A8Swizzled(inKeySet));
391 ioStr.append(QStringLiteral(";"));
392 internalToString(ioStr, "l16swizzle", isL16Swizzled(inKeySet));
393 ioStr.append(QStringLiteral("}"));
394 }
395 };
396
397 struct QSSGShaderKeyImageMap : public QSSGShaderKeyUnsigned<6>
398 {
399 enum ImageMapBits {
400 Enabled = 1 << 0,
401 EnvMap = 1 << 1,
402 LightProbe = 1 << 2,
403 InvertUV = 1 << 3,
404 Premultiplied = 1 << 4,
405 Identity = 1 << 5
406 };
407
408 QSSGShaderKeyImageMap(const char *inName = "") : QSSGShaderKeyUnsigned<6>(inName) {}
409
getBitValueQSSGShaderKeyImageMap410 bool getBitValue(ImageMapBits imageBit, QSSGDataView<quint32> inKeySet) const
411 {
412 return (getValue(inKeySet) & imageBit) ? true : false;
413 }
414
setBitValueQSSGShaderKeyImageMap415 void setBitValue(ImageMapBits imageBit, bool inValue, QSSGDataRef<quint32> inKeySet)
416 {
417 quint32 theValue = getValue(inKeySet);
418 quint32 mask = imageBit;
419 if (inValue) {
420 theValue = theValue | mask;
421 } else {
422 mask = ~mask;
423 theValue = theValue & mask;
424 }
425 setValue(inKeySet, theValue);
426 }
427
isEnabledQSSGShaderKeyImageMap428 bool isEnabled(QSSGDataView<quint32> inKeySet) const { return getBitValue(Enabled, inKeySet); }
setEnabledQSSGShaderKeyImageMap429 void setEnabled(QSSGDataRef<quint32> inKeySet, bool val) { setBitValue(Enabled, val, inKeySet); }
430
isEnvMapQSSGShaderKeyImageMap431 bool isEnvMap(QSSGDataView<quint32> inKeySet) const { return getBitValue(EnvMap, inKeySet); }
setEnvMapQSSGShaderKeyImageMap432 void setEnvMap(QSSGDataRef<quint32> inKeySet, bool val) { setBitValue(EnvMap, val, inKeySet); }
433
isLightProbeQSSGShaderKeyImageMap434 bool isLightProbe(QSSGDataView<quint32> inKeySet) const { return getBitValue(LightProbe, inKeySet); }
setLightProbeQSSGShaderKeyImageMap435 void setLightProbe(QSSGDataRef<quint32> inKeySet, bool val) { setBitValue(LightProbe, val, inKeySet); }
436
isInvertUVMapQSSGShaderKeyImageMap437 bool isInvertUVMap(QSSGDataView<quint32> inKeySet) const { return getBitValue(InvertUV, inKeySet); }
setInvertUVMapQSSGShaderKeyImageMap438 void setInvertUVMap(QSSGDataRef<quint32> inKeySet, bool val) { setBitValue(InvertUV, val, inKeySet); }
439
isPremultipliedQSSGShaderKeyImageMap440 bool isPremultiplied(QSSGDataView<quint32> inKeySet) const { return getBitValue(Premultiplied, inKeySet); }
setPremultipliedQSSGShaderKeyImageMap441 void setPremultiplied(QSSGDataRef<quint32> inKeySet, bool val) { setBitValue(Premultiplied, val, inKeySet); }
442
isIdentityTransformQSSGShaderKeyImageMap443 bool isIdentityTransform(QSSGDataView<quint32> inKeySet) const { return getBitValue(Identity, inKeySet); }
setIdentityTransformQSSGShaderKeyImageMap444 void setIdentityTransform(QSSGDataRef<quint32> inKeySet, bool val) { setBitValue(Identity, val, inKeySet); }
445
toStringQSSGShaderKeyImageMap446 void toString(QString &ioStr, QSSGDataView<quint32> inKeySet) const
447 {
448 ioStr.append(QString::fromLocal8Bit(name));
449 ioStr.append(QStringLiteral("={"));
450 internalToString(ioStr, "enabled", isEnabled(inKeySet));
451 ioStr.append(QStringLiteral(";"));
452 internalToString(ioStr, "envMap", isEnvMap(inKeySet));
453 ioStr.append(QStringLiteral(";"));
454 internalToString(ioStr, "lightProbe", isLightProbe(inKeySet));
455 ioStr.append(QStringLiteral(";"));
456 internalToString(ioStr, "invertUV", isInvertUVMap(inKeySet));
457 ioStr.append(QStringLiteral(";"));
458 internalToString(ioStr, "premultiplied", isPremultiplied(inKeySet));
459 ioStr.append(QStringLiteral(";"));
460 internalToString(ioStr, "identity", isIdentityTransform(inKeySet));
461 ioStr.append(QStringLiteral("}"));
462 }
463 };
464
465 struct QSSGShaderKeySpecularModel : QSSGShaderKeyUnsigned<2>
466 {
467 QSSGShaderKeySpecularModel(const char *inName = "") : QSSGShaderKeyUnsigned<2>(inName) {}
468
setSpecularModelQSSGShaderKeySpecularModel469 void setSpecularModel(QSSGDataRef<quint32> inKeySet, QSSGRenderDefaultMaterial::MaterialSpecularModel inModel)
470 {
471 setValue(inKeySet, quint32(inModel));
472 }
473
getSpecularModelQSSGShaderKeySpecularModel474 QSSGRenderDefaultMaterial::MaterialSpecularModel getSpecularModel(QSSGDataView<quint32> inKeySet) const
475 {
476 return static_cast<QSSGRenderDefaultMaterial::MaterialSpecularModel>(getValue(inKeySet));
477 }
478
toStringQSSGShaderKeySpecularModel479 void toString(QString &ioStr, QSSGDataView<quint32> inKeySet) const
480 {
481 ioStr.append(QString::fromLocal8Bit(name));
482 ioStr.append(QStringLiteral("="));
483 switch (getSpecularModel(inKeySet)) {
484 case QSSGRenderDefaultMaterial::MaterialSpecularModel::KGGX:
485 ioStr.append(QStringLiteral("KGGX"));
486 break;
487 case QSSGRenderDefaultMaterial::MaterialSpecularModel::KWard:
488 ioStr.append(QStringLiteral("KWard"));
489 break;
490 case QSSGRenderDefaultMaterial::MaterialSpecularModel::Default:
491 ioStr.append(QStringLiteral("Default"));
492 break;
493 }
494 ioStr.append(QStringLiteral(";"));
495 }
496 };
497
498 struct QSSGShaderKeyAlphaMode : QSSGShaderKeyUnsigned<2>
499 {
500 QSSGShaderKeyAlphaMode(const char *inName = "") : QSSGShaderKeyUnsigned<2>(inName) {}
501
setAlphaModeQSSGShaderKeyAlphaMode502 void setAlphaMode(QSSGDataRef<quint32> inKeySet, QSSGRenderDefaultMaterial::MaterialAlphaMode inMode)
503 {
504 setValue(inKeySet, quint32(inMode));
505 }
506
getAlphaModeQSSGShaderKeyAlphaMode507 QSSGRenderDefaultMaterial::MaterialAlphaMode getAlphaMode(QSSGDataView<quint32> inKeySet) const
508 {
509 return static_cast<QSSGRenderDefaultMaterial::MaterialAlphaMode>(getValue(inKeySet));
510 }
511
toStringQSSGShaderKeyAlphaMode512 void toString(QString &ioStr, QSSGDataView<quint32> inKeySet) const
513 {
514 ioStr.append(QString::fromLocal8Bit(name));
515 ioStr.append(QStringLiteral("="));
516 switch (getAlphaMode(inKeySet)) {
517 case QSSGRenderDefaultMaterial::MaterialAlphaMode::Opaque:
518 ioStr.append(QStringLiteral("Opaque"));
519 break;
520 case QSSGRenderDefaultMaterial::MaterialAlphaMode::Mask:
521 ioStr.append(QStringLiteral("Mask"));
522 break;
523 case QSSGRenderDefaultMaterial::MaterialAlphaMode::Blend:
524 ioStr.append(QStringLiteral("Blend"));
525 break;
526 case QSSGRenderDefaultMaterial::MaterialAlphaMode::Default:
527 ioStr.append(QStringLiteral("Default"));
528 break;
529 }
530 ioStr.append(QStringLiteral(";"));
531 }
532 };
533
534 struct QSSGShaderKeyVertexAttribute : public QSSGShaderKeyUnsigned<7>
535 {
536 enum VertexAttributeBits {
537 Position = 1 << 0,
538 Normal = 1 << 1,
539 TexCoord0 = 1 << 2,
540 TexCoord1 = 1 << 3,
541 Tangent = 1 << 4,
542 Binormal = 1 << 5,
543 Color = 1 << 6
544 };
545
546 QSSGShaderKeyVertexAttribute(const char *inName = "") : QSSGShaderKeyUnsigned<7>(inName) {}
547
getBitValueQSSGShaderKeyVertexAttribute548 bool getBitValue(VertexAttributeBits bit, QSSGDataView<quint32> inKeySet) const
549 {
550 return (getValue(inKeySet) & bit) ? true : false;
551 }
552
toStringQSSGShaderKeyVertexAttribute553 void toString(QString &ioStr, QSSGDataView<quint32> inKeySet) const
554 {
555 ioStr.append(QString::fromLocal8Bit(name));
556 ioStr.append(QStringLiteral("={"));
557 internalToString(ioStr, "position", getBitValue(Position, inKeySet));
558 ioStr.append(QStringLiteral(";"));
559 internalToString(ioStr, "normal", getBitValue(Normal, inKeySet));
560 ioStr.append(QStringLiteral(";"));
561 internalToString(ioStr, "texcoord0", getBitValue(TexCoord0, inKeySet));
562 ioStr.append(QStringLiteral(";"));
563 internalToString(ioStr, "texcoord1", getBitValue(TexCoord1, inKeySet));
564 ioStr.append(QStringLiteral(";"));
565 internalToString(ioStr, "tangent", getBitValue(Tangent, inKeySet));
566 ioStr.append(QStringLiteral(";"));
567 internalToString(ioStr, "binormal", getBitValue(Binormal, inKeySet));
568 ioStr.append(QStringLiteral(";"));
569 internalToString(ioStr, "color", getBitValue(Color, inKeySet));
570 ioStr.append(QStringLiteral("}"));
571 }
572 };
573
574 struct QSSGShaderDefaultMaterialKeyProperties
575 {
576 enum {
577 LightCount = 7,
578 };
579 enum {
580 SingleChannelImageCount = 5,
581 };
582 enum ImageMapNames {
583 DiffuseMap = 0,
584 EmissiveMap,
585 SpecularMap,
586 BaseColorMap,
587 BumpMap,
588 SpecularAmountMap,
589 NormalMap,
590 DisplacementMap,
591 LightmapIndirect,
592 LightmapRadiosity,
593 LightmapShadow,
594 // single channel images
595 OpacityMap,
596 RoughnessMap,
597 MetalnessMap,
598 OcclusionMap,
599 TranslucencyMap,
600
601 ImageMapCount,
602 SingleChannelImagesFirst = OpacityMap
603 };
604 enum ImageChannelNames {
605 OpacityChannel = 0,
606 RoughnessChannel,
607 MetalnessChannel,
608 OcclusionChannel,
609 TranslucencyChannel,
610 };
611
612 QSSGShaderKeyBoolean m_hasLighting;
613 QSSGShaderKeyBoolean m_hasIbl;
614 QSSGShaderKeyUnsigned<3> m_lightCount;
615 QSSGShaderKeyBoolean m_lightFlags[LightCount];
616 QSSGShaderKeyBoolean m_lightSpotFlags[LightCount];
617 QSSGShaderKeyBoolean m_lightAreaFlags[LightCount];
618 QSSGShaderKeyBoolean m_lightShadowFlags[LightCount];
619 QSSGShaderKeyBoolean m_specularEnabled;
620 QSSGShaderKeyBoolean m_fresnelEnabled;
621 QSSGShaderKeyBoolean m_vertexColorsEnabled;
622 QSSGShaderKeySpecularModel m_specularModel;
623 QSSGShaderKeyImageMap m_imageMaps[ImageMapCount];
624 QSSGShaderKeyTextureSwizzle m_textureSwizzle[ImageMapCount];
625 QSSGShaderKeyTextureChannel m_textureChannels[SingleChannelImageCount];
626 QSSGShaderKeyTessellation m_tessellationMode;
627 QSSGShaderKeyBoolean m_hasSkinning;
628 QSSGShaderKeyBoolean m_wireframeMode;
629 QSSGShaderKeyBoolean m_isDoubleSided;
630 QSSGShaderKeyAlphaMode m_alphaMode;
631 QSSGShaderKeyVertexAttribute m_vertexAttributes;
632
QSSGShaderDefaultMaterialKeyPropertiesQSSGShaderDefaultMaterialKeyProperties633 QSSGShaderDefaultMaterialKeyProperties()
634 : m_hasLighting("hasLighting")
635 , m_hasIbl("hasIbl")
636 , m_lightCount("lightCount")
637 , m_specularEnabled("specularEnabled")
638 , m_fresnelEnabled("fresnelEnabled")
639 , m_vertexColorsEnabled("vertexColorsEnabled")
640 , m_specularModel("specularModel")
641 , m_tessellationMode("tessellationMode")
642 , m_hasSkinning("hasSkinning")
643 , m_wireframeMode("wireframeMode")
644 , m_isDoubleSided("isDoubleSided")
645 , m_alphaMode("alphaMode")
646 , m_vertexAttributes("vertexAttributes")
647 {
648 m_lightFlags[0].name = "light0HasPosition";
649 m_lightFlags[1].name = "light1HasPosition";
650 m_lightFlags[2].name = "light2HasPosition";
651 m_lightFlags[3].name = "light3HasPosition";
652 m_lightFlags[4].name = "light4HasPosition";
653 m_lightFlags[5].name = "light5HasPosition";
654 m_lightFlags[6].name = "light6HasPosition";
655 m_lightSpotFlags[0].name = "light0HasSpot";
656 m_lightSpotFlags[1].name = "light1HasSpot";
657 m_lightSpotFlags[2].name = "light2HasSpot";
658 m_lightSpotFlags[3].name = "light3HasSpot";
659 m_lightSpotFlags[4].name = "light4HasSpot";
660 m_lightSpotFlags[5].name = "light5HasSpot";
661 m_lightSpotFlags[6].name = "light6HasSpot";
662 m_lightAreaFlags[0].name = "light0HasArea";
663 m_lightAreaFlags[1].name = "light1HasArea";
664 m_lightAreaFlags[2].name = "light2HasArea";
665 m_lightAreaFlags[3].name = "light3HasArea";
666 m_lightAreaFlags[4].name = "light4HasArea";
667 m_lightAreaFlags[5].name = "light5HasArea";
668 m_lightAreaFlags[6].name = "light6HasArea";
669 m_lightShadowFlags[0].name = "light0HasShadow";
670 m_lightShadowFlags[1].name = "light1HasShadow";
671 m_lightShadowFlags[2].name = "light2HasShadow";
672 m_lightShadowFlags[3].name = "light3HasShadow";
673 m_lightShadowFlags[4].name = "light4HasShadow";
674 m_lightShadowFlags[5].name = "light5HasShadow";
675 m_lightShadowFlags[6].name = "light6HasShadow";
676
677 m_imageMaps[0].name = "diffuseMap";
678 m_imageMaps[1].name = "emissiveMap";
679 m_imageMaps[2].name = "specularMap";
680 m_imageMaps[3].name = "baseColorMap";
681 m_imageMaps[4].name = "bumpMap";
682 m_imageMaps[5].name = "specularAmountMap";
683 m_imageMaps[6].name = "normalMap";
684 m_imageMaps[7].name = "displacementMap";
685 m_imageMaps[8].name = "lightmapIndirect";
686 m_imageMaps[9].name = "lightmapRadiosity";
687 m_imageMaps[10].name = "lightmapShadow";
688 m_imageMaps[11].name = "opacityMap";
689 m_imageMaps[12].name = "roughnessMap";
690 m_imageMaps[13].name = "metalnessMap";
691 m_imageMaps[14].name = "occlusionMap";
692 m_imageMaps[15].name = "translucencyMap";
693
694 m_textureSwizzle[0].name = "diffuseMap_swizzle";
695 m_textureSwizzle[1].name = "emissiveMap_swizzle";
696 m_textureSwizzle[2].name = "specularMap_swizzle";
697 m_textureSwizzle[3].name = "baseColorMap_swizzle";
698 m_textureSwizzle[4].name = "bumpMap_swizzle";
699 m_textureSwizzle[5].name = "specularAmountMap_swizzle";
700 m_textureSwizzle[6].name = "normalMap_swizzle";
701 m_textureSwizzle[7].name = "displacementMap_swizzle";
702 m_textureSwizzle[8].name = "lightmapIndirect_swizzle";
703 m_textureSwizzle[9].name = "lightmapRadiosity_swizzle";
704 m_textureSwizzle[10].name = "lightmapShadow_swizzle";
705 m_textureSwizzle[11].name = "opacityMap_swizzle";
706 m_textureSwizzle[12].name = "roughnessMap_swizzle";
707 m_textureSwizzle[13].name = "metalnessMap_swizzle";
708 m_textureSwizzle[14].name = "occlusionMap_swizzle";
709 m_textureSwizzle[15].name = "translucencyMap_swizzle";
710
711 m_textureChannels[0].name = "opacityMap_channel";
712 m_textureChannels[1].name = "roughnessMap_channel";
713 m_textureChannels[2].name = "metalnessMap_channel";
714 m_textureChannels[3].name = "occlusionMap_channel";
715 m_textureChannels[4].name = "translucencyMap_channel";
716
717 setPropertyOffsets();
718 }
719
720 template<typename TVisitor>
visitPropertiesQSSGShaderDefaultMaterialKeyProperties721 void visitProperties(TVisitor &inVisitor)
722 {
723 inVisitor.visit(m_hasLighting);
724 inVisitor.visit(m_hasIbl);
725 inVisitor.visit(m_lightCount);
726
727 for (quint32 idx = 0, end = LightCount; idx < end; ++idx) {
728 inVisitor.visit(m_lightFlags[idx]);
729 }
730
731 for (quint32 idx = 0, end = LightCount; idx < end; ++idx) {
732 inVisitor.visit(m_lightSpotFlags[idx]);
733 }
734
735 for (quint32 idx = 0, end = LightCount; idx < end; ++idx) {
736 inVisitor.visit(m_lightAreaFlags[idx]);
737 }
738
739 for (quint32 idx = 0, end = LightCount; idx < end; ++idx) {
740 inVisitor.visit(m_lightShadowFlags[idx]);
741 }
742
743 inVisitor.visit(m_specularEnabled);
744 inVisitor.visit(m_fresnelEnabled);
745 inVisitor.visit(m_vertexColorsEnabled);
746 inVisitor.visit(m_specularModel);
747
748 for (quint32 idx = 0, end = ImageMapCount; idx < end; ++idx) {
749 inVisitor.visit(m_imageMaps[idx]);
750 inVisitor.visit(m_textureSwizzle[idx]);
751 }
752 for (quint32 idx = 0, end = SingleChannelImageCount; idx < end; ++idx)
753 inVisitor.visit(m_textureChannels[idx]);
754
755 inVisitor.visit(m_tessellationMode);
756 inVisitor.visit(m_hasSkinning);
757 inVisitor.visit(m_wireframeMode);
758 inVisitor.visit(m_isDoubleSided);
759 inVisitor.visit(m_alphaMode);
760 inVisitor.visit(m_vertexAttributes);
761 }
762
763 struct OffsetVisitor
764 {
765 quint32 m_offset;
OffsetVisitorQSSGShaderDefaultMaterialKeyProperties::OffsetVisitor766 OffsetVisitor() : m_offset(0) {}
767 template<typename TPropType>
visitQSSGShaderDefaultMaterialKeyProperties::OffsetVisitor768 void visit(TPropType &inProp)
769 {
770 // if we cross the 32 bit border we just move
771 // to the next dword.
772 // This cost a few extra bits but prevents tedious errors like
773 // loosing shader key bits because they got moved beyond the 32 border
774 quint32 bit = m_offset % 32;
775 if (bit + TPropType::BitWidth > 31) {
776 m_offset += 32 - bit;
777 }
778
779 inProp.setOffset(m_offset);
780 m_offset += TPropType::BitWidth;
781 }
782 };
783
setPropertyOffsetsQSSGShaderDefaultMaterialKeyProperties784 void setPropertyOffsets()
785 {
786 OffsetVisitor visitor;
787 visitProperties(visitor);
788 // If this assert fires, then the default material key needs more bits.
789 Q_ASSERT(visitor.m_offset < 320);
790 }
791 };
792
793 struct QSSGShaderDefaultMaterialKey
794 {
795 enum {
796 DataBufferSize = 10,
797 };
798 quint32 m_dataBuffer[DataBufferSize];
799 uint m_featureSetHash;
800
QSSGShaderDefaultMaterialKeyQSSGShaderDefaultMaterialKey801 QSSGShaderDefaultMaterialKey(uint inFeatureSetHash) : m_featureSetHash(inFeatureSetHash)
802 {
803 for (size_t idx = 0; idx < DataBufferSize; ++idx)
804 m_dataBuffer[idx] = 0;
805 }
806
QSSGShaderDefaultMaterialKeyQSSGShaderDefaultMaterialKey807 QSSGShaderDefaultMaterialKey() : m_featureSetHash(0)
808 {
809 for (size_t idx = 0; idx < DataBufferSize; ++idx)
810 m_dataBuffer[idx] = 0;
811 }
812
hashQSSGShaderDefaultMaterialKey813 uint hash() const
814 {
815 uint retval = 0;
816 for (size_t idx = 0; idx < DataBufferSize; ++idx)
817 retval = retval ^ qHash(m_dataBuffer[idx]);
818 return retval ^ m_featureSetHash;
819 }
820
821 bool operator==(const QSSGShaderDefaultMaterialKey &other) const
822 {
823 bool retval = true;
824 for (size_t idx = 0; idx < DataBufferSize && retval; ++idx)
825 retval = m_dataBuffer[idx] == other.m_dataBuffer[idx];
826 return retval && m_featureSetHash == other.m_featureSetHash;
827 }
828
829 // Cast operators to make getting properties easier.
830 operator QSSGDataRef<quint32>() { return toDataRef(m_dataBuffer, DataBufferSize); }
831 operator QSSGDataView<quint32>() const { return toDataView(m_dataBuffer, DataBufferSize); }
832
833 struct StringVisitor
834 {
835 QByteArray &m_str;
836 QSSGDataView<quint32> m_keyStore;
StringVisitorQSSGShaderDefaultMaterialKey::StringVisitor837 StringVisitor(QByteArray &s, QSSGDataView<quint32> ks) : m_str(s), m_keyStore(ks) {}
838 template<typename TPropType>
visitQSSGShaderDefaultMaterialKey::StringVisitor839 void visit(const TPropType &prop)
840 {
841 quint32 originalSize = m_str.size();
842 if (m_str.size())
843 m_str.append(";");
844 QString str = QString::fromUtf8(m_str);
845 prop.toString(str, m_keyStore);
846 // if the only thing we added was the semicolon
847 // then nuke the semicolon
848 m_str = str.toLocal8Bit();
849 if (originalSize && m_str.size() == int(originalSize + 1))
850 m_str.resize(int(originalSize));
851 }
852 };
853
toStringQSSGShaderDefaultMaterialKey854 void toString(QByteArray &ioString, QSSGShaderDefaultMaterialKeyProperties &inProperties) const
855 {
856 StringVisitor theVisitor(ioString, *this);
857 inProperties.visitProperties(theVisitor);
858 }
859 };
860
861 Q_STATIC_ASSERT(std::is_trivially_destructible<QSSGShaderDefaultMaterialKey>::value);
862
863
qHash(const QSSGShaderDefaultMaterialKey & key)864 inline uint qHash(const QSSGShaderDefaultMaterialKey &key)
865 {
866 return key.hash();
867 }
868
869 QT_END_NAMESPACE
870
871 #endif
872