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