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
qshaderdescription.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// Qt-Security score:significant reason:default
4
6#include "qshader_p.h"
7#include <QDebug>
8#include <QDataStream>
9#include <QJsonObject>
10#include <QJsonArray>
11
13
14/*!
15 \class QShaderDescription
16 \ingroup painting-3D
17 \inmodule QtGui
18 \since 6.6
19
20 \brief Describes the interface of a shader.
21
22 \warning The QRhi family of classes in the Qt Gui module, including QShader
23 and QShaderDescription, offer limited compatibility guarantees. There are
24 no source or binary compatibility guarantees for these classes, meaning the
25 API is only guaranteed to work with the Qt version the application was
26 developed against. Source incompatible changes are however aimed to be kept
27 at a minimum and will only be made in minor releases (6.7, 6.8, and so on).
28 To use these classes in an application, link to
29 \c{Qt::GuiPrivate} (if using CMake), and include the headers with the \c
30 rhi prefix, for example \c{#include <rhi/qshaderdescription.h>}.
31
32 A shader typically has a set of inputs and outputs. A vertex shader for
33 example has a number of input variables and may use one or more uniform
34 buffers to access data (e.g. a modelview matrix) provided by the
35 application. The shader for the fragment stage receives data from the
36 vertex stage (in a simple setup) and may also rely on data from uniform
37 buffers, images, and samplers.
38
39 When it comes to vertex inputs and the layout of the uniform buffers (what
40 are the names of the members? what is there size, offset, and so on),
41 applications and frameworks may need to discover this dynamically at run
42 time. This is typical when the shader is not built-in but provided by an
43 external entity, like the user.
44
45 Modern and lean graphics APIs may no longer provide a way to query shader
46 reflection information at run time. Therefore, such data is now
47 automatically generated by QShaderBaker and is provided as a
48 QShaderDescription object for each and every QShader.
49
50 \section2 Example
51
52 Take the following vertex shader:
53
54 \badcode
55 #version 440
56
57 layout(location = 0) in vec4 position;
58 layout(location = 1) in vec3 color;
59 layout(location = 0) out vec3 v_color;
60
61 layout(std140, binding = 0) uniform buf {
62 mat4 mvp;
63 float opacity;
64 } ubuf;
65
66 void main()
67 {
68 v_color = color;
69 gl_Position = ubuf.mvp * position;
70 }
71 \endcode
72
73 This shader has two inputs: \c position at location 0 with a type of \c
74 vec4, and \c color at location 1 with a type of \c vec3. It has one output:
75 \c v_color, although this is typically not interesting for applications.
76 What is more important, there is a uniform block at binding 0 with a size
77 of 68 bytes and two members, a 4x4 matrix named \c mvp at offset 0, and a
78 float \c opacity at offset 64.
79
80 All this is described by a QShaderDescription object. QShaderDescription can
81 be serialized to JSON and to a binary format via QDataStream, and can be
82 deserialized from this binary format. In practice this is rarely needed
83 since QShader takes care of the associated QShaderDescription automatically,
84 but if the QShaderDescription of the above shader would be written out as
85 JSON (like it is done by the \c qsb tool's \c{-d} option), it would look
86 like the following:
87
88 \badcode
89 {
90 "inputs": [
91 {
92 "location": 1,
93 "name": "color",
94 "type": "vec3"
95 },
96 {
97 "location": 0,
98 "name": "position",
99 "type": "vec4"
100 }
101 ],
102 "outputs": [
103 {
104 "location": 0,
105 "name": "v_color",
106 "type": "vec3"
107 }
108 ],
109 "uniformBlocks": [
110 {
111 "binding": 0,
112 "blockName": "buf",
113 "members": [
114 {
115 "matrixStride": 16,
116 "name": "mvp",
117 "offset": 0,
118 "size": 64,
119 "type": "mat4"
120 },
121 {
122 "name": "opacity",
123 "offset": 64,
124 "size": 4,
125 "type": "float"
126 }
127 ],
128 "set": 0,
129 "size": 68,
130 "structName": "ubuf"
131 }
132 ]
133 }
134 \endcode
135
136 The C++ API allows accessing a data structure like the above. For
137 simplicity the inner structs only contain public data members, also
138 considering that their layout is unlikely to change in the future.
139
140 \sa QShaderBaker, QShader
141 */
142
143/*!
144 \enum QShaderDescription::VariableType
145 Represents the type of a variable or block member.
146
147 \value Unknown
148 \value Float
149 \value Vec2
150 \value Vec3
151 \value Vec4
152 \value Mat2
153 \value Mat2x3
154 \value Mat2x4
155 \value Mat3
156 \value Mat3x2
157 \value Mat3x4
158 \value Mat4
159 \value Mat4x2
160 \value Mat4x3
161 \value Int
162 \value Int2
163 \value Int3
164 \value Int4
165 \value Uint
166 \value Uint2
167 \value Uint3
168 \value Uint4
169 \value Bool
170 \value Bool2
171 \value Bool3
172 \value Bool4
173 \value Double
174 \value Double2
175 \value Double3
176 \value Double4
177 \value DMat2
178 \value DMat2x3
179 \value DMat2x4
180 \value DMat3
181 \value DMat3x2
182 \value DMat3x4
183 \value DMat4
184 \value DMat4x2
185 \value DMat4x3
186 \value Sampler1D
187 \value Sampler2D
188 \value Sampler2DMS
189 \value Sampler3D
190 \value SamplerCube
191 \value Sampler1DArray
192 \value Sampler2DArray
193 \value Sampler2DMSArray
194 \value Sampler3DArray
195 \value SamplerCubeArray
196 \value SamplerRect
197 \value SamplerBuffer
198 \value SamplerExternalOES
199 \value Sampler For separate samplers.
200 \value Image1D
201 \value Image2D
202 \value Image2DMS
203 \value Image3D
204 \value ImageCube
205 \value Image1DArray
206 \value Image2DArray
207 \value Image2DMSArray
208 \value Image3DArray
209 \value ImageCubeArray
210 \value ImageRect
211 \value ImageBuffer
212 \value Struct
213 \value Half
214 \value Half2
215 \value Half3
216 \value Half4
217 */
218
219/*!
220 \enum QShaderDescription::ImageFormat
221 Image format.
222
223 \value ImageFormatUnknown
224 \value ImageFormatRgba32f
225 \value ImageFormatRgba16f
226 \value ImageFormatR32f
227 \value ImageFormatRgba8
228 \value ImageFormatRgba8Snorm
229 \value ImageFormatRg32f
230 \value ImageFormatRg16f
231 \value ImageFormatR11fG11fB10f
232 \value ImageFormatR16f
233 \value ImageFormatRgba16
234 \value ImageFormatRgb10A2
235 \value ImageFormatRg16
236 \value ImageFormatRg8
237 \value ImageFormatR16
238 \value ImageFormatR8
239 \value ImageFormatRgba16Snorm
240 \value ImageFormatRg16Snorm
241 \value ImageFormatRg8Snorm
242 \value ImageFormatR16Snorm
243 \value ImageFormatR8Snorm
244 \value ImageFormatRgba32i
245 \value ImageFormatRgba16i
246 \value ImageFormatRgba8i
247 \value ImageFormatR32i
248 \value ImageFormatRg32i
249 \value ImageFormatRg16i
250 \value ImageFormatRg8i
251 \value ImageFormatR16i
252 \value ImageFormatR8i
253 \value ImageFormatRgba32ui
254 \value ImageFormatRgba16ui
255 \value ImageFormatRgba8ui
256 \value ImageFormatR32ui
257 \value ImageFormatRgb10a2ui
258 \value ImageFormatRg32ui
259 \value ImageFormatRg16ui
260 \value ImageFormatRg8ui
261 \value ImageFormatR16ui
262 \value ImageFormatR8ui
263 */
264
265/*!
266 \enum QShaderDescription::ImageFlag
267 Image flags.
268
269 \value ReadOnlyImage
270 \value WriteOnlyImage
271 */
272
273/*!
274 \enum QShaderDescription::QualifierFlag
275 Qualifier flags.
276
277 \value QualifierReadOnly
278 \value QualifierWriteOnly
279 \value QualifierCoherent
280 \value QualifierVolatile
281 \value QualifierRestrict
282 */
283
284/*!
285 \struct QShaderDescription::InOutVariable
286 \inmodule QtGui
287 \since 6.6
288
289 \brief Describes an input or output variable in the shader.
290
291 \note This is a RHI API with limited compatibility guarantees, see \l QShaderDescription
292 for details.
293 */
294
295/*!
296 \variable QShaderDescription::InOutVariable::name
297 */
298
299/*!
300 \variable QShaderDescription::InOutVariable::type
301 */
302
303/*!
304 \variable QShaderDescription::InOutVariable::location
305 */
306
307/*!
308 \variable QShaderDescription::InOutVariable::binding
309 */
310
311/*!
312 \variable QShaderDescription::InOutVariable::descriptorSet
313 */
314
315/*!
316 \variable QShaderDescription::InOutVariable::imageFormat
317 */
318
319/*!
320 \variable QShaderDescription::InOutVariable::imageFlags
321 */
322
323/*!
324 \variable QShaderDescription::InOutVariable::arrayDims
325 */
326
327/*!
328 \variable QShaderDescription::InOutVariable::perPatch
329 */
330
331/*!
332 \variable QShaderDescription::InOutVariable::structMembers
333 */
334
335/*!
336 \struct QShaderDescription::BlockVariable
337 \inmodule QtGui
338 \since 6.6
339
340 \brief Describes a member of a uniform or push constant block.
341
342 \note This is a RHI API with limited compatibility guarantees, see \l QShaderDescription
343 for details.
344 */
345
346/*!
347 \variable QShaderDescription::BlockVariable::name
348 */
349
350/*!
351 \variable QShaderDescription::BlockVariable::type
352 */
353
354/*!
355 \variable QShaderDescription::BlockVariable::offset
356 */
357
358/*!
359 \variable QShaderDescription::BlockVariable::size
360 */
361
362/*!
363 \variable QShaderDescription::BlockVariable::arrayDims
364 */
365
366/*!
367 \variable QShaderDescription::BlockVariable::arrayStride
368 */
369
370/*!
371 \variable QShaderDescription::BlockVariable::matrixStride
372 */
373
374/*!
375 \variable QShaderDescription::BlockVariable::matrixIsRowMajor
376 */
377
378/*!
379 \variable QShaderDescription::BlockVariable::structMembers
380 */
381
382/*!
383 \struct QShaderDescription::UniformBlock
384 \inmodule QtGui
385 \since 6.6
386
387 \brief Describes a uniform block.
388
389 \note When translating to shading languages without uniform block support
390 (like GLSL 120 or GLSL/ES 100), uniform blocks are replaced with ordinary
391 uniforms in a struct. The name of the struct, and so the prefix for the
392 uniforms generated from the block members, is given by structName.
393
394 \note This is a RHI API with limited compatibility guarantees, see \l QShaderDescription
395 for details.
396 */
397
398/*!
399 \variable QShaderDescription::UniformBlock::blockName
400 */
401
402/*!
403 \variable QShaderDescription::UniformBlock::structName
404 */
405
406/*!
407 \variable QShaderDescription::UniformBlock::size
408 */
409
410/*!
411 \variable QShaderDescription::UniformBlock::binding
412 */
413
414/*!
415 \variable QShaderDescription::UniformBlock::descriptorSet
416 */
417
418/*!
419 \variable QShaderDescription::UniformBlock::members
420 */
421
422/*!
423 \struct QShaderDescription::PushConstantBlock
424 \inmodule QtGui
425 \since 6.6
426
427 \brief Describes a push constant block.
428
429 \note This is a RHI API with limited compatibility guarantees, see \l QShaderDescription
430 for details.
431 */
432
433/*!
434 \variable QShaderDescription::PushConstantBlock::name
435 */
436
437/*!
438 \variable QShaderDescription::PushConstantBlock::size
439 */
440
441/*!
442 \variable QShaderDescription::PushConstantBlock::members
443 */
444
445/*!
446 \struct QShaderDescription::StorageBlock
447 \inmodule QtGui
448 \since 6.6
449
450 \brief Describes a shader storage block.
451
452 \note This is a RHI API with limited compatibility guarantees, see \l QShaderDescription
453 for details.
454 */
455
456/*!
457 \variable QShaderDescription::StorageBlock::blockName
458 */
459
460/*!
461 \variable QShaderDescription::StorageBlock::instanceName
462 */
463
464/*!
465 \variable QShaderDescription::StorageBlock::knownSize
466 */
467
468/*!
469 \variable QShaderDescription::StorageBlock::binding
470 */
471
472/*!
473 \variable QShaderDescription::StorageBlock::descriptorSet
474 */
475
476/*!
477 \variable QShaderDescription::StorageBlock::members
478 */
479
480/*!
481 \variable QShaderDescription::StorageBlock::runtimeArrayStride
482 */
483
484/*!
485 \variable QShaderDescription::StorageBlock::qualifierFlags
486 */
487
488/*!
489 \struct QShaderDescription::BuiltinVariable
490 \inmodule QtGui
491 \since 6.6
492
493 \brief Describes a built-in variable.
494
495 \note This is a RHI API with limited compatibility guarantees, see \l QShaderDescription
496 for details.
497 */
498
499/*!
500 \variable QShaderDescription::BuiltinVariable::type
501 */
502
503/*!
504 \variable QShaderDescription::BuiltinVariable::varType
505 */
506
507/*!
508 \variable QShaderDescription::BuiltinVariable::arrayDims
509 */
510
511/*!
512 \enum QShaderDescription::BuiltinType
513 Built-in variable type.
514
515 \value PositionBuiltin
516 \value PointSizeBuiltin
517 \value ClipDistanceBuiltin
518 \value CullDistanceBuiltin
519 \value VertexIdBuiltin
520 \value InstanceIdBuiltin
521 \value PrimitiveIdBuiltin
522 \value InvocationIdBuiltin
523 \value LayerBuiltin
524 \value ViewportIndexBuiltin
525 \value TessLevelOuterBuiltin
526 \value TessLevelInnerBuiltin
527 \value TessCoordBuiltin
528 \value PatchVerticesBuiltin
529 \value FragCoordBuiltin
530 \value PointCoordBuiltin
531 \value FrontFacingBuiltin
532 \value SampleIdBuiltin
533 \value SamplePositionBuiltin
534 \value SampleMaskBuiltin
535 \value FragDepthBuiltin
536 \value NumWorkGroupsBuiltin
537 \value WorkgroupSizeBuiltin
538 \value WorkgroupIdBuiltin
539 \value LocalInvocationIdBuiltin
540 \value GlobalInvocationIdBuiltin
541 \value LocalInvocationIndexBuiltin
542 \value VertexIndexBuiltin
543 \value InstanceIndexBuiltin
544 \value ViewIndexBuiltin
545 */
546
547/*!
548 Constructs a new, empty QShaderDescription.
549
550 \note Being empty implies that isValid() returns \c false for the
551 newly constructed instance.
552 */
553QShaderDescription::QShaderDescription()
554 : d(new QShaderDescriptionPrivate)
555{
556}
557
558/*!
559 \internal
560 */
561void QShaderDescription::detach()
562{
563 qAtomicDetach(d);
564}
565
566/*!
567 Constructs a copy of \a other.
568 */
569QShaderDescription::QShaderDescription(const QShaderDescription &other)
570 : d(other.d)
571{
572 d->ref.ref();
573}
574
575/*!
576 Assigns \a other to this object.
577 */
578QShaderDescription &QShaderDescription::operator=(const QShaderDescription &other)
579{
580 qAtomicAssign(d, other.d);
581 return *this;
582}
583
584/*!
585 Destructor.
586 */
587QShaderDescription::~QShaderDescription()
588{
589 if (!d->ref.deref())
590 delete d;
591}
592
593/*!
594 \return true if the QShaderDescription contains at least one entry in one of
595 the variable and block lists.
596 */
597bool QShaderDescription::isValid() const
598{
599 return !d->inVars.isEmpty() || !d->outVars.isEmpty()
600 || !d->uniformBlocks.isEmpty() || !d->pushConstantBlocks.isEmpty() || !d->storageBlocks.isEmpty()
601 || !d->combinedImageSamplers.isEmpty() || !d->storageImages.isEmpty()
602 || !d->separateImages.isEmpty() || !d->separateSamplers.isEmpty()
603 || !d->inBuiltins.isEmpty() || !d->outBuiltins.isEmpty();
604}
605
606/*!
607 \return a serialized JSON text version of the data.
608
609 \note There is no deserialization method provided for JSON text.
610
611 \sa serialize()
612 */
613QByteArray QShaderDescription::toJson() const
614{
615 return d->makeDoc().toJson();
616}
617
618/*!
619 Serializes this QShaderDescription to \a stream. \a version specifies
620 the qsb version.
621
622 \sa deserialize(), toJson()
623 */
624void QShaderDescription::serialize(QDataStream *stream, int version) const
625{
626 d->writeToStream(stream, version);
627}
628
629/*!
630 \return a new QShaderDescription loaded from \a stream. \a version specifies
631 the qsb version.
632
633 \sa serialize()
634 */
635QShaderDescription QShaderDescription::deserialize(QDataStream *stream, int version)
636{
637 QShaderDescription desc;
638 QShaderDescriptionPrivate::get(&desc)->loadFromStream(stream, version);
639 return desc;
640}
641
642/*!
643 \return the list of input variables. This includes vertex inputs (sometimes
644 called attributes) for the vertex stage, and inputs for other stages
645 (sometimes called varyings).
646 */
647QList<QShaderDescription::InOutVariable> QShaderDescription::inputVariables() const
648{
649 return d->inVars;
650}
651
652/*!
653 \return the list of output variables.
654 */
655QList<QShaderDescription::InOutVariable> QShaderDescription::outputVariables() const
656{
657 return d->outVars;
658}
659
660/*!
661 \return the list of uniform blocks.
662 */
663QList<QShaderDescription::UniformBlock> QShaderDescription::uniformBlocks() const
664{
665 return d->uniformBlocks;
666}
667
668/*!
669 \return the list of push constant blocks.
670
671 \note Avoid relying on push constant blocks for shaders that are to be used
672 in combination with the Qt Rendering Hardware Interface since that
673 currently has no support for them.
674 */
675QList<QShaderDescription::PushConstantBlock> QShaderDescription::pushConstantBlocks() const
676{
677 return d->pushConstantBlocks;
678}
679
680/*!
681 \return the list of shader storage blocks.
682
683 For example, with GLSL/Vulkan shaders as source, the declaration
684
685 \badcode
686 struct Stuff {
687 vec2 a;
688 vec2 b;
689 };
690 layout(std140, binding = 0) buffer StuffSsbo {
691 vec4 whatever;
692 Stuff stuff[];
693 } buf;
694 \endcode
695
696 generates the following: (shown as textual JSON here)
697
698 \badcode
699 "storageBlocks": [ {
700 "binding": 0,
701 "blockName": "StuffSsbo",
702 "instanceName": "buf",
703 "knownSize": 16,
704 "runtimeArrayStride": 16
705 "members": [
706 {
707 "name": "whatever",
708 "offset": 0,
709 "size": 16,
710 "type": "vec4"
711 },
712 {
713 "arrayDims": [
714 0
715 ],
716 "name": "stuff",
717 "offset": 16,
718 "size": 0,
719 "structMembers": [
720 {
721 "name": "a",
722 "offset": 0,
723 "size": 8,
724 "type": "vec2"
725 },
726 {
727 "name": "b",
728 "offset": 8,
729 "size": 8,
730 "type": "vec2"
731 }
732 ],
733 "type": "struct"
734 }
735 ],
736 "set": 0
737 } ]
738 \endcode
739
740 \note The size of the last member in the storage block is undefined. This shows
741 up as \c size 0 and an array dimension of \c{[0]}. The storage block's \c knownSize
742 excludes the size of the last member since that will only be known at run time. The
743 stride in bytes between array items for a last member with undefined array size is
744 \c runtimeArrayStride. This value is determined according to the specified buffer
745 memory layout standard (std140, std430) rules.
746
747 \note SSBOs are not available with some graphics APIs, such as, OpenGL 2.x or
748 OpenGL ES older than 3.1.
749 */
750QList<QShaderDescription::StorageBlock> QShaderDescription::storageBlocks() const
751{
752 return d->storageBlocks;
753}
754
755/*!
756 \return the list of combined image samplers
757
758 With GLSL/Vulkan shaders as source a \c{layout(binding = 1) uniform sampler2D tex;}
759 uniform generates the following: (shown as textual JSON here)
760
761 \badcode
762 "combinedImageSamplers": [
763 {
764 "binding": 1,
765 "name": "tex",
766 "set": 0,
767 "type": "sampler2D"
768 }
769 ]
770 \endcode
771
772 This does not mean that other language versions of the shader must also use
773 a combined image sampler, especially considering that the concept may not
774 exist everywhere. For instance, a HLSL version will likely just use a
775 Texture2D and SamplerState object with registers t1 and s1, respectively.
776 */
777QList<QShaderDescription::InOutVariable> QShaderDescription::combinedImageSamplers() const
778{
779 return d->combinedImageSamplers;
780}
781
782QList<QShaderDescription::InOutVariable> QShaderDescription::separateImages() const
783{
784 return d->separateImages;
785}
786
787QList<QShaderDescription::InOutVariable> QShaderDescription::separateSamplers() const
788{
789 return d->separateSamplers;
790}
791
792/*!
793 \return the list of image variables.
794
795 These will likely occur in compute shaders. For example,
796 \c{layout (binding = 0, rgba8) uniform readonly image2D inputImage;}
797 generates the following: (shown as textual JSON here)
798
799 \badcode
800 "storageImages": [
801 {
802 "binding": 0,
803 "imageFormat": "rgba8",
804 "name": "inputImage",
805 "set": 0,
806 "type": "image2D"
807 }
808 ]
809 \endcode
810
811 \note Separate image objects are not compatible with some graphics APIs,
812 such as, OpenGL 2.x or OpenGL ES older than 3.1.
813 */
814QList<QShaderDescription::InOutVariable> QShaderDescription::storageImages() const
815{
816 return d->storageImages;
817}
818
819/*!
820 \return the list of active builtins used as input. For example, a
821 tessellation evaluation shader reading the value of gl_TessCoord and
822 gl_Position will have TessCoordBuiltin and PositionBuiltin listed here.
823 */
824QVector<QShaderDescription::BuiltinVariable> QShaderDescription::inputBuiltinVariables() const
825{
826 return d->inBuiltins;
827}
828
829/*!
830 \return the list of active built-in variables used as input. For example, a
831 vertex shader will very often have PositionBuiltin as an output built-in.
832 */
833QVector<QShaderDescription::BuiltinVariable> QShaderDescription::outputBuiltinVariables() const
834{
835 return d->outBuiltins;
836}
837
838/*!
839 \return the local size of a compute shader.
840
841 For example, for a compute shader with the following declaration the
842 function returns { 256, 16, 1}.
843
844 \badcode
845 layout(local_size_x = 256, local_size_y = 16, local_size_z = 1) in;
846 \endcode
847 */
848std::array<uint, 3> QShaderDescription::computeShaderLocalSize() const
849{
850 return d->localSize;
851}
852
853/*!
854 \return the number of output vertices.
855
856 For example, for a tessellation control shader with the following
857 declaration the function returns 3.
858
859 \badcode
860 layout(vertices = 3) out;
861 \endcode
862 */
863uint QShaderDescription::tessellationOutputVertexCount() const
864{
865 return d->tessOutVertCount;
866}
867
868/*!
869 \enum QShaderDescription::TessellationMode
870
871 \value UnknownTessellationMode
872 \value TrianglesTessellationMode
873 \value QuadTessellationMode
874 \value IsolineTessellationMode
875 */
876
877/*!
878 \return the tessellation execution mode for a tessellation control or
879 evaluation shader.
880
881 When not set, the returned value is UnknownTessellationMode.
882
883 For example, for a tessellation evaluation shader with the following
884 declaration the function returns TrianglesTessellationMode.
885
886 \badcode
887 layout(triangles) in;
888 \endcode
889 */
890QShaderDescription::TessellationMode QShaderDescription::tessellationMode() const
891{
892 return d->tessMode;
893}
894
895/*!
896 \enum QShaderDescription::TessellationWindingOrder
897
898 \value UnknownTessellationWindingOrder
899 \value CwTessellationWindingOrder
900 \value CcwTessellationWindingOrder
901 */
902
903/*!
904 \return the tessellation winding order for a tessellation control or
905 evaluation shader.
906
907 When not set, the returned value is UnknownTessellationWindingOrder.
908
909 For example, for a tessellation evaluation shader with the following
910 declaration the function returns CcwTessellationWindingOrder.
911
912 \badcode
913 layout(triangles, fractional_odd_spacing, ccw) in;
914 \endcode
915 */
916QShaderDescription::TessellationWindingOrder QShaderDescription::tessellationWindingOrder() const
917{
918 return d->tessWind;
919}
920
921/*!
922 \enum QShaderDescription::TessellationPartitioning
923
924 \value UnknownTessellationPartitioning
925 \value EqualTessellationPartitioning
926 \value FractionalEvenTessellationPartitioning
927 \value FractionalOddTessellationPartitioning
928 */
929
930/*!
931 \return the tessellation partitioning mode for a tessellation control or
932 evaluation shader.
933
934 When not set, the returned value is UnknownTessellationPartitioning.
935
936 For example, for a tessellation evaluation shader with the following
937 declaration the function returns FractionalOddTessellationPartitioning.
938
939 \badcode
940 layout(triangles, fractional_odd_spacing, ccw) in;
941 \endcode
942 */
943QShaderDescription::TessellationPartitioning QShaderDescription::tessellationPartitioning() const
944{
945 return d->tessPart;
946}
947
948static const struct TypeTab {
949 const char k[20];
951} typeTab[] = {
952 { "float", QShaderDescription::Float },
953 { "vec2", QShaderDescription::Vec2 },
954 { "vec3", QShaderDescription::Vec3 },
955 { "vec4", QShaderDescription::Vec4 },
956 { "mat2", QShaderDescription::Mat2 },
957 { "mat3", QShaderDescription::Mat3 },
958 { "mat4", QShaderDescription::Mat4 },
959
960 { "struct", QShaderDescription::Struct },
961
962 { "sampler1D", QShaderDescription::Sampler1D },
963 { "sampler2D", QShaderDescription::Sampler2D },
964 { "sampler2DMS", QShaderDescription::Sampler2DMS },
965 { "sampler3D", QShaderDescription::Sampler3D },
966 { "samplerCube", QShaderDescription::SamplerCube },
967 { "sampler1DArray", QShaderDescription::Sampler1DArray },
968 { "sampler2DArray", QShaderDescription::Sampler2DArray },
969 { "sampler2DMSArray", QShaderDescription::Sampler2DMSArray },
970 { "sampler3DArray", QShaderDescription::Sampler3DArray },
971 { "samplerCubeArray", QShaderDescription::SamplerCubeArray },
972 { "samplerRect", QShaderDescription::SamplerRect },
973 { "samplerBuffer", QShaderDescription::SamplerBuffer },
974 { "samplerExternalOES", QShaderDescription::SamplerExternalOES },
975 { "sampler", QShaderDescription::Sampler },
976
977 { "mat2x3", QShaderDescription::Mat2x3 },
978 { "mat2x4", QShaderDescription::Mat2x4 },
979 { "mat3x2", QShaderDescription::Mat3x2 },
980 { "mat3x4", QShaderDescription::Mat3x4 },
981 { "mat4x2", QShaderDescription::Mat4x2 },
982 { "mat4x3", QShaderDescription::Mat4x3 },
983
984 { "int", QShaderDescription::Int },
985 { "ivec2", QShaderDescription::Int2 },
986 { "ivec3", QShaderDescription::Int3 },
987 { "ivec4", QShaderDescription::Int4 },
988
989 { "uint", QShaderDescription::Uint },
990 { "uvec2", QShaderDescription::Uint2 },
991 { "uvec3", QShaderDescription::Uint3 },
992 { "uvec4", QShaderDescription::Uint4 },
993
994 { "bool", QShaderDescription::Bool },
995 { "bvec2", QShaderDescription::Bool2 },
996 { "bvec3", QShaderDescription::Bool3 },
997 { "bvec4", QShaderDescription::Bool4 },
998
999 { "double", QShaderDescription::Double },
1000 { "dvec2", QShaderDescription::Double2 },
1001 { "dvec3", QShaderDescription::Double3 },
1002 { "dvec4", QShaderDescription::Double4 },
1003 { "dmat2", QShaderDescription::DMat2 },
1004 { "dmat3", QShaderDescription::DMat3 },
1005 { "dmat4", QShaderDescription::DMat4 },
1006 { "dmat2x3", QShaderDescription::DMat2x3 },
1007 { "dmat2x4", QShaderDescription::DMat2x4 },
1008 { "dmat3x2", QShaderDescription::DMat3x2 },
1009 { "dmat3x4", QShaderDescription::DMat3x4 },
1010 { "dmat4x2", QShaderDescription::DMat4x2 },
1011 { "dmat4x3", QShaderDescription::DMat4x3 },
1012
1013 { "image1D", QShaderDescription::Image1D },
1014 { "image2D", QShaderDescription::Image2D },
1015 { "image2DMS", QShaderDescription::Image2DMS },
1016 { "image3D", QShaderDescription::Image3D },
1017 { "imageCube", QShaderDescription::ImageCube },
1018 { "image1DArray", QShaderDescription::Image1DArray },
1019 { "image2DArray", QShaderDescription::Image2DArray },
1020 { "image2DMSArray", QShaderDescription::Image2DMSArray },
1021 { "image3DArray", QShaderDescription::Image3DArray },
1022 { "imageCubeArray", QShaderDescription::ImageCubeArray },
1023 { "imageRect", QShaderDescription::ImageRect },
1024 { "imageBuffer", QShaderDescription::ImageBuffer },
1025
1026 { "half", QShaderDescription::Half },
1027 { "half2", QShaderDescription::Half2 },
1028 { "half3", QShaderDescription::Half3 },
1029 { "half4", QShaderDescription::Half4 } };
1030
1031static QLatin1StringView typeStr(QShaderDescription::VariableType t)
1032{
1033 for (size_t i = 0; i < sizeof(typeTab) / sizeof(TypeTab); ++i) {
1034 if (typeTab[i].v == t)
1035 return QLatin1StringView(typeTab[i].k);
1036 }
1037 return {};
1038}
1039
1040static const struct ImageFormatTab {
1041 const char k[15];
1043} imageFormatTab[] {
1044 { "unknown", QShaderDescription::ImageFormatUnknown },
1045 { "rgba32f", QShaderDescription::ImageFormatRgba32f },
1046 { "rgba16", QShaderDescription::ImageFormatRgba16f },
1047 { "r32f", QShaderDescription::ImageFormatR32f },
1048 { "rgba8", QShaderDescription::ImageFormatRgba8 },
1049 { "rgba8_snorm", QShaderDescription::ImageFormatRgba8Snorm },
1050 { "rg32f", QShaderDescription::ImageFormatRg32f },
1051 { "rg16f", QShaderDescription::ImageFormatRg16f },
1052 { "r11f_g11f_b10f", QShaderDescription::ImageFormatR11fG11fB10f },
1053 { "r16f", QShaderDescription::ImageFormatR16f },
1054 { "rgba16", QShaderDescription::ImageFormatRgba16 },
1055 { "rgb10_a2", QShaderDescription::ImageFormatRgb10A2 },
1056 { "rg16", QShaderDescription::ImageFormatRg16 },
1057 { "rg8", QShaderDescription::ImageFormatRg8 },
1058 { "r16", QShaderDescription::ImageFormatR16 },
1059 { "r8", QShaderDescription::ImageFormatR8 },
1060 { "rgba16_snorm", QShaderDescription::ImageFormatRgba16Snorm },
1061 { "rg16_snorm", QShaderDescription::ImageFormatRg16Snorm },
1062 { "rg8_snorm", QShaderDescription::ImageFormatRg8Snorm },
1063 { "r16_snorm", QShaderDescription::ImageFormatR16Snorm },
1064 { "r8_snorm", QShaderDescription::ImageFormatR8Snorm },
1065 { "rgba32i", QShaderDescription::ImageFormatRgba32i },
1066 { "rgba16i", QShaderDescription::ImageFormatRgba16i },
1067 { "rgba8i", QShaderDescription::ImageFormatRgba8i },
1068 { "r32i", QShaderDescription::ImageFormatR32i },
1069 { "rg32i", QShaderDescription::ImageFormatRg32i },
1070 { "rg16i", QShaderDescription::ImageFormatRg16i },
1071 { "rg8i", QShaderDescription::ImageFormatRg8i },
1072 { "r16i", QShaderDescription::ImageFormatR16i },
1073 { "r8i", QShaderDescription::ImageFormatR8i },
1074 { "rgba32ui", QShaderDescription::ImageFormatRgba32ui },
1075 { "rgba16ui", QShaderDescription::ImageFormatRgba16ui },
1076 { "rgba8ui", QShaderDescription::ImageFormatRgba8ui },
1077 { "r32ui", QShaderDescription::ImageFormatR32ui },
1078 { "rgb10_a2ui", QShaderDescription::ImageFormatRgb10a2ui },
1079 { "rg32ui", QShaderDescription::ImageFormatRg32ui },
1080 { "rg16ui", QShaderDescription::ImageFormatRg16ui },
1081 { "rg8ui", QShaderDescription::ImageFormatRg8ui },
1082 { "r16ui", QShaderDescription::ImageFormatR16ui },
1083 { "r8ui", QShaderDescription::ImageFormatR8ui }
1085
1086static QLatin1StringView imageFormatStr(QShaderDescription::ImageFormat f)
1087{
1088 for (size_t i = 0; i < sizeof(imageFormatTab) / sizeof(ImageFormatTab); ++i) {
1089 if (imageFormatTab[i].v == f)
1090 return QLatin1StringView(imageFormatTab[i].k);
1091 }
1092 return {};
1093}
1094
1095static const struct BuiltinTypeTab {
1096 const char k[21];
1098} builtinTypeTab[] = {
1099 { "Position", QShaderDescription::PositionBuiltin },
1100 { "PointSize", QShaderDescription::PointSizeBuiltin },
1101 { "ClipDistance", QShaderDescription::ClipDistanceBuiltin },
1102 { "CullDistance", QShaderDescription::CullDistanceBuiltin },
1103 { "VertexId", QShaderDescription::VertexIdBuiltin },
1104 { "InstanceId", QShaderDescription::InstanceIdBuiltin },
1105 { "PrimitiveId", QShaderDescription::PrimitiveIdBuiltin },
1106 { "InvocationId", QShaderDescription::InvocationIdBuiltin },
1107 { "Layer", QShaderDescription::LayerBuiltin },
1108 { "ViewportIndex", QShaderDescription::ViewportIndexBuiltin },
1109 { "TessLevelOuter", QShaderDescription::TessLevelOuterBuiltin },
1110 { "TessLevelInner", QShaderDescription::TessLevelInnerBuiltin },
1111 { "TessCoord", QShaderDescription::TessCoordBuiltin },
1112 { "PatchVertices", QShaderDescription::PatchVerticesBuiltin },
1113 { "FragCoord", QShaderDescription::FragCoordBuiltin },
1114 { "PointCoord", QShaderDescription::PointCoordBuiltin },
1115 { "FrontFacing", QShaderDescription::FrontFacingBuiltin },
1116 { "SampleId", QShaderDescription::SampleIdBuiltin },
1117 { "SamplePosition", QShaderDescription::SamplePositionBuiltin },
1118 { "SampleMask", QShaderDescription::SampleMaskBuiltin },
1119 { "FragDepth", QShaderDescription::FragDepthBuiltin },
1120 { "NumWorkGroups", QShaderDescription::NumWorkGroupsBuiltin },
1121 { "WorkgroupSize", QShaderDescription::WorkgroupSizeBuiltin },
1122 { "WorkgroupId", QShaderDescription::WorkgroupIdBuiltin },
1123 { "LocalInvocationId", QShaderDescription::LocalInvocationIdBuiltin },
1124 { "GlobalInvocationId", QShaderDescription::GlobalInvocationIdBuiltin },
1125 { "LocalInvocationIndex", QShaderDescription::LocalInvocationIndexBuiltin },
1126 { "VertexIndex", QShaderDescription::VertexIndexBuiltin },
1127 { "InstanceIndex", QShaderDescription::InstanceIndexBuiltin },
1128 { "ViewIndex", QShaderDescription::ViewIndexBuiltin }
1130
1131static QLatin1StringView builtinTypeStr(QShaderDescription::BuiltinType t)
1132{
1133 for (size_t i = 0; i < sizeof(builtinTypeTab) / sizeof(BuiltinTypeTab); ++i) {
1134 if (builtinTypeTab[i].v == t)
1135 return QLatin1StringView(builtinTypeTab[i].k);
1136 }
1137 return {};
1138}
1139
1140static const struct TessellationModeTab {
1141 const char k[10];
1143} tessellationModeTab[] {
1144 { "unknown", QShaderDescription::UnknownTessellationMode },
1145 { "triangles", QShaderDescription::TrianglesTessellationMode },
1146 { "quad", QShaderDescription::QuadTessellationMode },
1147 { "isoline", QShaderDescription::IsolineTessellationMode }
1149
1150static QLatin1StringView tessModeStr(QShaderDescription::TessellationMode mode)
1151{
1152 for (size_t i = 0; i < sizeof(tessellationModeTab) / sizeof(TessellationModeTab); ++i) {
1153 if (tessellationModeTab[i].v == mode)
1154 return QLatin1StringView(tessellationModeTab[i].k);
1155 }
1156 return {};
1157}
1158
1159static const struct TessellationWindingOrderTab {
1160 const char k[8];
1162} tessellationWindingOrderTab[] {
1163 { "unknown", QShaderDescription::UnknownTessellationWindingOrder },
1164 { "cw", QShaderDescription::CwTessellationWindingOrder },
1165 { "ccw", QShaderDescription::CcwTessellationWindingOrder }
1167
1168static QLatin1StringView tessWindStr(QShaderDescription::TessellationWindingOrder w)
1169{
1170 for (size_t i = 0; i < sizeof(tessellationWindingOrderTab) / sizeof(TessellationWindingOrderTab); ++i) {
1171 if (tessellationWindingOrderTab[i].v == w)
1172 return QLatin1StringView(tessellationWindingOrderTab[i].k);
1173 }
1174 return {};
1175}
1176
1177static const struct TessellationPartitioningTab {
1178 const char k[24];
1180} tessellationPartitioningTab[] {
1181 { "unknown", QShaderDescription::UnknownTessellationPartitioning },
1182 { "equal_spacing", QShaderDescription::EqualTessellationPartitioning },
1183 { "fractional_even_spacing", QShaderDescription::FractionalEvenTessellationPartitioning },
1184 { "fractional_odd_spacing", QShaderDescription::FractionalOddTessellationPartitioning }
1186
1187static QLatin1StringView tessPartStr(QShaderDescription::TessellationPartitioning p)
1188{
1189 for (size_t i = 0; i < sizeof(tessellationPartitioningTab) / sizeof(TessellationPartitioningTab); ++i) {
1190 if (tessellationPartitioningTab[i].v == p)
1191 return QLatin1StringView(tessellationPartitioningTab[i].k);
1192 }
1193 return {};
1194}
1195
1196#ifndef QT_NO_DEBUG_STREAM
1197QDebug operator<<(QDebug dbg, const QShaderDescription &sd)
1198{
1199 const QShaderDescriptionPrivate *d = sd.d;
1200 QDebugStateSaver saver(dbg);
1201
1202 if (sd.isValid()) {
1203 dbg.nospace() << "QShaderDescription("
1204 << "inVars " << d->inVars
1205 << " outVars " << d->outVars
1206 << " uniformBlocks " << d->uniformBlocks
1207 << " pcBlocks " << d->pushConstantBlocks
1208 << " storageBlocks " << d->storageBlocks
1209 << " combinedSamplers " << d->combinedImageSamplers
1210 << " storageImages " << d->storageImages
1211 << " separateImages " << d->separateImages
1212 << " separateSamplers " << d->separateSamplers
1213 << " inBuiltins " << d->inBuiltins
1214 << " outBuiltins " << d->outBuiltins
1215 << ')';
1216 } else {
1217 dbg.nospace() << "QShaderDescription(null)";
1218 }
1219
1220 return dbg;
1221}
1222
1223QDebug operator<<(QDebug dbg, const QShaderDescription::InOutVariable &var)
1224{
1225 QDebugStateSaver saver(dbg);
1226 dbg.nospace() << "InOutVariable(" << typeStr(var.type) << ' ' << var.name;
1227 if (var.perPatch)
1228 dbg.nospace() << " per-patch";
1229 if (var.location >= 0)
1230 dbg.nospace() << " location=" << var.location;
1231 if (var.binding >= 0)
1232 dbg.nospace() << " binding=" << var.binding;
1233 if (var.descriptorSet >= 0)
1234 dbg.nospace() << " set=" << var.descriptorSet;
1235 if (var.imageFormat != QShaderDescription::ImageFormatUnknown)
1236 dbg.nospace() << " imageFormat=" << imageFormatStr(var.imageFormat);
1237 if (var.imageFlags)
1238 dbg.nospace() << " imageFlags=" << var.imageFlags;
1239 if (!var.arrayDims.isEmpty())
1240 dbg.nospace() << " array=" << var.arrayDims;
1241 if (!var.structMembers.isEmpty())
1242 dbg.nospace() << " structMembers=" << var.structMembers;
1243 dbg.nospace() << ')';
1244 return dbg;
1245}
1246
1247QDebug operator<<(QDebug dbg, const QShaderDescription::BlockVariable &var)
1248{
1249 QDebugStateSaver saver(dbg);
1250 dbg.nospace() << "BlockVariable(" << typeStr(var.type) << ' ' << var.name;
1251 if (var.offset != -1)
1252 dbg.nospace() << " offset=" << var.offset;
1253 dbg.nospace() << " size=" << var.size;
1254 if (!var.arrayDims.isEmpty())
1255 dbg.nospace() << " array=" << var.arrayDims;
1256 if (var.arrayStride)
1257 dbg.nospace() << " arrayStride=" << var.arrayStride;
1258 if (var.matrixStride)
1259 dbg.nospace() << " matrixStride=" << var.matrixStride;
1260 if (var.matrixIsRowMajor)
1261 dbg.nospace() << " [rowmaj]";
1262 if (!var.structMembers.isEmpty())
1263 dbg.nospace() << " structMembers=" << var.structMembers;
1264 dbg.nospace() << ')';
1265 return dbg;
1266}
1267
1268QDebug operator<<(QDebug dbg, const QShaderDescription::UniformBlock &blk)
1269{
1270 QDebugStateSaver saver(dbg);
1271 dbg.nospace() << "UniformBlock(" << blk.blockName << ' ' << blk.structName
1272 << " size=" << blk.size;
1273 if (blk.binding >= 0)
1274 dbg.nospace() << " binding=" << blk.binding;
1275 if (blk.descriptorSet >= 0)
1276 dbg.nospace() << " set=" << blk.descriptorSet;
1277 dbg.nospace() << ' ' << blk.members << ')';
1278 return dbg;
1279}
1280
1281QDebug operator<<(QDebug dbg, const QShaderDescription::PushConstantBlock &blk)
1282{
1283 QDebugStateSaver saver(dbg);
1284 dbg.nospace() << "PushConstantBlock(" << blk.name << " size=" << blk.size << ' ' << blk.members
1285 << ')';
1286 return dbg;
1287}
1288
1289QDebug operator<<(QDebug dbg, const QShaderDescription::StorageBlock &blk)
1290{
1291 QDebugStateSaver saver(dbg);
1292 dbg.nospace() << "StorageBlock(" << blk.blockName << ' ' << blk.instanceName
1293 << " knownSize=" << blk.knownSize;
1294 if (blk.binding >= 0)
1295 dbg.nospace() << " binding=" << blk.binding;
1296 if (blk.descriptorSet >= 0)
1297 dbg.nospace() << " set=" << blk.descriptorSet;
1298 if (blk.runtimeArrayStride)
1299 dbg.nospace() << " runtimeArrayStride=" << blk.runtimeArrayStride;
1300 if (blk.qualifierFlags)
1301 dbg.nospace() << " qualifierFlags=" << blk.qualifierFlags;
1302 dbg.nospace() << ' ' << blk.members << ')';
1303 return dbg;
1304}
1305
1306QDebug operator<<(QDebug dbg, const QShaderDescription::BuiltinVariable &builtin)
1307{
1308 QDebugStateSaver saver(dbg);
1309 dbg.nospace() << "BuiltinVariable(type=" << builtinTypeStr(builtin.type);
1310 dbg.nospace() << " varType=" << typeStr(builtin.varType);
1311 if (!builtin.arrayDims.isEmpty())
1312 dbg.nospace() << " array=" << builtin.arrayDims;
1313 dbg.nospace() << ")";
1314 return dbg;
1315}
1316#endif
1317
1318#define JSON_KEY(key) static constexpr QLatin1StringView key ## Key() noexcept { return QLatin1StringView( #key ); }
1319JSON_KEY(name)
1320JSON_KEY(type)
1321JSON_KEY(location)
1322JSON_KEY(binding)
1323JSON_KEY(set)
1324JSON_KEY(perPatch)
1325JSON_KEY(imageFormat)
1326JSON_KEY(imageFlags)
1327JSON_KEY(offset)
1328JSON_KEY(arrayDims)
1329JSON_KEY(arrayStride)
1330JSON_KEY(matrixStride)
1331JSON_KEY(matrixRowMajor)
1332JSON_KEY(structMembers)
1333JSON_KEY(members)
1334JSON_KEY(inputs)
1335JSON_KEY(outputs)
1336JSON_KEY(uniformBlocks)
1337JSON_KEY(blockName)
1338JSON_KEY(structName)
1339JSON_KEY(instanceName)
1340JSON_KEY(size)
1341JSON_KEY(knownSize)
1342JSON_KEY(pushConstantBlocks)
1343JSON_KEY(storageBlocks)
1344JSON_KEY(combinedImageSamplers)
1345JSON_KEY(storageImages)
1346JSON_KEY(inBuiltins)
1347JSON_KEY(outBuiltins)
1348JSON_KEY(computeLocalSize)
1349JSON_KEY(tessellationOutputVertexCount)
1350JSON_KEY(tessellationMode)
1351JSON_KEY(tessellationWindingOrder)
1352JSON_KEY(tessellationPartitioning)
1353JSON_KEY(separateImages)
1354JSON_KEY(separateSamplers)
1355JSON_KEY(runtimeArrayStride)
1356JSON_KEY(qualifierFlags)
1357#undef JSON_KEY
1358
1359static void addDeco(QJsonObject *obj, const QShaderDescription::InOutVariable &v)
1360{
1361 if (v.location >= 0)
1362 (*obj)[locationKey()] = v.location;
1363 if (v.binding >= 0)
1364 (*obj)[bindingKey()] = v.binding;
1365 if (v.descriptorSet >= 0)
1366 (*obj)[setKey()] = v.descriptorSet;
1367 if (v.perPatch)
1368 (*obj)[perPatchKey()] = v.perPatch;
1369 if (v.imageFormat != QShaderDescription::ImageFormatUnknown)
1370 (*obj)[imageFormatKey()] = imageFormatStr(v.imageFormat);
1371 if (v.imageFlags)
1372 (*obj)[imageFlagsKey()] = int(v.imageFlags);
1373 if (!v.arrayDims.isEmpty()) {
1374 QJsonArray dimArr;
1375 for (int dim : v.arrayDims)
1376 dimArr.append(dim);
1377 (*obj)[arrayDimsKey()] = dimArr;
1378 }
1379}
1380
1381static void serializeDecorations(QDataStream *stream, const QShaderDescription::InOutVariable &v, int version)
1382{
1383 (*stream) << v.location;
1384 (*stream) << v.binding;
1385 (*stream) << v.descriptorSet;
1386 (*stream) << int(v.imageFormat);
1387 (*stream) << int(v.imageFlags);
1388 (*stream) << int(v.arrayDims.size());
1389 for (int dim : v.arrayDims)
1390 (*stream) << dim;
1391 if (version > QShaderPrivate::QSB_VERSION_WITHOUT_NATIVE_SHADER_INFO)
1392 (*stream) << quint8(v.perPatch);
1393}
1394
1395static void serializeBuiltinVar(QDataStream *stream, const QShaderDescription::BuiltinVariable &v, int version)
1396{
1397 (*stream) << int(v.type);
1398 if (version > QShaderPrivate::QSB_VERSION_WITHOUT_INPUT_OUTPUT_INTERFACE_BLOCKS) {
1399 (*stream) << int(v.varType);
1400 (*stream) << int(v.arrayDims.size());
1401 for (int dim : v.arrayDims)
1402 (*stream) << dim;
1403 }
1404}
1405
1406static QJsonObject blockMemberObject(const QShaderDescription::BlockVariable &v)
1407{
1408 QJsonObject obj;
1409 obj[nameKey()] = QString::fromUtf8(v.name);
1410 obj[typeKey()] = typeStr(v.type);
1411 if (v.offset != -1)
1412 obj[offsetKey()] = v.offset;
1413 obj[sizeKey()] = v.size;
1414 if (!v.arrayDims.isEmpty()) {
1415 QJsonArray dimArr;
1416 for (int dim : v.arrayDims)
1417 dimArr.append(dim);
1418 obj[arrayDimsKey()] = dimArr;
1419 }
1420 if (v.arrayStride)
1421 obj[arrayStrideKey()] = v.arrayStride;
1422 if (v.matrixStride)
1423 obj[matrixStrideKey()] = v.matrixStride;
1424 if (v.matrixIsRowMajor)
1425 obj[matrixRowMajorKey()] = true;
1426 if (!v.structMembers.isEmpty()) {
1427 QJsonArray arr;
1428 for (const QShaderDescription::BlockVariable &sv : v.structMembers)
1429 arr.append(blockMemberObject(sv));
1430 obj[structMembersKey()] = arr;
1431 }
1432 return obj;
1433}
1434
1435static QJsonObject inOutObject(const QShaderDescription::InOutVariable &v)
1436{
1437 QJsonObject obj;
1438 obj[nameKey()] = QString::fromUtf8(v.name);
1439 obj[typeKey()] = typeStr(v.type);
1440 addDeco(&obj, v);
1441 if (!v.structMembers.isEmpty()) {
1442 QJsonArray arr;
1443 for (const QShaderDescription::BlockVariable &sv : v.structMembers)
1444 arr.append(blockMemberObject(sv));
1445 obj[structMembersKey()] = arr;
1446 }
1447 return obj;
1448}
1449
1450static QJsonObject builtinObject(const QShaderDescription::BuiltinVariable &v)
1451{
1452 QJsonObject obj;
1453
1454 obj[nameKey()] = builtinTypeStr(v.type);
1455 obj[typeKey()] = typeStr(v.varType);
1456 if (!v.arrayDims.isEmpty()) {
1457 QJsonArray dimArr;
1458 for (int dim : v.arrayDims)
1459 dimArr.append(dim);
1460 obj[arrayDimsKey()] = dimArr;
1461 }
1462 return obj;
1463}
1464
1465static void serializeBlockMemberVar(QDataStream *stream, const QShaderDescription::BlockVariable &v)
1466{
1467 (*stream) << QString::fromUtf8(v.name);
1468 (*stream) << int(v.type);
1469 (*stream) << v.offset;
1470 (*stream) << v.size;
1471 (*stream) << int(v.arrayDims.size());
1472 for (int dim : v.arrayDims)
1473 (*stream) << dim;
1474 (*stream) << v.arrayStride;
1475 (*stream) << v.matrixStride;
1476 (*stream) << v.matrixIsRowMajor;
1477 (*stream) << int(v.structMembers.size());
1478 for (const QShaderDescription::BlockVariable &sv : v.structMembers)
1479 serializeBlockMemberVar(stream, sv);
1480}
1481
1482static void serializeInOutVar(QDataStream *stream, const QShaderDescription::InOutVariable &v,
1483 int version)
1484{
1485 (*stream) << QString::fromUtf8(v.name);
1486 (*stream) << int(v.type);
1487 serializeDecorations(stream, v, version);
1488 if (version > QShaderPrivate::QSB_VERSION_WITHOUT_INPUT_OUTPUT_INTERFACE_BLOCKS) {
1489 (*stream) << int(v.structMembers.size());
1490 for (const QShaderDescription::BlockVariable &sv : v.structMembers)
1491 serializeBlockMemberVar(stream, sv);
1492 }
1493}
1494
1495QJsonDocument QShaderDescriptionPrivate::makeDoc()
1496{
1497 QJsonObject root;
1498
1499 QJsonArray jinputs;
1500 for (const QShaderDescription::InOutVariable &v : std::as_const(inVars))
1501 jinputs.append(inOutObject(v));
1502 if (!jinputs.isEmpty())
1503 root[inputsKey()] = jinputs;
1504
1505 QJsonArray joutputs;
1506 for (const QShaderDescription::InOutVariable &v : std::as_const(outVars))
1507 joutputs.append(inOutObject(v));
1508 if (!joutputs.isEmpty())
1509 root[outputsKey()] = joutputs;
1510
1511 QJsonArray juniformBlocks;
1512 for (const QShaderDescription::UniformBlock &b : uniformBlocks) {
1513 QJsonObject juniformBlock;
1514 juniformBlock[blockNameKey()] = QString::fromUtf8(b.blockName);
1515 juniformBlock[structNameKey()] = QString::fromUtf8(b.structName);
1516 juniformBlock[sizeKey()] = b.size;
1517 if (b.binding >= 0)
1518 juniformBlock[bindingKey()] = b.binding;
1519 if (b.descriptorSet >= 0)
1520 juniformBlock[setKey()] = b.descriptorSet;
1521 QJsonArray members;
1522 for (const QShaderDescription::BlockVariable &v : b.members)
1523 members.append(blockMemberObject(v));
1524 juniformBlock[membersKey()] = members;
1525 juniformBlocks.append(juniformBlock);
1526 }
1527 if (!juniformBlocks.isEmpty())
1528 root[uniformBlocksKey()] = juniformBlocks;
1529
1530 QJsonArray jpushConstantBlocks;
1531 for (const QShaderDescription::PushConstantBlock &b : pushConstantBlocks) {
1532 QJsonObject jpushConstantBlock;
1533 jpushConstantBlock[nameKey()] = QString::fromUtf8(b.name);
1534 jpushConstantBlock[sizeKey()] = b.size;
1535 QJsonArray members;
1536 for (const QShaderDescription::BlockVariable &v : b.members)
1537 members.append(blockMemberObject(v));
1538 jpushConstantBlock[membersKey()] = members;
1539 jpushConstantBlocks.append(jpushConstantBlock);
1540 }
1541 if (!jpushConstantBlocks.isEmpty())
1542 root[pushConstantBlocksKey()] = jpushConstantBlocks;
1543
1544 QJsonArray jstorageBlocks;
1545 for (const QShaderDescription::StorageBlock &b : storageBlocks) {
1546 QJsonObject jstorageBlock;
1547 jstorageBlock[blockNameKey()] = QString::fromUtf8(b.blockName);
1548 jstorageBlock[instanceNameKey()] = QString::fromUtf8(b.instanceName);
1549 jstorageBlock[knownSizeKey()] = b.knownSize;
1550 if (b.binding >= 0)
1551 jstorageBlock[bindingKey()] = b.binding;
1552 if (b.descriptorSet >= 0)
1553 jstorageBlock[setKey()] = b.descriptorSet;
1554 if (b.runtimeArrayStride)
1555 jstorageBlock[runtimeArrayStrideKey()] = b.runtimeArrayStride;
1556 if (b.qualifierFlags)
1557 jstorageBlock[qualifierFlagsKey()] = int(b.qualifierFlags);
1558 QJsonArray members;
1559 for (const QShaderDescription::BlockVariable &v : b.members)
1560 members.append(blockMemberObject(v));
1561 jstorageBlock[membersKey()] = members;
1562 jstorageBlocks.append(jstorageBlock);
1563 }
1564 if (!jstorageBlocks.isEmpty())
1565 root[storageBlocksKey()] = jstorageBlocks;
1566
1567 QJsonArray jcombinedSamplers;
1568 for (const QShaderDescription::InOutVariable &v : std::as_const(combinedImageSamplers)) {
1569 QJsonObject sampler;
1570 sampler[nameKey()] = QString::fromUtf8(v.name);
1571 sampler[typeKey()] = typeStr(v.type);
1572 addDeco(&sampler, v);
1573 jcombinedSamplers.append(sampler);
1574 }
1575 if (!jcombinedSamplers.isEmpty())
1576 root[combinedImageSamplersKey()] = jcombinedSamplers;
1577
1578 QJsonArray jstorageImages;
1579 for (const QShaderDescription::InOutVariable &v : std::as_const(storageImages)) {
1580 QJsonObject image;
1581 image[nameKey()] = QString::fromUtf8(v.name);
1582 image[typeKey()] = typeStr(v.type);
1583 addDeco(&image, v);
1584 jstorageImages.append(image);
1585 }
1586 if (!jstorageImages.isEmpty())
1587 root[storageImagesKey()] = jstorageImages;
1588
1589 QJsonArray jinBuiltins;
1590 for (const QShaderDescription::BuiltinVariable &v : std::as_const(inBuiltins))
1591 jinBuiltins.append(builtinObject(v));
1592 if (!jinBuiltins.isEmpty())
1593 root[inBuiltinsKey()] = jinBuiltins;
1594
1595 QJsonArray joutBuiltins;
1596 for (const QShaderDescription::BuiltinVariable &v : std::as_const(outBuiltins))
1597 joutBuiltins.append(builtinObject(v));
1598 if (!joutBuiltins.isEmpty())
1599 root[outBuiltinsKey()] = joutBuiltins;
1600
1601 if (localSize[0] || localSize[1] || localSize[2]) {
1602 QJsonArray jlocalSize;
1603 for (size_t i = 0; i < 3; ++i)
1604 jlocalSize.append(QJsonValue(int(localSize[i])));
1605 root[computeLocalSizeKey()] = jlocalSize;
1606 }
1607
1608 if (tessOutVertCount)
1609 root[tessellationOutputVertexCountKey()] = int(tessOutVertCount);
1610
1611 if (tessMode != QShaderDescription::UnknownTessellationMode)
1612 root[tessellationModeKey()] = tessModeStr(tessMode);
1613
1614 if (tessWind != QShaderDescription::UnknownTessellationWindingOrder)
1615 root[tessellationWindingOrderKey()] = tessWindStr(tessWind);
1616
1617 if (tessPart != QShaderDescription::UnknownTessellationPartitioning)
1618 root[tessellationPartitioningKey()] = tessPartStr(tessPart);
1619
1620 QJsonArray jseparateImages;
1621 for (const QShaderDescription::InOutVariable &v : std::as_const(separateImages)) {
1622 QJsonObject image;
1623 image[nameKey()] = QString::fromUtf8(v.name);
1624 image[typeKey()] = typeStr(v.type);
1625 addDeco(&image, v);
1626 jseparateImages.append(image);
1627 }
1628 if (!jseparateImages.isEmpty())
1629 root[separateImagesKey()] = jseparateImages;
1630
1631 QJsonArray jseparateSamplers;
1632 for (const QShaderDescription::InOutVariable &v : std::as_const(separateSamplers)) {
1633 QJsonObject sampler;
1634 sampler[nameKey()] = QString::fromUtf8(v.name);
1635 sampler[typeKey()] = typeStr(v.type);
1636 addDeco(&sampler, v);
1637 jseparateSamplers.append(sampler);
1638 }
1639 if (!jseparateSamplers.isEmpty())
1640 root[separateSamplersKey()] = jseparateSamplers;
1641
1642 return QJsonDocument(root);
1643}
1644
1645void QShaderDescriptionPrivate::writeToStream(QDataStream *stream, int version)
1646{
1647 (*stream) << int(inVars.size());
1648 for (const QShaderDescription::InOutVariable &v : std::as_const(inVars))
1649 serializeInOutVar(stream, v, version);
1650
1651 (*stream) << int(outVars.size());
1652 for (const QShaderDescription::InOutVariable &v : std::as_const(outVars))
1653 serializeInOutVar(stream, v, version);
1654
1655 (*stream) << int(uniformBlocks.size());
1656 for (const QShaderDescription::UniformBlock &b : uniformBlocks) {
1657 (*stream) << QString::fromUtf8(b.blockName);
1658 (*stream) << QString::fromUtf8(b.structName);
1659 (*stream) << b.size;
1660 (*stream) << b.binding;
1661 (*stream) << b.descriptorSet;
1662 (*stream) << int(b.members.size());
1663 for (const QShaderDescription::BlockVariable &v : b.members)
1664 serializeBlockMemberVar(stream, v);
1665 }
1666
1667 (*stream) << int(pushConstantBlocks.size());
1668 for (const QShaderDescription::PushConstantBlock &b : pushConstantBlocks) {
1669 (*stream) << QString::fromUtf8(b.name);
1670 (*stream) << b.size;
1671 (*stream) << int(b.members.size());
1672 for (const QShaderDescription::BlockVariable &v : b.members)
1673 serializeBlockMemberVar(stream, v);
1674 }
1675
1676 (*stream) << int(storageBlocks.size());
1677 for (const QShaderDescription::StorageBlock &b : storageBlocks) {
1678 (*stream) << QString::fromUtf8(b.blockName);
1679 (*stream) << QString::fromUtf8(b.instanceName);
1680 (*stream) << b.knownSize;
1681 (*stream) << b.binding;
1682 (*stream) << b.descriptorSet;
1683 (*stream) << int(b.members.size());
1684 for (const QShaderDescription::BlockVariable &v : b.members)
1685 serializeBlockMemberVar(stream, v);
1686 if (version > QShaderPrivate::QSB_VERSION_WITHOUT_EXTENDED_STORAGE_BUFFER_INFO) {
1687 (*stream) << b.runtimeArrayStride;
1688 (*stream) << b.qualifierFlags;
1689 }
1690 }
1691
1692 (*stream) << int(combinedImageSamplers.size());
1693 for (const QShaderDescription::InOutVariable &v : std::as_const(combinedImageSamplers)) {
1694 (*stream) << QString::fromUtf8(v.name);
1695 (*stream) << int(v.type);
1696 serializeDecorations(stream, v, version);
1697 }
1698
1699 (*stream) << int(storageImages.size());
1700 for (const QShaderDescription::InOutVariable &v : std::as_const(storageImages)) {
1701 (*stream) << QString::fromUtf8(v.name);
1702 (*stream) << int(v.type);
1703 serializeDecorations(stream, v, version);
1704 }
1705
1706 for (size_t i = 0; i < 3; ++i)
1707 (*stream) << quint32(localSize[i]);
1708
1709 (*stream) << int(separateImages.size());
1710 for (const QShaderDescription::InOutVariable &v : std::as_const(separateImages)) {
1711 (*stream) << QString::fromUtf8(v.name);
1712 (*stream) << int(v.type);
1713 serializeDecorations(stream, v, version);
1714 }
1715
1716 (*stream) << int(separateSamplers.size());
1717 for (const QShaderDescription::InOutVariable &v : std::as_const(separateSamplers)) {
1718 (*stream) << QString::fromUtf8(v.name);
1719 (*stream) << int(v.type);
1720 serializeDecorations(stream, v, version);
1721 }
1722
1723 if (version > QShaderPrivate::QSB_VERSION_WITHOUT_NATIVE_SHADER_INFO) {
1724 (*stream) << quint32(tessOutVertCount);
1725 (*stream) << quint32(tessMode);
1726 (*stream) << quint32(tessWind);
1727 (*stream) << quint32(tessPart);
1728
1729 (*stream) << int(inBuiltins.size());
1730 for (const QShaderDescription::BuiltinVariable &v : std::as_const(inBuiltins))
1731 serializeBuiltinVar(stream, v, version);
1732
1733 (*stream) << int(outBuiltins.size());
1734 for (const QShaderDescription::BuiltinVariable &v : std::as_const(outBuiltins))
1735 serializeBuiltinVar(stream, v, version);
1736 }
1737}
1738
1739static void deserializeDecorations(QDataStream *stream, int version, QShaderDescription::InOutVariable *v)
1740{
1741 (*stream) >> v->location;
1742 (*stream) >> v->binding;
1743 (*stream) >> v->descriptorSet;
1744 int f;
1745 (*stream) >> f;
1746 v->imageFormat = QShaderDescription::ImageFormat(f);
1747 (*stream) >> f;
1748 v->imageFlags = QShaderDescription::ImageFlags(f);
1749
1750 if (version > QShaderPrivate::QSB_VERSION_WITHOUT_VAR_ARRAYDIMS) {
1751 (*stream) >> f;
1752 v->arrayDims.resize(f);
1753 for (int i = 0; i < f; ++i)
1754 (*stream) >> v->arrayDims[i];
1755 }
1756
1757 if (version > QShaderPrivate::QSB_VERSION_WITHOUT_NATIVE_SHADER_INFO) {
1758 quint8 b;
1759 (*stream) >> b;
1760 v->perPatch = b;
1761 }
1762}
1763
1764static QShaderDescription::BuiltinVariable deserializeBuiltinVar(QDataStream *stream, int version)
1765{
1766 QShaderDescription::BuiltinVariable var;
1767 int t;
1768 (*stream) >> t;
1769 var.type = QShaderDescription::BuiltinType(t);
1770 if (version > QShaderPrivate::QSB_VERSION_WITHOUT_INPUT_OUTPUT_INTERFACE_BLOCKS) {
1771 (*stream) >> t;
1772 var.varType = QShaderDescription::VariableType(t);
1773 int count;
1774 (*stream) >> count;
1775 var.arrayDims.resize(count);
1776 for (int i = 0; i < count; ++i)
1777 (*stream) >> var.arrayDims[i];
1778 }
1779 return var;
1780}
1781
1782static QShaderDescription::BlockVariable deserializeBlockMemberVar(QDataStream *stream, int version)
1783{
1784 QShaderDescription::BlockVariable var;
1785 QString tmp;
1786 (*stream) >> tmp;
1787 var.name = tmp.toUtf8();
1788 int t;
1789 (*stream) >> t;
1790 var.type = QShaderDescription::VariableType(t);
1791 (*stream) >> var.offset;
1792 (*stream) >> var.size;
1793 int count;
1794 (*stream) >> count;
1795 var.arrayDims.resize(count);
1796 for (int i = 0; i < count; ++i)
1797 (*stream) >> var.arrayDims[i];
1798 (*stream) >> var.arrayStride;
1799 (*stream) >> var.matrixStride;
1800 (*stream) >> var.matrixIsRowMajor;
1801 (*stream) >> count;
1802 var.structMembers.resize(count);
1803 for (int i = 0; i < count; ++i)
1804 var.structMembers[i] = deserializeBlockMemberVar(stream, version);
1805 return var;
1806}
1807
1808static QShaderDescription::InOutVariable deserializeInOutVar(QDataStream *stream, int version)
1809{
1810 QShaderDescription::InOutVariable var;
1811 QString tmp;
1812 (*stream) >> tmp;
1813 var.name = tmp.toUtf8();
1814 int t;
1815 (*stream) >> t;
1816 var.type = QShaderDescription::VariableType(t);
1817 deserializeDecorations(stream, version, &var);
1818 if (version > QShaderPrivate::QSB_VERSION_WITHOUT_INPUT_OUTPUT_INTERFACE_BLOCKS) {
1819 int count;
1820 (*stream) >> count;
1821 var.structMembers.resize(count);
1822 for (int i = 0; i < count; ++i)
1823 var.structMembers[i] = deserializeBlockMemberVar(stream, version);
1824 }
1825 return var;
1826}
1827
1828void QShaderDescriptionPrivate::loadFromStream(QDataStream *stream, int version)
1829{
1830 Q_ASSERT(ref.loadRelaxed() == 1); // must be detached
1831
1832 int count;
1833 (*stream) >> count;
1834 inVars.resize(count);
1835 for (int i = 0; i < count; ++i)
1836 inVars[i] = deserializeInOutVar(stream, version);
1837
1838 (*stream) >> count;
1839 outVars.resize(count);
1840 for (int i = 0; i < count; ++i)
1841 outVars[i] = deserializeInOutVar(stream, version);
1842
1843 (*stream) >> count;
1844 uniformBlocks.resize(count);
1845 for (int i = 0; i < count; ++i) {
1846 QString tmp;
1847 (*stream) >> tmp;
1848 uniformBlocks[i].blockName = tmp.toUtf8();
1849 (*stream) >> tmp;
1850 uniformBlocks[i].structName = tmp.toUtf8();
1851 (*stream) >> uniformBlocks[i].size;
1852 (*stream) >> uniformBlocks[i].binding;
1853 (*stream) >> uniformBlocks[i].descriptorSet;
1854 int memberCount;
1855 (*stream) >> memberCount;
1856 uniformBlocks[i].members.resize(memberCount);
1857 for (int memberIdx = 0; memberIdx < memberCount; ++memberIdx)
1858 uniformBlocks[i].members[memberIdx] = deserializeBlockMemberVar(stream, version);
1859 }
1860
1861 (*stream) >> count;
1862 pushConstantBlocks.resize(count);
1863 for (int i = 0; i < count; ++i) {
1864 QString tmp;
1865 (*stream) >> tmp;
1866 pushConstantBlocks[i].name = tmp.toUtf8();
1867 (*stream) >> pushConstantBlocks[i].size;
1868 int memberCount;
1869 (*stream) >> memberCount;
1870 pushConstantBlocks[i].members.resize(memberCount);
1871 for (int memberIdx = 0; memberIdx < memberCount; ++memberIdx)
1872 pushConstantBlocks[i].members[memberIdx] = deserializeBlockMemberVar(stream, version);
1873 }
1874
1875 (*stream) >> count;
1876 storageBlocks.resize(count);
1877 for (int i = 0; i < count; ++i) {
1878 QString tmp;
1879 (*stream) >> tmp;
1880 storageBlocks[i].blockName = tmp.toUtf8();
1881 (*stream) >> tmp;
1882 storageBlocks[i].instanceName = tmp.toUtf8();
1883 (*stream) >> storageBlocks[i].knownSize;
1884 (*stream) >> storageBlocks[i].binding;
1885 (*stream) >> storageBlocks[i].descriptorSet;
1886 int memberCount;
1887 (*stream) >> memberCount;
1888 storageBlocks[i].members.resize(memberCount);
1889 for (int memberIdx = 0; memberIdx < memberCount; ++memberIdx)
1890 storageBlocks[i].members[memberIdx] = deserializeBlockMemberVar(stream, version);
1891
1892 if (version > QShaderPrivate::QSB_VERSION_WITHOUT_EXTENDED_STORAGE_BUFFER_INFO) {
1893 (*stream) >> storageBlocks[i].runtimeArrayStride;
1894 (*stream) >> storageBlocks[i].qualifierFlags;
1895 }
1896 }
1897
1898 (*stream) >> count;
1899 combinedImageSamplers.resize(count);
1900 for (int i = 0; i < count; ++i) {
1901 QString tmp;
1902 (*stream) >> tmp;
1903 combinedImageSamplers[i].name = tmp.toUtf8();
1904 int t;
1905 (*stream) >> t;
1906 combinedImageSamplers[i].type = QShaderDescription::VariableType(t);
1907 deserializeDecorations(stream, version, &combinedImageSamplers[i]);
1908 }
1909
1910 (*stream) >> count;
1911 storageImages.resize(count);
1912 for (int i = 0; i < count; ++i) {
1913 QString tmp;
1914 (*stream) >> tmp;
1915 storageImages[i].name = tmp.toUtf8();
1916 int t;
1917 (*stream) >> t;
1918 storageImages[i].type = QShaderDescription::VariableType(t);
1919 deserializeDecorations(stream, version, &storageImages[i]);
1920 }
1921
1922 for (size_t i = 0; i < 3; ++i) {
1923 quint32 v;
1924 (*stream) >> v;
1925 localSize[i] = v;
1926 }
1927
1928 if (version > QShaderPrivate::QSB_VERSION_WITHOUT_SEPARATE_IMAGES_AND_SAMPLERS) {
1929 (*stream) >> count;
1930 separateImages.resize(count);
1931 for (int i = 0; i < count; ++i) {
1932 QString tmp;
1933 (*stream) >> tmp;
1934 separateImages[i].name = tmp.toUtf8();
1935 int t;
1936 (*stream) >> t;
1937 separateImages[i].type = QShaderDescription::VariableType(t);
1938 deserializeDecorations(stream, version, &separateImages[i]);
1939 }
1940
1941 (*stream) >> count;
1942 separateSamplers.resize(count);
1943 for (int i = 0; i < count; ++i) {
1944 QString tmp;
1945 (*stream) >> tmp;
1946 separateSamplers[i].name = tmp.toUtf8();
1947 int t;
1948 (*stream) >> t;
1949 separateSamplers[i].type = QShaderDescription::VariableType(t);
1950 deserializeDecorations(stream, version, &separateSamplers[i]);
1951 }
1952 }
1953
1954 if (version > QShaderPrivate::QSB_VERSION_WITHOUT_NATIVE_SHADER_INFO) {
1955 quint32 v;
1956 (*stream) >> v;
1957 tessOutVertCount = v;
1958 (*stream) >> v;
1959 tessMode = QShaderDescription::TessellationMode(v);
1960 (*stream) >> v;
1961 tessWind = QShaderDescription::TessellationWindingOrder(v);
1962 (*stream) >> v;
1963 tessPart = QShaderDescription::TessellationPartitioning(v);
1964
1965 (*stream) >> count;
1966 inBuiltins.resize(count);
1967 for (int i = 0; i < count; ++i)
1968 inBuiltins[i] = deserializeBuiltinVar(stream, version);
1969
1970 (*stream) >> count;
1971 outBuiltins.resize(count);
1972 for (int i = 0; i < count; ++i)
1973 outBuiltins[i] = deserializeBuiltinVar(stream, version);
1974 }
1975}
1976
1977/*!
1978 Returns \c true if the two QShaderDescription objects \a lhs and \a rhs are
1979 equal.
1980
1981 \relates QShaderDescription
1982 */
1983bool operator==(const QShaderDescription &lhs, const QShaderDescription &rhs) noexcept
1984{
1985 if (lhs.d == rhs.d)
1986 return true;
1987
1988 return lhs.d->inVars == rhs.d->inVars
1989 && lhs.d->outVars == rhs.d->outVars
1990 && lhs.d->uniformBlocks == rhs.d->uniformBlocks
1991 && lhs.d->pushConstantBlocks == rhs.d->pushConstantBlocks
1992 && lhs.d->storageBlocks == rhs.d->storageBlocks
1993 && lhs.d->combinedImageSamplers == rhs.d->combinedImageSamplers
1994 && lhs.d->separateImages == rhs.d->separateImages
1995 && lhs.d->separateSamplers == rhs.d->separateSamplers
1996 && lhs.d->storageImages == rhs.d->storageImages
1997 && lhs.d->inBuiltins == rhs.d->inBuiltins
1998 && lhs.d->outBuiltins == rhs.d->outBuiltins
1999 && lhs.d->localSize == rhs.d->localSize
2000 && lhs.d->tessOutVertCount == rhs.d->tessOutVertCount
2001 && lhs.d->tessMode == rhs.d->tessMode
2002 && lhs.d->tessWind == rhs.d->tessWind
2003 && lhs.d->tessPart == rhs.d->tessPart;
2004}
2005
2006/*!
2007 Returns \c true if the two InOutVariable objects \a lhs and \a rhs are
2008 equal.
2009
2010 \relates QShaderDescription::InOutVariable
2011 */
2012bool operator==(const QShaderDescription::InOutVariable &lhs, const QShaderDescription::InOutVariable &rhs) noexcept
2013{
2014 return lhs.name == rhs.name
2015 && lhs.type == rhs.type
2016 && lhs.location == rhs.location
2017 && lhs.binding == rhs.binding
2018 && lhs.descriptorSet == rhs.descriptorSet
2019 && lhs.imageFormat == rhs.imageFormat
2020 && lhs.imageFlags == rhs.imageFlags
2021 && lhs.arrayDims == rhs.arrayDims
2022 && lhs.perPatch == rhs.perPatch
2023 && lhs.structMembers == rhs.structMembers;
2024}
2025
2026/*!
2027 Returns \c true if the two BlockVariable objects \a lhs and \a rhs are
2028 equal.
2029
2030 \relates QShaderDescription::BlockVariable
2031 */
2032bool operator==(const QShaderDescription::BlockVariable &lhs, const QShaderDescription::BlockVariable &rhs) noexcept
2033{
2034 return lhs.name == rhs.name
2035 && lhs.type == rhs.type
2036 && lhs.offset == rhs.offset
2037 && lhs.size == rhs.size
2038 && lhs.arrayDims == rhs.arrayDims
2039 && lhs.arrayStride == rhs.arrayStride
2040 && lhs.matrixStride == rhs.matrixStride
2041 && lhs.matrixIsRowMajor == rhs.matrixIsRowMajor
2042 && lhs.structMembers == rhs.structMembers;
2043}
2044
2045/*!
2046 Returns \c true if the two UniformBlock objects \a lhs and \a rhs are
2047 equal.
2048
2049 \relates QShaderDescription::UniformBlock
2050 */
2051bool operator==(const QShaderDescription::UniformBlock &lhs, const QShaderDescription::UniformBlock &rhs) noexcept
2052{
2053 return lhs.blockName == rhs.blockName
2054 && lhs.structName == rhs.structName
2055 && lhs.size == rhs.size
2056 && lhs.binding == rhs.binding
2057 && lhs.descriptorSet == rhs.descriptorSet
2058 && lhs.members == rhs.members;
2059}
2060
2061/*!
2062 Returns \c true if the two PushConstantBlock objects \a lhs and \a rhs are
2063 equal.
2064
2065 \relates QShaderDescription::PushConstantBlock
2066 */
2067bool operator==(const QShaderDescription::PushConstantBlock &lhs, const QShaderDescription::PushConstantBlock &rhs) noexcept
2068{
2069 return lhs.name == rhs.name
2070 && lhs.size == rhs.size
2071 && lhs.members == rhs.members;
2072}
2073
2074/*!
2075 Returns \c true if the two StorageBlock objects \a lhs and \a rhs are
2076 equal.
2077
2078 \relates QShaderDescription::StorageBlock
2079 */
2080bool operator==(const QShaderDescription::StorageBlock &lhs, const QShaderDescription::StorageBlock &rhs) noexcept
2081{
2082 return lhs.blockName == rhs.blockName
2083 && lhs.instanceName == rhs.instanceName
2084 && lhs.knownSize == rhs.knownSize
2085 && lhs.binding == rhs.binding
2086 && lhs.descriptorSet == rhs.descriptorSet
2087 && lhs.runtimeArrayStride == rhs.runtimeArrayStride
2088 && lhs.qualifierFlags == rhs.qualifierFlags
2089 && lhs.members == rhs.members;
2090}
2091
2092/*!
2093 Returns \c true if the two BuiltinVariable objects \a lhs and \a rhs are
2094 equal.
2095
2096 \relates QShaderDescription::BuiltinVariable
2097 */
2098bool operator==(const QShaderDescription::BuiltinVariable &lhs, const QShaderDescription::BuiltinVariable &rhs) noexcept
2099{
2100 return lhs.type == rhs.type
2101 && lhs.varType == rhs.varType
2102 && lhs.arrayDims == rhs.arrayDims;
2103}
2104
2105QT_END_NAMESPACE
Combined button and popup list for selecting options.
QDebug operator<<(QDebug dbg, const QFileInfo &fi)
static QLatin1StringView tessModeStr(QShaderDescription::TessellationMode mode)
static QLatin1StringView tessPartStr(QShaderDescription::TessellationPartitioning p)
static void serializeBlockMemberVar(QDataStream *stream, const QShaderDescription::BlockVariable &v)
static QLatin1StringView builtinTypeStr(QShaderDescription::BuiltinType t)
static QJsonObject inOutObject(const QShaderDescription::InOutVariable &v)
static void serializeBuiltinVar(QDataStream *stream, const QShaderDescription::BuiltinVariable &v, int version)
#define JSON_KEY(key)
static QJsonObject builtinObject(const QShaderDescription::BuiltinVariable &v)
static void serializeDecorations(QDataStream *stream, const QShaderDescription::InOutVariable &v, int version)
static QLatin1StringView imageFormatStr(QShaderDescription::ImageFormat f)
static QJsonObject blockMemberObject(const QShaderDescription::BlockVariable &v)
static void addDeco(QJsonObject *obj, const QShaderDescription::InOutVariable &v)
static QLatin1StringView tessWindStr(QShaderDescription::TessellationWindingOrder w)
static QLatin1StringView typeStr(QShaderDescription::VariableType t)
const char k[20]