Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qshader.cpp
Go to the documentation of this file.
1// Copyright (C) 2023 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qshader_p.h"
5#include <QDataStream>
6#include <QBuffer>
7
9
256 : d(nullptr)
257{
258}
259
264{
265 if (d)
266 qAtomicDetach(d);
267 else
268 d = new QShaderPrivate;
269}
270
275 : d(other.d)
276{
277 if (d)
278 d->ref.ref();
279}
280
285{
286 if (d) {
287 if (other.d) {
288 qAtomicAssign(d, other.d);
289 } else {
290 if (!d->ref.deref())
291 delete d;
292 d = nullptr;
293 }
294 } else if (other.d) {
295 other.d->ref.ref();
296 d = other.d;
297 }
298 return *this;
299}
300
305{
306 if (d && !d->ref.deref())
307 delete d;
308}
309
314{
315 return d ? !d->shaders.isEmpty() : false;
316}
317
322{
323 return d ? d->stage : QShader::VertexStage;
324}
325
330{
331 if (!d || stage != d->stage) {
332 detach();
333 d->stage = stage;
334 }
335}
336
341{
342 return d ? d->desc : QShaderDescription();
343}
344
349{
350 detach();
351 d->desc = desc;
352}
353
358{
359 return d ? d->shaders.keys().toVector() : QList<QShaderKey>();
360}
361
366{
367 return d ? d->shaders.value(key) : QShaderCode();
368}
369
374{
375 if (d && d->shaders.value(key) == shader)
376 return;
377
378 detach();
379 d->shaders[key] = shader;
380}
381
387{
388 if (!d)
389 return;
390
391 auto it = d->shaders.find(key);
392 if (it == d->shaders.end())
393 return;
394
395 detach();
396 d->shaders.erase(it);
397}
398
399static void writeShaderKey(QDataStream *ds, const QShaderKey &k)
400{
401 *ds << int(k.source());
402 *ds << k.sourceVersion().version();
403 *ds << k.sourceVersion().flags();
404 *ds << int(k.sourceVariant());
405}
406
421{
422 static QShaderPrivate sd;
423 QShaderPrivate *dd = d ? d : &sd;
424
425 QBuffer buf;
426 QDataStream ds(&buf);
428 if (!buf.open(QIODevice::WriteOnly))
429 return QByteArray();
430
431 const int qsbVersion = QShaderPrivate::qtQsbVersion(version);
432 ds << qsbVersion;
433
434 ds << int(dd->stage);
435 dd->desc.serialize(&ds, qsbVersion);
436 ds << int(dd->shaders.size());
437 for (auto it = dd->shaders.cbegin(), itEnd = dd->shaders.cend(); it != itEnd; ++it) {
438 const QShaderKey &k(it.key());
439 writeShaderKey(&ds, k);
440 const QShaderCode &shader(dd->shaders.value(k));
441 ds << shader.shader();
442 ds << shader.entryPoint();
443 }
444 ds << int(dd->bindings.size());
445 for (auto it = dd->bindings.cbegin(), itEnd = dd->bindings.cend(); it != itEnd; ++it) {
446 const QShaderKey &k(it.key());
447 writeShaderKey(&ds, k);
448 const NativeResourceBindingMap &map(it.value());
449 ds << int(map.size());
450 for (auto mapIt = map.cbegin(), mapItEnd = map.cend(); mapIt != mapItEnd; ++mapIt) {
451 ds << mapIt.key();
452 ds << mapIt.value().first;
453 ds << mapIt.value().second;
454 }
455 }
456 ds << int(dd->combinedImageMap.size());
457 for (auto it = dd->combinedImageMap.cbegin(), itEnd = dd->combinedImageMap.cend(); it != itEnd; ++it) {
458 const QShaderKey &k(it.key());
459 writeShaderKey(&ds, k);
461 ds << int(list.size());
462 for (auto listIt = list.cbegin(), listItEnd = list.cend(); listIt != listItEnd; ++listIt) {
463 ds << listIt->combinedSamplerName;
464 ds << listIt->textureBinding;
465 ds << listIt->samplerBinding;
466 }
467 }
469 ds << int(dd->nativeShaderInfoMap.size());
470 for (auto it = dd->nativeShaderInfoMap.cbegin(), itEnd = dd->nativeShaderInfoMap.cend(); it != itEnd; ++it) {
471 const QShaderKey &k(it.key());
472 writeShaderKey(&ds, k);
473 ds << it->flags;
474 ds << int(it->extraBufferBindings.size());
475 for (auto mapIt = it->extraBufferBindings.cbegin(), mapItEnd = it->extraBufferBindings.cend();
476 mapIt != mapItEnd; ++mapIt)
477 {
478 ds << mapIt.key();
479 ds << mapIt.value();
480 }
481 }
482 }
483
484 return qCompress(buf.buffer());
485}
486
488{
489 int intVal;
490 *ds >> intVal;
491 k->setSource(QShader::Source(intVal));
492 QShaderVersion ver;
493 *ds >> intVal;
494 ver.setVersion(intVal);
495 *ds >> intVal;
496 ver.setFlags(QShaderVersion::Flags(intVal));
497 k->setSourceVersion(ver);
498 *ds >> intVal;
500}
501
511{
512 QByteArray udata = qUncompress(data);
513 QBuffer buf(&udata);
514 QDataStream ds(&buf);
516 if (!buf.open(QIODevice::ReadOnly))
517 return QShader();
518
519 QShader bs;
520 bs.detach(); // to get d created
522 Q_ASSERT(d->ref.loadRelaxed() == 1); // must be detached
523 int intVal;
524 ds >> intVal;
525 d->qsbVersion = intVal;
526 if (d->qsbVersion != QShaderPrivate::QSB_VERSION
535 {
536 qWarning("Attempted to deserialize QShader with unknown version %d.", d->qsbVersion);
537 return QShader();
538 }
539
540 ds >> intVal;
541 d->stage = Stage(intVal);
542 if (d->qsbVersion > QShaderPrivate::QSB_VERSION_WITH_CBOR) {
543 d->desc = QShaderDescription::deserialize(&ds, d->qsbVersion);
544 } else if (d->qsbVersion > QShaderPrivate::QSB_VERSION_WITH_BINARY_JSON) {
545 qWarning("Can no longer load QShaderDescription from CBOR.");
546 d->desc = QShaderDescription();
547 } else {
548 qWarning("Can no longer load QShaderDescription from binary JSON.");
549 d->desc = QShaderDescription();
550 }
551 int count;
552 ds >> count;
553 for (int i = 0; i < count; ++i) {
554 QShaderKey k;
555 readShaderKey(&ds, &k);
558 ds >> s;
559 shader.setShader(s);
560 ds >> s;
561 shader.setEntryPoint(s);
562 d->shaders[k] = shader;
563 }
564
566 ds >> count;
567 for (int i = 0; i < count; ++i) {
568 QShaderKey k;
569 readShaderKey(&ds, &k);
571 int mapSize;
572 ds >> mapSize;
573 for (int b = 0; b < mapSize; ++b) {
574 int binding;
575 ds >> binding;
576 int firstNativeBinding;
577 ds >> firstNativeBinding;
578 int secondNativeBinding;
579 ds >> secondNativeBinding;
580 map.insert(binding, { firstNativeBinding, secondNativeBinding });
581 }
582 d->bindings.insert(k, map);
583 }
584 }
585
587 ds >> count;
588 for (int i = 0; i < count; ++i) {
589 QShaderKey k;
590 readShaderKey(&ds, &k);
592 int listSize;
593 ds >> listSize;
594 for (int b = 0; b < listSize; ++b) {
595 QByteArray combinedSamplerName;
596 ds >> combinedSamplerName;
597 int textureBinding;
598 ds >> textureBinding;
599 int samplerBinding;
600 ds >> samplerBinding;
601 list.append({ combinedSamplerName, textureBinding, samplerBinding });
602 }
603 d->combinedImageMap.insert(k, list);
604 }
605 }
606
608 ds >> count;
609 for (int i = 0; i < count; ++i) {
610 QShaderKey k;
611 readShaderKey(&ds, &k);
612 int flags;
613 ds >> flags;
614 QMap<int, int> extraBufferBindings;
615 int mapSize;
616 ds >> mapSize;
617 for (int b = 0; b < mapSize; ++b) {
618 int k, v;
619 ds >> k;
620 ds >> v;
621 extraBufferBindings.insert(k, v);
622 }
623 d->nativeShaderInfoMap.insert(k, { flags, extraBufferBindings });
624 }
625 }
626
627 return bs;
628}
629
638 : m_version(v), m_flags(f)
639{
640}
641
671 : m_shader(code), m_entryPoint(entry)
672{
673}
674
704 const QShaderVersion &sver,
705 QShader::Variant svar)
706 : m_source(s),
707 m_sourceVersion(sver),
708 m_sourceVariant(svar)
709{
710}
711
749bool operator==(const QShader &lhs, const QShader &rhs) noexcept
750{
751 if (!lhs.d || !rhs.d)
752 return lhs.d == rhs.d;
753
754 return lhs.d->stage == rhs.d->stage
755 && lhs.d->shaders == rhs.d->shaders
756 && lhs.d->bindings == rhs.d->bindings;
757}
758
773size_t qHash(const QShader &s, size_t seed) noexcept
774{
775 if (s.d) {
777 seed = hash(seed, s.stage());
778 if (!s.d->shaders.isEmpty()) {
779 seed = hash(seed, s.d->shaders.firstKey());
780 seed = hash(seed, s.d->shaders.first());
781 }
782 }
783 return seed;
784}
785
792bool operator==(const QShaderVersion &lhs, const QShaderVersion &rhs) noexcept
793{
794 return lhs.version() == rhs.version() && lhs.flags() == rhs.flags();
795}
796
797#ifdef Q_OS_INTEGRITY
798size_t qHash(const QShaderVersion &s, size_t seed) noexcept
799{
800 return qHashMulti(seed, s.version(), s.flags());
801}
802#endif
803
811bool operator<(const QShaderVersion &lhs, const QShaderVersion &rhs) noexcept
812{
813 if (lhs.version() < rhs.version())
814 return true;
815
816 if (lhs.version() == rhs.version())
817 return int(lhs.flags()) < int(rhs.flags());
818
819 return false;
820}
821
836bool operator==(const QShaderKey &lhs, const QShaderKey &rhs) noexcept
837{
838 return lhs.source() == rhs.source() && lhs.sourceVersion() == rhs.sourceVersion()
839 && lhs.sourceVariant() == rhs.sourceVariant();
840}
841
849bool operator<(const QShaderKey &lhs, const QShaderKey &rhs) noexcept
850{
851 if (int(lhs.source()) < int(rhs.source()))
852 return true;
853
854 if (int(lhs.source()) == int(rhs.source())) {
855 if (lhs.sourceVersion() < rhs.sourceVersion())
856 return true;
857 if (lhs.sourceVersion() == rhs.sourceVersion()) {
858 if (int(lhs.sourceVariant()) < int(rhs.sourceVariant()))
859 return true;
860 }
861 }
862
863 return false;
864}
865
880size_t qHash(const QShaderKey &k, size_t seed) noexcept
881{
882 return qHashMulti(seed,
883 k.source(),
884 k.sourceVersion().version(),
885 k.sourceVersion().flags(),
886 k.sourceVariant());
887}
888
894bool operator==(const QShaderCode &lhs, const QShaderCode &rhs) noexcept
895{
896 return lhs.shader() == rhs.shader() && lhs.entryPoint() == rhs.entryPoint();
897}
898
913size_t qHash(const QShaderCode &k, size_t seed) noexcept
914{
915 return qHash(k.shader(), seed);
916}
917
918#ifndef QT_NO_DEBUG_STREAM
920{
921 const QShaderPrivate *d = bs.d;
922 QDebugStateSaver saver(dbg);
923
924 if (d) {
925 dbg.nospace() << "QShader("
926 << "stage=" << d->stage
927 << " shaders=" << d->shaders.keys()
928 << " desc.isValid=" << d->desc.isValid()
929 << ')';
930 } else {
931 dbg.nospace() << "QShader()";
932 }
933
934 return dbg;
935}
936
938{
939 QDebugStateSaver saver(dbg);
940 dbg.nospace() << "ShaderKey(" << k.source()
941 << " " << k.sourceVersion()
942 << " " << k.sourceVariant() << ")";
943 return dbg;
944}
945
947{
948 QDebugStateSaver saver(dbg);
949 dbg.nospace() << "Version(" << v.version() << " " << v.flags() << ")";
950 return dbg;
951}
952#endif // QT_NO_DEBUG_STREAM
953
995{
996 if (!d)
997 return {};
998
999 auto it = d->bindings.constFind(key);
1000 if (it == d->bindings.cend())
1001 return {};
1002
1003 return it.value();
1004}
1005
1012{
1013 detach();
1014 d->bindings[key] = map;
1015}
1016
1021{
1022 if (!d)
1023 return;
1024
1025 auto it = d->bindings.find(key);
1026 if (it == d->bindings.end())
1027 return;
1028
1029 detach();
1030 d->bindings.erase(it);
1031}
1032
1075{
1076 if (!d)
1077 return {};
1078
1079 auto it = d->combinedImageMap.constFind(key);
1080 if (it == d->combinedImageMap.cend())
1081 return {};
1082
1083 return it.value();
1084}
1085
1093{
1094 detach();
1096}
1097
1102{
1103 if (!d)
1104 return;
1105
1106 auto it = d->combinedImageMap.find(key);
1107 if (it == d->combinedImageMap.end())
1108 return;
1109
1110 detach();
1111 d->combinedImageMap.erase(it);
1112}
1113
1153{
1154 if (!d)
1155 return {};
1156
1158 if (it == d->nativeShaderInfoMap.cend())
1159 return {};
1160
1161 return it.value();
1162}
1163
1170{
1171 detach();
1173}
1174
1179{
1180 if (!d)
1181 return;
1182
1183 auto it = d->nativeShaderInfoMap.find(key);
1184 if (it == d->nativeShaderInfoMap.end())
1185 return;
1186
1187 detach();
1189}
1190
bool ref() noexcept
bool deref() noexcept
\inmodule QtCore \reentrant
Definition qbuffer.h:16
\inmodule QtCore
Definition qbytearray.h:57
\inmodule QtCore\reentrant
Definition qdatastream.h:30
void setVersion(int)
Sets the version number of the data serialization format to v, a value of the \l Version enum.
\inmodule QtCore
\inmodule QtCore
Definition qlist.h:74
qsizetype size() const noexcept
Definition qlist.h:386
const_iterator cend() const noexcept
Definition qlist.h:614
void append(parameter_type t)
Definition qlist.h:441
const_iterator cbegin() const noexcept
Definition qlist.h:613
iterator insert(const Key &key, const T &value)
Definition qmap.h:687
T value(const Key &key, const T &defaultValue=T()) const
Definition qmap.h:356
iterator erase(const_iterator it)
Definition qmap.h:618
const_iterator cend() const
Definition qmap.h:604
const_iterator cbegin() const
Definition qmap.h:600
const_iterator constFind(const Key &key) const
Definition qmap.h:654
QList< Key > keys() const
Definition qmap.h:382
iterator find(const Key &key)
Definition qmap.h:640
bool isEmpty() const
Definition qmap.h:268
iterator end()
Definition qmap.h:601
size_type size() const
Definition qmap.h:266
qsizetype size() const
Definition qset.h:50
const_iterator cend() const noexcept
Definition qset.h:142
const_iterator cbegin() const noexcept
Definition qset.h:138
\inmodule QtGui
Definition qshader.h:60
bool operator==(const QShaderCode &lhs, const QShaderCode &rhs) noexcept
Returns true if the two QShaderCode objects lhs and rhs are equal.
Definition qshader.cpp:894
QShaderCode()=default
void serialize(QDataStream *stream, int version) const
Serializes this QShaderDescription to stream.
static QShaderDescription deserialize(QDataStream *stream, int version)
\inmodule QtGui
Definition qshader.h:174
size_t qHash(const QShaderKey &k, size_t seed) noexcept
Returns the hash value for k, using seed to seed the calculation.
Definition qshader.cpp:880
void setSource(QShader::Source s)
Sets the shader type s.
Definition qshader.h:182
void setSourceVariant(QShader::Variant svar)
Sets the type of variant to use to svar.
Definition qshader.h:188
void setSourceVersion(const QShaderVersion &sver)
Sets the shading language version sver.
Definition qshader.h:185
QShader::Source source() const
Definition qshader.h:181
QShaderVersion sourceVersion() const
Definition qshader.h:184
QShader::Variant sourceVariant() const
Definition qshader.h:187
bool operator==(const QShaderKey &lhs, const QShaderKey &rhs) noexcept
Returns true if the two QShaderKey objects lhs and rhs are equal.
Definition qshader.cpp:836
bool operator<(const QShaderKey &lhs, const QShaderKey &rhs) noexcept
Definition qshader.cpp:849
QShaderKey()=default
\inmodule QtGui
Definition qshader.h:32
bool operator<(const QShaderVersion &lhs, const QShaderVersion &rhs) noexcept
Definition qshader.cpp:811
void setVersion(int v)
Sets the shading language version to v.
Definition qshader.h:43
void setFlags(Flags f)
Sets the flags f.
Definition qshader.h:46
Flags flags() const
Definition qshader.h:45
QShaderVersion()=default
int version() const
Definition qshader.h:42
bool operator==(const QShaderVersion &lhs, const QShaderVersion &rhs) noexcept
Returns true if the two QShaderVersion objects lhs and rhs are equal.
Definition qshader.cpp:792
\inmodule QtGui
Definition qshader.h:81
SerializedFormatVersion
Describes the desired output format when serializing the QShader.
Definition qshader.h:111
SeparateToCombinedImageSamplerMappingList separateToCombinedImageSamplerMappingList(const QShaderKey &key) const
\variable QShader::SeparateToCombinedImageSamplerMapping::combinedSamplerName
Definition qshader.cpp:1074
void removeResourceBindingMap(const QShaderKey &key)
Removes the native resource binding map for key.
Definition qshader.cpp:1020
void setNativeShaderInfo(const QShaderKey &key, const NativeShaderInfo &info)
Stores the given native shader info associated with key.
Definition qshader.cpp:1169
QShaderCode shader(const QShaderKey &key) const
Definition qshader.cpp:365
QList< QShaderKey > availableShaders() const
Definition qshader.cpp:357
void setSeparateToCombinedImageSamplerMappingList(const QShaderKey &key, const SeparateToCombinedImageSamplerMappingList &list)
Stores the given combined image sampler mapping list associated with key.
Definition qshader.cpp:1091
NativeResourceBindingMap nativeResourceBindingMap(const QShaderKey &key) const
Definition qshader.cpp:994
QShader & operator=(const QShader &other)
Assigns other to this object.
Definition qshader.cpp:284
static QShader fromSerialized(const QByteArray &data)
Creates a new QShader instance from the given data.
Definition qshader.cpp:510
Stage stage() const
Definition qshader.cpp:321
friend struct QShaderPrivate
Definition qshader.h:165
void removeShader(const QShaderKey &key)
Removes the source or binary shader code for a given key.
Definition qshader.cpp:386
NativeShaderInfo nativeShaderInfo(const QShaderKey &key) const
\variable QShader::NativeShaderInfo::flags
Definition qshader.cpp:1152
void removeNativeShaderInfo(const QShaderKey &key)
Removes the native shader information for key.
Definition qshader.cpp:1178
QShader()
Constructs a new, empty (and thus invalid) QShader instance.
Definition qshader.cpp:255
Variant
Describes what kind of shader code an entry contains.
Definition qshader.h:103
void setShader(const QShaderKey &key, const QShaderCode &shader)
Stores the source or binary shader code for a given shader version specified by key.
Definition qshader.cpp:373
void setResourceBindingMap(const QShaderKey &key, const NativeResourceBindingMap &map)
Stores the given native resource binding map associated with key.
Definition qshader.cpp:1011
void removeSeparateToCombinedImageSamplerMappingList(const QShaderKey &key)
Removes the combined image sampler mapping list for key.
Definition qshader.cpp:1101
Source
Describes what kind of shader code an entry contains.
Definition qshader.h:92
void detach()
Definition qshader.cpp:263
~QShader()
Destructor.
Definition qshader.cpp:304
QShaderDescription description() const
Definition qshader.cpp:340
void setDescription(const QShaderDescription &desc)
Sets the reflection metadata to desc.
Definition qshader.cpp:348
Stage
Describes the stage of the graphics pipeline the shader is suitable for.
Definition qshader.h:83
@ VertexStage
Definition qshader.h:84
bool isValid() const
Definition qshader.cpp:313
void setStage(Stage stage)
Sets the pipeline stage.
Definition qshader.cpp:329
QByteArray serialized(SerializedFormatVersion version=SerializedFormatVersion::Latest) const
Definition qshader.cpp:420
QHash< int, QWidget * > hash
[35multi]
QMap< QString, QString > map
[6]
QSet< QString >::iterator it
Combined button and popup list for selecting options.
QT_WARNING_POP void qAtomicAssign(T *&d, T *x)
This is a helper for the assignment operators of implicitly shared classes.
Definition qatomic.h:180
void qAtomicDetach(T *&d)
This is a helper for the detach method of implicitly shared classes.
Definition qatomic.h:199
QByteArray qCompress(const uchar *data, qsizetype nbytes, int compressionLevel)
Q_CORE_EXPORT QByteArray qUncompress(const uchar *data, qsizetype nbytes)
size_t qHash(const QFileSystemWatcherPathKey &key, size_t seed=0)
Flags
constexpr QtPrivate::QHashMultiReturnType< T... > qHashMulti(size_t seed, const T &... args) noexcept(std::conjunction_v< QtPrivate::QNothrowHashable< T >... >)
#define qWarning
Definition qlogging.h:162
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLuint64 key
GLenum GLenum GLsizei count
GLfloat GLfloat f
GLenum GLuint GLenum GLsizei const GLchar * buf
GLbitfield flags
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint entry
GLuint shader
Definition qopenglext.h:665
GLdouble s
[6]
Definition qopenglext.h:235
static Q_CONSTINIT QBasicAtomicInteger< unsigned > seed
Definition qrandom.cpp:196
bool operator==(const QRandomGenerator &rng1, const QRandomGenerator &rng2)
Definition qrandom.cpp:1219
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
static void readShaderKey(QDataStream *ds, QShaderKey *k)
Definition qshader.cpp:487
QDebug operator<<(QDebug dbg, const QShader &bs)
Definition qshader.cpp:919
static void writeShaderKey(QDataStream *ds, const QShaderKey &k)
Definition qshader.cpp:399
@ desc
QList< int > list
[14]
QFileInfo info(fileName)
[8]
QObject::connect nullptr
QSharedPointer< T > other(t)
[5]
QMap< QShaderKey, QShader::SeparateToCombinedImageSamplerMappingList > combinedImageMap
Definition qshader_p.h:85
static const int QSB_VERSION_WITH_CBOR
Definition qshader_p.h:33
static const int QSB_VERSION_WITH_BINARY_JSON
Definition qshader_p.h:34
QShader::Stage stage
Definition qshader_p.h:80
QMap< QShaderKey, QShader::NativeResourceBindingMap > bindings
Definition qshader_p.h:84
static const int QSB_VERSION_WITHOUT_INPUT_OUTPUT_INTERFACE_BLOCKS
Definition qshader_p.h:28
static const int QSB_VERSION_WITHOUT_BINDINGS
Definition qshader_p.h:35
static const int QSB_VERSION_WITHOUT_VAR_ARRAYDIMS
Definition qshader_p.h:32
QAtomicInt ref
Definition qshader_p.h:78
static const int QSB_VERSION_WITHOUT_EXTENDED_STORAGE_BUFFER_INFO
Definition qshader_p.h:29
static int qtQsbVersion(QShader::SerializedFormatVersion qtVersion)
Definition qshader_p.h:67
QMap< QShaderKey, QShaderCode > shaders
Definition qshader_p.h:83
QMap< QShaderKey, QShader::NativeShaderInfo > nativeShaderInfoMap
Definition qshader_p.h:86
static const int QSB_VERSION_WITHOUT_NATIVE_SHADER_INFO
Definition qshader_p.h:30
static QShaderPrivate * get(QShader *s)
Definition qshader_p.h:65
static const int QSB_VERSION_WITHOUT_SEPARATE_IMAGES_AND_SAMPLERS
Definition qshader_p.h:31
QShaderDescription desc
Definition qshader_p.h:81
static const int QSB_VERSION
Definition qshader_p.h:27
\inmodule QtGui
Definition qshader.h:155