Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qssgrendershaderkeys_p.h
Go to the documentation of this file.
1// Copyright (C) 2008-2012 NVIDIA Corporation.
2// Copyright (C) 2019 The Qt Company Ltd.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
4// Qt-Security score:significant reason:default
5
6
7#ifndef QSSG_RENDER_SHADER_KEY_H
8#define QSSG_RENDER_SHADER_KEY_H
9
10//
11// W A R N I N G
12// -------------
13//
14// This file is not part of the Qt API. It exists purely as an
15// implementation detail. This header file may change from version to
16// version without notice, or even be removed.
17//
18// We mean it.
19//
20
21#include <QtQuick3DUtils/private/qssgdataref_p.h>
22#include <QtQuick3DUtils/private/qssgrenderbasetypes_p.h>
23#include <QtQuick3DRuntimeRender/private/qssgrenderdefaultmaterial_p.h>
24#include <QtQuick3DRuntimeRender/private/qssgrenderlight_p.h>
25#include <QtQuick3DRuntimeRender/private/qssgrhicontext_p.h>
26
27QT_BEGIN_NAMESPACE
28// We have an ever expanding set of properties we like to hash into one or more 32 bit
29// quantities.
30// Furthermore we would like this set of properties to be convertable to string
31// So the shader cache file itself is somewhat human readable/diagnosable.
32// To do this we create a set of objects that act as properties to the master shader key.
33// These objects are tallied in order to figure out their actual offset into the shader key's
34// data store. They are also run through in order to create the string shader cache key.
35
36struct QSSGShaderKeyPropertyBase
37{
38 QByteArrayView name;
39 quint32 offset;
40 explicit constexpr QSSGShaderKeyPropertyBase(const char *inName = "") : name(inName), offset(0) {}
41 quint32 getOffset() const { return offset; }
42 void setOffset(quint32 of) { offset = of; }
43
44 template<quint32 TBitWidth>
45 quint32 getMaskTemplate() const
46 {
47 quint32 bit = offset % 32;
48 quint32 startValue = (1 << TBitWidth) - 1;
49 quint32 mask = startValue << bit;
50 return mask;
51 }
52
53 quint32 getIdx() const { return offset / 32; }
54
55protected:
56 void internalToString(QByteArray &ioStr, const QByteArrayView &inBuffer) const
57 {
58 ioStr.append(name);
59 ioStr.append('=');
60 ioStr.append(inBuffer);
61 }
62
63 static void internalToString(QByteArray &ioStr, const QByteArrayView &name, bool inValue)
64 {
65 if (inValue) {
66 ioStr.append(name);
67 ioStr.append('=');
68 ioStr.append(inValue ? QByteArrayView("true") : QByteArrayView("false"));
69 }
70 }
71 static bool getBoolValue(const QByteArray& str, const QByteArrayView &name)
72 {
73 const int index = str.indexOf(name);
74 if (index < 0)
75 return false;
76 const qsizetype nameLen = name.size();
77 if (str[index + nameLen] != '=')
78 return false;
79 if (str.mid(index + nameLen + 1, 4) == QByteArrayView("true"))
80 return true;
81 return false;
82 }
83};
84
85struct QSSGShaderKeyBoolean : public QSSGShaderKeyPropertyBase
86{
87 enum {
89 };
90
91 explicit constexpr QSSGShaderKeyBoolean(const char *inName = "") : QSSGShaderKeyPropertyBase(inName) {}
92
93 quint32 getMask() const { return getMaskTemplate<BitWidth>(); }
94 void setValue(QSSGDataRef<quint32> inDataStore, bool inValue) const
95 {
96 const qint32 idx = qint32(getIdx());
97 Q_ASSERT(idx >= 0 && idx <= INT32_MAX);
98 Q_ASSERT(inDataStore.size() > idx);
99 quint32 mask = getMask();
100 quint32 &target = inDataStore[idx];
101 if (inValue) {
102 target = target | mask;
103 } else {
104 mask = ~mask;
105 target = target & mask;
106 }
107 }
108
109 bool getValue(QSSGDataView<quint32> inDataStore) const
110 {
111 quint32 idx = getIdx();
112 quint32 mask = getMask();
113 const quint32 &target = inDataStore[idx];
114 return (target & mask) ? true : false;
115 }
116
117 void toString(QByteArray &ioStr, QSSGDataView<quint32> inKeySet) const
118 {
119 bool isHigh = getValue(inKeySet);
120 internalToString(ioStr, name, isHigh);
121 }
122 void fromString(const QByteArray &ioStr, QSSGDataRef<quint32> inKeySet)
123 {
124 setValue(inKeySet, getBoolValue(ioStr, name));
125 }
126};
127
128template<quint32 TBitWidth>
129struct QSSGShaderKeyUnsigned : public QSSGShaderKeyPropertyBase
130{
131 enum {
132 BitWidth = TBitWidth,
133 };
134 explicit constexpr QSSGShaderKeyUnsigned(const char *inName = "") : QSSGShaderKeyPropertyBase(inName) {}
135 quint32 getMask() const { return getMaskTemplate<BitWidth>(); }
136 void setValue(QSSGDataRef<quint32> inDataStore, quint32 inValue) const
137 {
138 quint32 startValue = (1 << TBitWidth) - 1;
139 // Ensure inValue is within range of bit width.
140 inValue = inValue & startValue;
141 quint32 bit = offset % 32;
142 quint32 mask = getMask();
143 quint32 idx = getIdx();
144 inValue = inValue << bit;
145 quint32 &target = inDataStore[idx];
146 // Get rid of existing value
147 quint32 inverseMask = ~mask;
148 target = target & inverseMask;
149 target = target | inValue;
150 }
151
152 quint32 getValue(QSSGDataView<quint32> inDataStore) const
153 {
154 quint32 idx = getIdx();
155 quint32 bit = offset % 32;
156 quint32 mask = getMask();
157 const quint32 &target = inDataStore[idx];
158
159 quint32 retval = target & mask;
160 retval = retval >> bit;
161 return retval;
162 }
163
164 void toString(QByteArray &ioStr, QSSGDataView<quint32> inKeySet) const
165 {
166 quint32 value = getValue(inKeySet);
167 char buf[64];
168 memset(buf, 0, sizeof (buf));
169 toStr(value, toDataRef(buf, 64));
170 internalToString(ioStr, buf);
171 }
172
173 void fromString(const QByteArray &ioStr, QSSGDataRef<quint32> inKeySet)
174 {
175 const qsizetype nameLen = name.size();
176 const qsizetype strOffset = ioStr.indexOf(name);
177 if (strOffset >= 0) {
178 /* The key is stored as name=val */
179 if (ioStr[strOffset + nameLen] != '=')
180 return;
181 const QByteArray s = ioStr.right(ioStr.size() - strOffset - nameLen - 1);
182 int i = 0;
183 while (QChar(QLatin1Char(s[i])).isDigit())
184 i++;
185 const quint32 value = s.left(i).toInt();
186 setValue(inKeySet, value);
187 }
188 }
189
190private:
191 static quint32 toStr(quint32 item, QSSGDataRef<char> buffer)
192 {
193 // hope the buffer is big enough...
194 return static_cast<quint32>(::snprintf(buffer.begin(), buffer.size(), "%u", item));
195 }
196};
197
199{
201 R = 0,
202 G = 1,
203 B = 2,
204 A = 3,
205 };
206 explicit QSSGShaderKeyTextureChannel(const char *inName = "") : QSSGShaderKeyUnsigned<2>(inName) {}
207
208 TexturChannelBits getTextureChannel(QSSGDataView<quint32> inKeySet) const
209 {
210 return TexturChannelBits(getValue(inKeySet));
211 }
212
213 void setTextureChannel(TexturChannelBits channel, QSSGDataRef<quint32> inKeySet)
214 {
215 setValue(inKeySet, quint32(channel));
216 }
217 static constexpr char textureChannelToChar[4] = {
218 'R',
219 'G',
220 'B',
221 'A'
222 };
223 void toString(QByteArray &ioStr, QSSGDataView<quint32> inKeySet) const
224 {
225 ioStr.append(name);
226 ioStr.append('=');
227 ioStr.append(textureChannelToChar[getTextureChannel(inKeySet)]);
228 }
229 void fromString(const QByteArray &ioStr, QSSGDataRef<quint32> inKeySet)
230 {
231 const qsizetype nameLen = name.size();
232 const qsizetype strOffset = ioStr.indexOf(name);
233 if (strOffset >= 0) {
234 /* The key is stored as name=ch */
235 if (ioStr[strOffset + nameLen] != '=')
236 return;
237 const char ch = ioStr[strOffset + nameLen + 1];
238 if (ch == 'R')
239 setValue(inKeySet, TexturChannelBits::R);
240 else if (ch == 'G')
241 setValue(inKeySet, TexturChannelBits::G);
242 else if (ch == 'B')
243 setValue(inKeySet, TexturChannelBits::B);
244 else if (ch == 'A')
245 setValue(inKeySet, TexturChannelBits::A);
246 }
247 }
248};
249
251{
253 Enabled = 1 << 0,
254 EnvMap = 1 << 1,
255 LightProbe = 1 << 2,
256 Identity = 1 << 3,
257 UsesUV1 = 1 << 4,
258 Linear = 1 << 5,
260 };
261
262 explicit QSSGShaderKeyImageMap(const char *inName = "") : QSSGShaderKeyUnsigned<7>(inName) {}
263
264 bool getBitValue(ImageMapBits imageBit, QSSGDataView<quint32> inKeySet) const
265 {
266 return (getValue(inKeySet) & imageBit) ? true : false;
267 }
268
269 void setBitValue(ImageMapBits imageBit, bool inValue, QSSGDataRef<quint32> inKeySet)
270 {
271 quint32 theValue = getValue(inKeySet);
272 quint32 mask = imageBit;
273 if (inValue) {
274 theValue = theValue | mask;
275 } else {
276 mask = ~mask;
277 theValue = theValue & mask;
278 }
279 setValue(inKeySet, theValue);
280 }
281
282 bool isEnabled(QSSGDataView<quint32> inKeySet) const { return getBitValue(Enabled, inKeySet); }
283 void setEnabled(QSSGDataRef<quint32> inKeySet, bool val) { setBitValue(Enabled, val, inKeySet); }
284
285 bool isEnvMap(QSSGDataView<quint32> inKeySet) const { return getBitValue(EnvMap, inKeySet); }
286 void setEnvMap(QSSGDataRef<quint32> inKeySet, bool val) { setBitValue(EnvMap, val, inKeySet); }
287
288 bool isLightProbe(QSSGDataView<quint32> inKeySet) const { return getBitValue(LightProbe, inKeySet); }
289 void setLightProbe(QSSGDataRef<quint32> inKeySet, bool val) { setBitValue(LightProbe, val, inKeySet); }
290
291 bool isIdentityTransform(QSSGDataView<quint32> inKeySet) const { return getBitValue(Identity, inKeySet); }
292 void setIdentityTransform(QSSGDataRef<quint32> inKeySet, bool val) { setBitValue(Identity, val, inKeySet); }
293
294 bool isUsingUV1(QSSGDataView<quint32> inKeySet) const { return getBitValue(UsesUV1, inKeySet); }
295 void setUsesUV1(QSSGDataRef<quint32> inKeySet, bool val) { setBitValue(UsesUV1, val, inKeySet); }
296
297 bool isLinear(QSSGDataView<quint32> inKeySet) const { return getBitValue(Linear, inKeySet); }
298 void setLinear(QSSGDataRef<quint32> inKeySet, bool val) { setBitValue(Linear, val, inKeySet); }
299
300 bool isPreMultipliedAlpha(QSSGDataView<quint32> inKeySet) const { return getBitValue(PreMultipliedAlpha, inKeySet); }
301 void setPreMultipliedAlpha(QSSGDataRef<quint32> inKeySet, bool val) { setBitValue(PreMultipliedAlpha, val, inKeySet); }
302
303 void toString(QByteArray &ioStr, QSSGDataView<quint32> inKeySet) const
304 {
305 ioStr.append(name);
306 ioStr.append(QByteArrayView("={"));
307 internalToString(ioStr, QByteArrayView("enabled"), isEnabled(inKeySet));
308 ioStr.append(';');
309 internalToString(ioStr, QByteArrayView("envMap"), isEnvMap(inKeySet));
310 ioStr.append(';');
311 internalToString(ioStr, QByteArrayView("lightProbe"), isLightProbe(inKeySet));
312 ioStr.append(';');
313 internalToString(ioStr, QByteArrayView("identity"), isIdentityTransform(inKeySet));
314 ioStr.append(';');
315 internalToString(ioStr, QByteArrayView("usesUV1"), isUsingUV1(inKeySet));
316 ioStr.append(';');
317 internalToString(ioStr, QByteArrayView("linear"), isLinear(inKeySet));
318 ioStr.append(';');
319 internalToString(ioStr, QByteArrayView("preMultipliedAlpha"), isPreMultipliedAlpha(inKeySet));
320 ioStr.append('}');
321 }
322};
323
325{
326 explicit QSSGShaderKeySpecularModel(const char *inName = "") : QSSGShaderKeyUnsigned<2>(inName) {}
327
328 void setSpecularModel(QSSGDataRef<quint32> inKeySet, QSSGRenderDefaultMaterial::MaterialSpecularModel inModel)
329 {
330 setValue(inKeySet, quint32(inModel));
331 }
332
334 {
335 return static_cast<QSSGRenderDefaultMaterial::MaterialSpecularModel>(getValue(inKeySet));
336 }
337
338 void toString(QByteArray &ioStr, QSSGDataView<quint32> inKeySet) const
339 {
340 ioStr.append(name);
341 ioStr.append('=');
342 switch (getSpecularModel(inKeySet)) {
343 case QSSGRenderDefaultMaterial::MaterialSpecularModel::SchlickGGX:
344 ioStr.append(QByteArrayView("SchlickGGX"));
345 break;
346 case QSSGRenderDefaultMaterial::MaterialSpecularModel::BlinnPhong:
347 ioStr.append(QByteArrayView("BlinnPhong"));
348 break;
349 }
350 }
351 void fromString(const QByteArray &ioStr, QSSGDataRef<quint32> inKeySet)
352 {
353 const qsizetype nameLen = name.size();
354 const int strOffset = ioStr.indexOf(name);
355 if (strOffset >= 0) {
356 /* The key is stored as name=specularMode; */
357 if (ioStr[strOffset + nameLen] != '=')
358 return;
359 const int codeOffsetBegin = strOffset + nameLen + 1;
360 int codeOffset = 0;
361 while (ioStr[codeOffsetBegin + codeOffset] != ';')
362 codeOffset++;
363 const QByteArray val = ioStr.mid(codeOffsetBegin, codeOffset);
364 if (val == QByteArrayView("SchlickGGX"))
365 setSpecularModel(inKeySet, QSSGRenderDefaultMaterial::MaterialSpecularModel::SchlickGGX);
366 if (val == QByteArrayView("BlinnPhong"))
367 setSpecularModel(inKeySet, QSSGRenderDefaultMaterial::MaterialSpecularModel::BlinnPhong);
368 }
369 }
370};
371
373{
374 explicit QSSGShaderKeyDiffuseModel(const char *inName = "") : QSSGShaderKeyUnsigned<2>(inName) {}
375
376 void setDiffuseModel(QSSGDataRef<quint32> inKeySet, QSSGRenderDefaultMaterial::MaterialDiffuseModel inModel)
377 {
378 setValue(inKeySet, quint32(inModel));
379 }
380
382 {
383 return static_cast<QSSGRenderDefaultMaterial::MaterialDiffuseModel>(getValue(inKeySet));
384 }
385
386 void toString(QByteArray &ioStr, QSSGDataView<quint32> inKeySet) const
387 {
388 ioStr.append(name);
389 ioStr.append('=');
390 switch (getDiffuseModel(inKeySet)) {
391 case QSSGRenderDefaultMaterial::MaterialDiffuseModel::Burley:
392 ioStr.append(QByteArrayView("Burley"));
393 break;
394 case QSSGRenderDefaultMaterial::MaterialDiffuseModel::Lambert:
395 ioStr.append(QByteArrayView("Lambert"));
396 break;
397 case QSSGRenderDefaultMaterial::MaterialDiffuseModel::LambertWrap:
398 ioStr.append(QByteArrayView("LambertWrap"));
399 break;
400 }
401 }
402 void fromString(const QByteArray &ioStr, QSSGDataRef<quint32> inKeySet)
403 {
404 const qsizetype nameLen = name.size();
405 const int strOffset = ioStr.indexOf(name);
406 if (strOffset >= 0) {
407 /* The key is stored as name=specularMode; */
408 if (ioStr[strOffset + nameLen] != '=')
409 return;
410 const int codeOffsetBegin = strOffset + nameLen + 1;
411 int codeOffset = 0;
412 while (ioStr[codeOffsetBegin + codeOffset] != ';')
413 codeOffset++;
414 const QByteArray val = ioStr.mid(codeOffsetBegin, codeOffset);
415 if (val == QByteArrayView("Burley"))
416 setDiffuseModel(inKeySet, QSSGRenderDefaultMaterial::MaterialDiffuseModel::Burley);
417 if (val == QByteArrayView("Lambert"))
418 setDiffuseModel(inKeySet, QSSGRenderDefaultMaterial::MaterialDiffuseModel::Lambert);
419 if (val == QByteArrayView("LambertWrap"))
420 setDiffuseModel(inKeySet, QSSGRenderDefaultMaterial::MaterialDiffuseModel::LambertWrap);
421 }
422 }
423};
424
426{
427 // possible values:
428 // SoftShadowQuality::Hard : 00
429 // SoftShadowQuality::PCF4 : 01
430 // SoftShadowQuality::PCF8 : 10
431 // SoftShadowQuality::PCF16 : 11
432 // All others map to PCF16
433
434 explicit QSSGShaderKeyShadowSoftness(const char *inName = "") : QSSGShaderKeyUnsigned<2>(inName) {}
435
436 void setShadowSoftness(QSSGDataRef<quint32> inKeySet, QSSGRenderLight::SoftShadowQuality inQuality)
437 {
438 quint32 val = 0;
439 switch (inQuality) {
440 case QSSGRenderLight::SoftShadowQuality::Hard:
441 val = 0;
442 break;
443 case QSSGRenderLight::SoftShadowQuality::PCF4:
444 val = 1;
445 break;
446 case QSSGRenderLight::SoftShadowQuality::PCF8:
447 val = 2;
448 break;
449 case QSSGRenderLight::SoftShadowQuality::PCF16:
450 default:
451 val = 3;
452 break;
453 }
454 setValue(inKeySet, val);
455 }
456
457 QSSGRenderLight::SoftShadowQuality getShadowSoftness(QSSGDataView<quint32> inKeySet) const
458 {
459 quint32 val = getValue(inKeySet);
460 switch (val) {
461 case 0:
462 return QSSGRenderLight::SoftShadowQuality::Hard;
463 case 1:
464 return QSSGRenderLight::SoftShadowQuality::PCF4;
465 case 2:
466 return QSSGRenderLight::SoftShadowQuality::PCF8;
467 case 3:
468 default:
469 return QSSGRenderLight::SoftShadowQuality::PCF16;
470 }
471 }
472
473 void toString(QByteArray &ioStr, QSSGDataView<quint32> inKeySet) const
474 {
475 ioStr.append(name);
476 ioStr.append('=');
477 switch (getShadowSoftness(inKeySet)) {
478 case QSSGRenderLight::SoftShadowQuality::Hard:
479 ioStr.append(QByteArrayView("Hard"));
480 break;
481 case QSSGRenderLight::SoftShadowQuality::PCF4:
482 ioStr.append(QByteArrayView("PCF4"));
483 break;
484 case QSSGRenderLight::SoftShadowQuality::PCF8:
485 ioStr.append(QByteArrayView("PCF8"));
486 break;
487 case QSSGRenderLight::SoftShadowQuality::PCF16:
488 case QSSGRenderLight::SoftShadowQuality::PCF32:
489 case QSSGRenderLight::SoftShadowQuality::PCF64:
490 ioStr.append(QByteArrayView("PCF16"));
491 break;
492 }
493 }
494
495 void fromString(const QByteArray &ioStr, QSSGDataRef<quint32> inKeySet)
496 {
497 const qsizetype nameLen = name.size();
498 const int strOffset = ioStr.indexOf(name);
499 if (strOffset >= 0) {
500 /* The key is stored as name=shadowSoftness; */
501 if (ioStr[strOffset + nameLen] != '=')
502 return;
503 const int codeOffsetBegin = strOffset + nameLen + 1;
504 int codeOffset = 0;
505 while (ioStr[codeOffsetBegin + codeOffset] != ';')
506 codeOffset++;
507 const QByteArray val = ioStr.mid(codeOffsetBegin, codeOffset);
508 if (val == QByteArrayView("Hard"))
509 setShadowSoftness(inKeySet, QSSGRenderLight::SoftShadowQuality::Hard);
510 if (val == QByteArrayView("PCF4"))
511 setShadowSoftness(inKeySet, QSSGRenderLight::SoftShadowQuality::PCF4);
512 if (val == QByteArrayView("PCF8"))
513 setShadowSoftness(inKeySet, QSSGRenderLight::SoftShadowQuality::PCF8);
514 if (val == QByteArrayView("PCF16"))
515 setShadowSoftness(inKeySet, QSSGRenderLight::SoftShadowQuality::PCF16);
516 }
517 }
518
519};
520
522{
523 explicit QSSGShaderKeyAlphaMode(const char *inName = "") : QSSGShaderKeyUnsigned<2>(inName) {}
524
525 void setAlphaMode(QSSGDataRef<quint32> inKeySet, QSSGRenderDefaultMaterial::MaterialAlphaMode inMode)
526 {
527 setValue(inKeySet, quint32(inMode));
528 }
529
530 QSSGRenderDefaultMaterial::MaterialAlphaMode getAlphaMode(QSSGDataView<quint32> inKeySet) const
531 {
532 return static_cast<QSSGRenderDefaultMaterial::MaterialAlphaMode>(getValue(inKeySet));
533 }
534
535 void toString(QByteArray &ioStr, QSSGDataView<quint32> inKeySet) const
536 {
537 ioStr.append(name);
538 ioStr.append('=');
539 switch (getAlphaMode(inKeySet)) {
540 case QSSGRenderDefaultMaterial::MaterialAlphaMode::Default:
541 ioStr.append(QByteArrayView("Default"));
542 break;
543 case QSSGRenderDefaultMaterial::MaterialAlphaMode::Mask:
544 ioStr.append(QByteArrayView("Mask"));
545 break;
546 case QSSGRenderDefaultMaterial::MaterialAlphaMode::Blend:
547 ioStr.append(QByteArrayView("Blend"));
548 break;
549 case QSSGRenderDefaultMaterial::MaterialAlphaMode::Opaque:
550 ioStr.append(QByteArrayView("Opaque"));
551 break;
552 }
553 }
554 void fromString(const QByteArray &ioStr, QSSGDataRef<quint32> inKeySet)
555 {
556 const qsizetype nameLen = name.size();
557 const qsizetype strOffset = ioStr.indexOf(name);
558 if (strOffset >= 0) {
559 /* The key is stored as name=alphaMode; */
560 if (ioStr[strOffset + nameLen] != '=')
561 return;
562 const int codeOffsetBegin = strOffset + nameLen + 1;
563 int codeOffset = 0;
564 while (ioStr[codeOffsetBegin + codeOffset] != ';')
565 codeOffset++;
566 const QByteArray val = ioStr.mid(codeOffsetBegin, codeOffset);
567 if (val == QByteArrayView("Default"))
568 setAlphaMode(inKeySet, QSSGRenderDefaultMaterial::MaterialAlphaMode::Default);
569 if (val == QByteArrayView("Mask"))
570 setAlphaMode(inKeySet, QSSGRenderDefaultMaterial::MaterialAlphaMode::Mask);
571 if (val == QByteArrayView("Blend"))
572 setAlphaMode(inKeySet, QSSGRenderDefaultMaterial::MaterialAlphaMode::Blend);
573 if (val == QByteArrayView("Opaque"))
574 setAlphaMode(inKeySet, QSSGRenderDefaultMaterial::MaterialAlphaMode::Opaque);
575 }
576 }
577};
578
580{
582 Position = 1 << 0,
583 Normal = 1 << 1,
584 TexCoord0 = 1 << 2,
585 TexCoord1 = 1 << 3,
586 Tangent = 1 << 4,
587 Binormal = 1 << 5,
588 Color = 1 << 6,
591 };
592
593 explicit QSSGShaderKeyVertexAttribute(const char *inName = "") : QSSGShaderKeyUnsigned<9>(inName) {}
594
595 bool getBitValue(VertexAttributeBits bit, QSSGDataView<quint32> inKeySet) const
596 {
597 return (getValue(inKeySet) & bit) ? true : false;
598 }
599 void setBitValue(VertexAttributeBits bit, QSSGDataRef<quint32> inKeySet, bool value) const
600 {
601 quint32 v = getValue(inKeySet);
602 v = value ? (v | bit) : (v & ~bit);
603 setValue(inKeySet, v);
604 }
605
606 void toString(QByteArray &ioStr, QSSGDataView<quint32> inKeySet) const
607 {
608 ioStr.append(name);
609 ioStr.append(QByteArrayView("={"));
610 internalToString(ioStr, QByteArrayView("position"), getBitValue(Position, inKeySet));
611 ioStr.append(';');
612 internalToString(ioStr, QByteArrayView("normal"), getBitValue(Normal, inKeySet));
613 ioStr.append(';');
614 internalToString(ioStr, QByteArrayView("texcoord0"), getBitValue(TexCoord0, inKeySet));
615 ioStr.append(';');
616 internalToString(ioStr, QByteArrayView("texcoord1"), getBitValue(TexCoord1, inKeySet));
617 ioStr.append(';');
618 internalToString(ioStr, QByteArrayView("tangent"), getBitValue(Tangent, inKeySet));
619 ioStr.append(';');
620 internalToString(ioStr, QByteArrayView("binormal"), getBitValue(Binormal, inKeySet));
621 ioStr.append(';');
622 internalToString(ioStr, QByteArrayView("color"), getBitValue(Color, inKeySet));
623 ioStr.append(';');
624 internalToString(ioStr, QByteArrayView("texcoordlightmap"), getBitValue(TexCoordLightmap, inKeySet));
625 ioStr.append(';');
626 internalToString(ioStr, QByteArrayView("joint&weight"), getBitValue(JointAndWeight, inKeySet));
627 ioStr.append('}');
628 }
629 void fromString(const QByteArray &ioStr, QSSGDataRef<quint32> inKeySet)
630 {
631 const qsizetype nameLen = name.size();
632 const qsizetype strOffset = ioStr.indexOf(name);
633 if (strOffset >= 0) {
634 /* The key is stored as name={;;;;;;} */
635 if (ioStr[strOffset + nameLen] != '=')
636 return;
637 if (ioStr[strOffset + nameLen + 1] != '{')
638 return;
639 const int codeOffsetBegin = strOffset + nameLen + 2;
640 int codeOffset = 0;
641 while (ioStr[codeOffsetBegin + codeOffset] != '}')
642 codeOffset++;
643 const QByteArray val = ioStr.mid(codeOffsetBegin, codeOffset);
644 const QVector<QByteArray> list = val.split(';');
645 if (list.size() != 8)
646 return;
647 setBitValue(Position, inKeySet, getBoolValue(list[0], QByteArrayView("position")));
648 setBitValue(Normal, inKeySet, getBoolValue(list[1], QByteArrayView("normal")));
649 setBitValue(TexCoord0, inKeySet, getBoolValue(list[2], QByteArrayView("texcoord0")));
650 setBitValue(TexCoord1, inKeySet, getBoolValue(list[3], QByteArrayView("texcoord1")));
651 setBitValue(Tangent, inKeySet, getBoolValue(list[4], QByteArrayView("tangent")));
652 setBitValue(Binormal, inKeySet, getBoolValue(list[5], QByteArrayView("binormal")));
653 setBitValue(Color, inKeySet, getBoolValue(list[6], QByteArrayView("color")));
654 setBitValue(TexCoordLightmap, inKeySet, getBoolValue(list[7], QByteArrayView("texcoordlightmap")));
655 }
656 }
657};
658
660{
661 enum {
663 };
711
772
774 : m_hasLighting("hasLighting")
775 , m_hasPunctualLights("hasPunctualLights")
776 , m_hasShadows("hasShadows")
777 , m_hasIbl("hasIbl")
778 , m_specularEnabled("specularEnabled")
779 , m_fresnelScaleBiasEnabled("fresnelScaleBiasEnabled")
780 , m_clearcoatFresnelScaleBiasEnabled("clearcoatFresnelScaleBiasEnabled")
781 , m_fresnelEnabled("fresnelEnabled")
782 , m_baseColorSingleChannelEnabled("baseColorSingleChannelEnabled")
783 , m_specularSingleChannelEnabled("specularSingleChannelEnabled")
784 , m_emissiveSingleChannelEnabled("emissiveSingleChannelEnabled")
785 , m_invertOpacityMapValue("invertOpacityMapValue")
786 , m_vertexColorsEnabled("vertexColorsEnabled")
787 , m_vertexColorsMaskEnabled("vertexColorsMaskEnabled")
788 , m_vertexColorRedMask("vertexColorRedMask")
789 , m_vertexColorGreenMask("vertexColorGreenMask")
790 , m_vertexColorBlueMask("vertexColorBlueMask")
791 , m_vertexColorAlphaMask("vertexColorAlphaMask")
792 , m_specularModel("specularModel")
793 , m_diffuseModel("diffuseModel")
794 , m_boneCount("boneCount")
795 , m_isDoubleSided("isDoubleSided")
796 , m_overridesPosition("overridesPosition")
797 , m_usesProjectionMatrix("usesProjectionMatrix")
798 , m_usesInverseProjectionMatrix("usesInverseProjectionMatrix")
799 , m_usesPointsTopology("usesPointsTopology")
800 , m_usesVarColor("usesVarColor")
801 , m_alphaMode("alphaMode")
802 , m_vertexAttributes("vertexAttributes")
803 , m_usesFloatJointIndices("usesFloatJointIndices")
804 , m_usesInstancing("usesInstancing")
805 , m_targetCount("targetCount")
806 , m_targetPositionOffset("targetPositionOffset")
807 , m_targetNormalOffset("targetNormalOffset")
808 , m_targetTangentOffset("targetTangentOffset")
809 , m_targetBinormalOffset("targetBinormalOffset")
810 , m_targetTexCoord0Offset("targetTexCoord0Offset")
811 , m_targetTexCoord1Offset("targetTexCoord1Offset")
812 , m_targetColorOffset("targetColorOffset")
813 , m_blendParticles("blendParticles")
814 , m_clearcoatEnabled("clearcoatEnabled")
815 , m_sheenEnabled("sheenEnabled")
816 , m_anisotropyEnabled("anisotropyEnabled")
817 , m_iridescenceEnabled("iridescenceEnabled")
818 , m_dispersionEnabled("dispersionEnabled")
819 , m_transmissionEnabled("transmissionEnabled")
820 , m_specularAAEnabled("specularAAEnabled")
821 , m_lightmapEnabled("lightmapEnabled")
822 , m_specularGlossyEnabled("specularGlossyEnabled")
823 , m_metallicRoughnessEnabled("metallicRoughnessEnabled")
824 , m_debugMode("debugMode")
825 , m_fogEnabled("fogEnabled")
826 , m_viewCount("viewCount")
827 , m_usesViewIndex("usesViewIndex")
828 , m_oitMSAA("oitMSAA")
829 , m_orderIndependentTransparency("orderIndependentTransparency")
830 , m_shadowSoftness("shadowSoftness")
831 {
832 m_imageMaps[DiffuseMap].name = "diffuseMap";
833 m_imageMaps[BumpMap].name = "bumpMap";
834 m_imageMaps[SpecularMap].name = "specularMap";
835 m_imageMaps[NormalMap].name = "normalMap";
836 m_imageMaps[ClearcoatNormalMap].name = "clearcoatNormalMap";
837 m_imageMaps[SheenColorMap].name = "sheenColorMap";
838 m_imageMaps[AnisotropyMap].name = "anisotropyMap";
839 m_imageMaps[OpacityMap].name = "opacityMap";
840 m_imageMaps[RoughnessMap].name = "roughnessMap";
841 m_imageMaps[MetalnessMap].name = "metalnessMap";
842 m_imageMaps[OcclusionMap].name = "occlusionMap";
843 m_imageMaps[TranslucencyMap].name = "translucencyMap";
844 m_imageMaps[HeightMap].name = "heightMap";
845 m_imageMaps[ClearcoatMap].name = "clearcoatMap";
846 m_imageMaps[ClearcoatRoughnessMap].name = "clearcoatRoughnessMap";
847 m_imageMaps[TransmissionMap].name = "transmissionMap";
848 m_imageMaps[ThicknessMap].name = "thicknessMap";
849 m_imageMaps[BaseColorMap].name = "baseColorMap";
850 m_imageMaps[SpecularAmountMap].name = "specularAmountMap";
851 m_imageMaps[EmissiveMap].name = "emissiveMap";
852 m_imageMaps[SheenRoughnessMap].name = "sheenRoughnessMap";
853 m_imageMaps[IridescenceMap].name = "iridescenceMap";
854 m_imageMaps[IridescenceThicknessMap].name = "iridescenceThicknessMap";
855
856 m_textureChannels[OpacityChannel].name = "opacityMap_channel";
857 m_textureChannels[RoughnessChannel].name = "roughnessMap_channel";
858 m_textureChannels[MetalnessChannel].name = "metalnessMap_channel";
859 m_textureChannels[OcclusionChannel].name = "occlusionMap_channel";
860 m_textureChannels[TranslucencyChannel].name = "translucencyMap_channel";
861 m_textureChannels[HeightChannel].name = "heightMap_channel";
862 m_textureChannels[ClearcoatChannel].name = "clearcoatMap_channel";
863 m_textureChannels[ClearcoatRoughnessChannel].name = "clearcoatRoughnessMap_channel";
864 m_textureChannels[TransmissionChannel].name = "transmissionMap_channel";
865 m_textureChannels[ThicknessChannel].name = "thicknessMap_channel";
866 m_textureChannels[BaseColorChannel].name = "baseColorMap_channel";
867 m_textureChannels[SpecularAmountChannel].name = "specularAmountMap_channel";
868 m_textureChannels[EmissiveChannel].name = "emissiveMap_channel";
869 m_textureChannels[SheenRoughnessChannel].name = "sheenRoughnessMap_channel";
870 m_textureChannels[IridescenceChannel].name = "iridescenceMap_channel";
871 m_textureChannels[IridescenceThicknessChannel].name = "iridescenceThicknessMap_channel";
872
873 init();
874 }
875
876 template<typename TVisitor>
877 void visitProperties(TVisitor &inVisitor)
878 {
879 inVisitor.visit(m_hasLighting);
880 inVisitor.visit(m_hasPunctualLights);
881 inVisitor.visit(m_hasShadows);
882 inVisitor.visit(m_hasIbl);
883 inVisitor.visit(m_specularEnabled);
884 inVisitor.visit(m_fresnelEnabled);
885 inVisitor.visit(m_fresnelScaleBiasEnabled);
886 inVisitor.visit(m_clearcoatFresnelScaleBiasEnabled);
887 inVisitor.visit(m_baseColorSingleChannelEnabled);
888 inVisitor.visit(m_specularSingleChannelEnabled);
889 inVisitor.visit(m_emissiveSingleChannelEnabled);
890 inVisitor.visit(m_invertOpacityMapValue);
891 inVisitor.visit(m_vertexColorsEnabled);
892 inVisitor.visit(m_vertexColorsMaskEnabled);
893 inVisitor.visit(m_vertexColorRedMask);
894 inVisitor.visit(m_vertexColorGreenMask);
895 inVisitor.visit(m_vertexColorBlueMask);
896 inVisitor.visit(m_vertexColorAlphaMask);
897 inVisitor.visit(m_specularModel);
898 inVisitor.visit(m_diffuseModel);
899
900 for (quint32 idx = 0, end = ImageMapCount; idx < end; ++idx)
901 inVisitor.visit(m_imageMaps[idx]);
902
903 for (auto &textureChannel : m_textureChannels)
904 inVisitor.visit(textureChannel);
905
906 inVisitor.visit(m_boneCount);
907 inVisitor.visit(m_isDoubleSided);
908 inVisitor.visit(m_overridesPosition);
909 inVisitor.visit(m_usesProjectionMatrix);
910 inVisitor.visit(m_usesInverseProjectionMatrix);
911 inVisitor.visit(m_usesPointsTopology);
912 inVisitor.visit(m_usesVarColor);
913 inVisitor.visit(m_alphaMode);
914 inVisitor.visit(m_vertexAttributes);
915 inVisitor.visit(m_usesFloatJointIndices);
916 inVisitor.visit(m_usesInstancing);
917 inVisitor.visit(m_targetCount);
918 inVisitor.visit(m_targetPositionOffset);
919 inVisitor.visit(m_targetNormalOffset);
920 inVisitor.visit(m_targetTangentOffset);
921 inVisitor.visit(m_targetBinormalOffset);
922 inVisitor.visit(m_targetTexCoord0Offset);
923 inVisitor.visit(m_targetTexCoord1Offset);
924 inVisitor.visit(m_targetColorOffset);
925 inVisitor.visit(m_blendParticles);
926 inVisitor.visit(m_clearcoatEnabled);
927 inVisitor.visit(m_sheenEnabled);
928 inVisitor.visit(m_anisotropyEnabled);
929 inVisitor.visit(m_iridescenceEnabled);
930 inVisitor.visit(m_dispersionEnabled);
931 inVisitor.visit(m_transmissionEnabled);
932 inVisitor.visit(m_specularAAEnabled);
933 inVisitor.visit(m_lightmapEnabled);
934 inVisitor.visit(m_specularGlossyEnabled);
935 inVisitor.visit(m_metallicRoughnessEnabled);
936 inVisitor.visit(m_debugMode);
937 inVisitor.visit(m_fogEnabled);
938 inVisitor.visit(m_viewCount);
939 inVisitor.visit(m_usesViewIndex);
940 inVisitor.visit(m_oitMSAA);
941 inVisitor.visit(m_orderIndependentTransparency);
942 inVisitor.visit(m_shadowSoftness);
943 }
944
946 {
949 template<typename TPropType>
950 void visit(TPropType &inProp)
951 {
952 // if we cross the 32 bit border we just move
953 // to the next dword.
954 // This cost a few extra bits but prevents tedious errors like
955 // loosing shader key bits because they got moved beyond the 32 border
956 quint32 bit = m_offset % 32;
957 if (bit + TPropType::BitWidth > 32) {
958 m_offset += 32 - bit;
959 }
960
961 inProp.setOffset(m_offset);
962 m_offset += TPropType::BitWidth;
963 }
964 };
965
967 {
969 template<typename P>
970 constexpr void visit(const P &prop)
971 {
972 size += prop.name.size();
973 }
974 };
975
977 {
980
981 template<typename P>
982 void visit(P &prop)
983 {
984 offsetVisitor.visit(prop);
985 stringSizeVisitor.visit(prop);
986 }
987 };
988
989 void init()
990 {
991 InitVisitor visitor;
992 visitProperties(visitor);
993
994 // If this assert fires, then the default material key needs more bits.
995 Q_ASSERT(visitor.offsetVisitor.m_offset < 800);
996 // This is so we can do some guestimate of how big the string buffer needs
997 // to be to avoid doing a lot of allocations when concatenating the strings.
998 m_stringBufferSizeHint = visitor.stringSizeVisitor.size;
999 }
1000};
1001
1002template <typename Props, size_t size>
1004{
1005 enum {
1007 };
1010
1012 {
1013 for (size_t idx = 0; idx < DataBufferSize; ++idx)
1014 m_dataBuffer[idx] = 0;
1015 }
1016
1018 {
1019 for (size_t idx = 0; idx < DataBufferSize; ++idx)
1020 m_dataBuffer[idx] = 0;
1021 }
1022
1023 size_t hash() const
1024 {
1025 size_t retval = 0;
1026 for (size_t idx = 0; idx < DataBufferSize; ++idx)
1027 retval = retval ^ qHash(m_dataBuffer[idx]);
1028 return retval ^ m_featureSetHash;
1029 }
1030
1031 bool operator==(const QSSGShaderBaseMaterialKey<Props, size> &other) const
1032 {
1033 bool retval = true;
1034 for (size_t idx = 0; idx < DataBufferSize && retval; ++idx)
1035 retval = m_dataBuffer[idx] == other.m_dataBuffer[idx];
1036 return retval && m_featureSetHash == other.m_featureSetHash;
1037 }
1038
1039 // Cast operators to make getting properties easier.
1042
1044 {
1048 template<typename TPropType>
1049 void visit(const TPropType &prop)
1050 {
1051 const qsizetype originalSize = m_str.size();
1052 if (m_str.size())
1053 m_str.append(';');
1055 // if the only thing we added was the semicolon
1056 // then nuke the semicolon
1057 if (originalSize && m_str.size() == (originalSize + 1))
1059 }
1060 };
1061
1063 {
1066 StringInVisitor(const QByteArray &s, QSSGDataRef<quint32> ks) : m_str(s), m_keyStore(ks) {}
1067
1068 template<typename TPropType>
1069 void visit(TPropType &prop)
1070 {
1071 prop.fromString(m_str, m_keyStore);
1072 }
1073 };
1074
1075 void toString(QByteArray &ioString, const Props &inProperties) const
1076 {
1077 ioString.reserve(inProperties.m_stringBufferSizeHint);
1078 StringVisitor theVisitor(ioString, *this);
1079 const_cast<Props &>(inProperties).visitProperties(theVisitor);
1080 }
1081 void fromString(QByteArray &ioString, Props &inProperties)
1082 {
1083 StringInVisitor theVisitor(ioString, *this);
1084 inProperties.visitProperties(theVisitor);
1085 }
1087 {
1088 QByteArray ret;
1089 ret.resize(sizeof(m_dataBuffer));
1090 memcpy(ret.data(), m_dataBuffer, sizeof(m_dataBuffer));
1091 return ret;
1092 }
1093 bool fromByteArray(const QByteArray &data) const
1094 {
1095 if (data.size() != sizeof(m_dataBuffer))
1096 return false;
1097 memcpy((void *)m_dataBuffer, data.data(), sizeof(m_dataBuffer));
1098 return true;
1099 }
1100};
1101
1103
1104Q_STATIC_ASSERT(std::is_trivially_destructible<QSSGShaderDefaultMaterialKey>::value);
1105
1106
1108{
1109 return key.hash();
1110}
1111
1112QT_END_NAMESPACE
1113
1114#endif
QSSGShaderBaseMaterialKey< QSSGShaderDefaultMaterialKeyProperties, 25 > QSSGShaderDefaultMaterialKey
size_t qHash(const QSSGShaderDefaultMaterialKey &key)
StringInVisitor(const QByteArray &s, QSSGDataRef< quint32 > ks)
bool operator==(const QSSGShaderBaseMaterialKey< Props, size > &other) const
void toString(QByteArray &ioString, const Props &inProperties) const
bool fromByteArray(const QByteArray &data) const
QSSGShaderBaseMaterialKey(size_t inFeatureSetHash)
void fromString(QByteArray &ioString, Props &inProperties)
quint32 m_dataBuffer[DataBufferSize]
QSSGShaderKeyUnsigned< 8 > m_targetTexCoord1Offset
QSSGShaderKeyTextureChannel m_textureChannels[SingleChannelImageCount]
QSSGShaderKeyUnsigned< 16 > m_vertexColorAlphaMask
QSSGShaderKeyImageMap m_imageMaps[ImageMapCount]
QSSGShaderKeyUnsigned< 8 > m_targetPositionOffset
QSSGShaderKeyUnsigned< 8 > m_targetTexCoord0Offset
QSSGShaderKeyUnsigned< 16 > m_vertexColorBlueMask
QSSGShaderKeyVertexAttribute m_vertexAttributes
QSSGShaderKeyUnsigned< 8 > m_targetBinormalOffset
QSSGShaderKeyUnsigned< 16 > m_vertexColorGreenMask
QSSGShaderKeyUnsigned< 3 > m_orderIndependentTransparency
QSSGShaderKeyUnsigned< 16 > m_vertexColorRedMask
void toString(QByteArray &ioStr, QSSGDataView< quint32 > inKeySet) const
QSSGRenderDefaultMaterial::MaterialAlphaMode getAlphaMode(QSSGDataView< quint32 > inKeySet) const
QSSGShaderKeyAlphaMode(const char *inName="")
void setAlphaMode(QSSGDataRef< quint32 > inKeySet, QSSGRenderDefaultMaterial::MaterialAlphaMode inMode)
void fromString(const QByteArray &ioStr, QSSGDataRef< quint32 > inKeySet)
void setValue(QSSGDataRef< quint32 > inDataStore, bool inValue) const
void toString(QByteArray &ioStr, QSSGDataView< quint32 > inKeySet) const
constexpr QSSGShaderKeyBoolean(const char *inName="")
bool getValue(QSSGDataView< quint32 > inDataStore) const
void fromString(const QByteArray &ioStr, QSSGDataRef< quint32 > inKeySet)
QSSGShaderKeyDiffuseModel(const char *inName="")
void setDiffuseModel(QSSGDataRef< quint32 > inKeySet, QSSGRenderDefaultMaterial::MaterialDiffuseModel inModel)
QSSGRenderDefaultMaterial::MaterialDiffuseModel getDiffuseModel(QSSGDataView< quint32 > inKeySet) const
void fromString(const QByteArray &ioStr, QSSGDataRef< quint32 > inKeySet)
void toString(QByteArray &ioStr, QSSGDataView< quint32 > inKeySet) const
void setIdentityTransform(QSSGDataRef< quint32 > inKeySet, bool val)
void setPreMultipliedAlpha(QSSGDataRef< quint32 > inKeySet, bool val)
bool isPreMultipliedAlpha(QSSGDataView< quint32 > inKeySet) const
void setBitValue(ImageMapBits imageBit, bool inValue, QSSGDataRef< quint32 > inKeySet)
void setEnabled(QSSGDataRef< quint32 > inKeySet, bool val)
bool isUsingUV1(QSSGDataView< quint32 > inKeySet) const
QSSGShaderKeyImageMap(const char *inName="")
void toString(QByteArray &ioStr, QSSGDataView< quint32 > inKeySet) const
bool isIdentityTransform(QSSGDataView< quint32 > inKeySet) const
bool isEnabled(QSSGDataView< quint32 > inKeySet) const
bool isLightProbe(QSSGDataView< quint32 > inKeySet) const
void setLinear(QSSGDataRef< quint32 > inKeySet, bool val)
void setUsesUV1(QSSGDataRef< quint32 > inKeySet, bool val)
bool isEnvMap(QSSGDataView< quint32 > inKeySet) const
bool getBitValue(ImageMapBits imageBit, QSSGDataView< quint32 > inKeySet) const
void setLightProbe(QSSGDataRef< quint32 > inKeySet, bool val)
bool isLinear(QSSGDataView< quint32 > inKeySet) const
void setEnvMap(QSSGDataRef< quint32 > inKeySet, bool val)
QSSGShaderKeyShadowSoftness(const char *inName="")
void setShadowSoftness(QSSGDataRef< quint32 > inKeySet, QSSGRenderLight::SoftShadowQuality inQuality)
void toString(QByteArray &ioStr, QSSGDataView< quint32 > inKeySet) const
void fromString(const QByteArray &ioStr, QSSGDataRef< quint32 > inKeySet)
QSSGRenderLight::SoftShadowQuality getShadowSoftness(QSSGDataView< quint32 > inKeySet) const
QSSGRenderDefaultMaterial::MaterialSpecularModel getSpecularModel(QSSGDataView< quint32 > inKeySet) const
void setSpecularModel(QSSGDataRef< quint32 > inKeySet, QSSGRenderDefaultMaterial::MaterialSpecularModel inModel)
void fromString(const QByteArray &ioStr, QSSGDataRef< quint32 > inKeySet)
void toString(QByteArray &ioStr, QSSGDataView< quint32 > inKeySet) const
QSSGShaderKeySpecularModel(const char *inName="")
void fromString(const QByteArray &ioStr, QSSGDataRef< quint32 > inKeySet)
void setTextureChannel(TexturChannelBits channel, QSSGDataRef< quint32 > inKeySet)
static constexpr char textureChannelToChar[4]
TexturChannelBits getTextureChannel(QSSGDataView< quint32 > inKeySet) const
void toString(QByteArray &ioStr, QSSGDataView< quint32 > inKeySet) const
QSSGShaderKeyTextureChannel(const char *inName="")
void fromString(const QByteArray &ioStr, QSSGDataRef< quint32 > inKeySet)
constexpr QSSGShaderKeyUnsigned(const char *inName="")
void setValue(QSSGDataRef< quint32 > inDataStore, quint32 inValue) const
quint32 getValue(QSSGDataView< quint32 > inDataStore) const
void toString(QByteArray &ioStr, QSSGDataView< quint32 > inKeySet) const
void toString(QByteArray &ioStr, QSSGDataView< quint32 > inKeySet) const
bool getBitValue(VertexAttributeBits bit, QSSGDataView< quint32 > inKeySet) const
QSSGShaderKeyVertexAttribute(const char *inName="")
void fromString(const QByteArray &ioStr, QSSGDataRef< quint32 > inKeySet)
void setBitValue(VertexAttributeBits bit, QSSGDataRef< quint32 > inKeySet, bool value) const