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 : std::as_const(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 : std::as_const(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 : std::as_const(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 : std::as_const(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 : std::as_const(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 : std::as_const(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 int count;
1752 if (!QShaderPrivate::readCount(stream, &count))
1753 return;
1754 v->arrayDims.resize(count);
1755 for (int i = 0; i < count; ++i)
1756 (*stream) >> v->arrayDims[i];
1757 }
1758
1759 if (version > QShaderPrivate::QSB_VERSION_WITHOUT_NATIVE_SHADER_INFO) {
1760 quint8 b;
1761 (*stream) >> b;
1762 v->perPatch = b;
1763 }
1764}
1765
1766static QShaderDescription::BuiltinVariable deserializeBuiltinVar(QDataStream *stream, int version)
1767{
1768 QShaderDescription::BuiltinVariable var;
1769 int t;
1770 (*stream) >> t;
1771 var.type = QShaderDescription::BuiltinType(t);
1772 if (version > QShaderPrivate::QSB_VERSION_WITHOUT_INPUT_OUTPUT_INTERFACE_BLOCKS) {
1773 (*stream) >> t;
1774 var.varType = QShaderDescription::VariableType(t);
1775 int count;
1776 if (!QShaderPrivate::readCount(stream, &count))
1777 return var;
1778 var.arrayDims.resize(count);
1779 for (int i = 0; i < count; ++i)
1780 (*stream) >> var.arrayDims[i];
1781 }
1782 return var;
1783}
1784
1785static const int MAX_STRUCT_NESTING_LEVEL = 64;
1786
1787static QShaderDescription::BlockVariable deserializeBlockMemberVar(QDataStream *stream, int version,
1788 int level)
1789{
1790 QShaderDescription::BlockVariable var;
1791 if (level > MAX_STRUCT_NESTING_LEVEL) {
1792 qWarning("Shader description has structs nested deeper than %d levels.", MAX_STRUCT_NESTING_LEVEL);
1793 stream->setStatus(QDataStream::ReadCorruptData);
1794 return var;
1795 }
1796 QString tmp;
1797 (*stream) >> tmp;
1798 var.name = tmp.toUtf8();
1799 int t;
1800 (*stream) >> t;
1801 var.type = QShaderDescription::VariableType(t);
1802 (*stream) >> var.offset;
1803 (*stream) >> var.size;
1804 int count;
1805 if (!QShaderPrivate::readCount(stream, &count))
1806 return var;
1807 var.arrayDims.resize(count);
1808 for (int i = 0; i < count; ++i)
1809 (*stream) >> var.arrayDims[i];
1810 (*stream) >> var.arrayStride;
1811 (*stream) >> var.matrixStride;
1812 (*stream) >> var.matrixIsRowMajor;
1813 if (!QShaderPrivate::readCount(stream, &count))
1814 return var;
1815 var.structMembers.resize(count);
1816 for (int i = 0; i < count; ++i)
1817 var.structMembers[i] = deserializeBlockMemberVar(stream, version, level + 1);
1818 return var;
1819}
1820
1821static QShaderDescription::InOutVariable deserializeInOutVar(QDataStream *stream, int version)
1822{
1823 QShaderDescription::InOutVariable var;
1824 QString tmp;
1825 (*stream) >> tmp;
1826 var.name = tmp.toUtf8();
1827 int t;
1828 (*stream) >> t;
1829 var.type = QShaderDescription::VariableType(t);
1830 deserializeDecorations(stream, version, &var);
1831 if (version > QShaderPrivate::QSB_VERSION_WITHOUT_INPUT_OUTPUT_INTERFACE_BLOCKS) {
1832 int count;
1833 if (!QShaderPrivate::readCount(stream, &count))
1834 return var;
1835 var.structMembers.resize(count);
1836 for (int i = 0; i < count; ++i)
1837 var.structMembers[i] = deserializeBlockMemberVar(stream, version, 0);
1838 }
1839 return var;
1840}
1841
1842void QShaderDescriptionPrivate::loadFromStream(QDataStream *stream, int version)
1843{
1844 Q_ASSERT(ref.loadRelaxed() == 1); // must be detached
1845
1846 int count;
1847 if (!QShaderPrivate::readCount(stream, &count))
1848 return;
1849 inVars.resize(count);
1850 for (int i = 0; i < count; ++i)
1851 inVars[i] = deserializeInOutVar(stream, version);
1852
1853 if (!QShaderPrivate::readCount(stream, &count))
1854 return;
1855 outVars.resize(count);
1856 for (int i = 0; i < count; ++i)
1857 outVars[i] = deserializeInOutVar(stream, version);
1858
1859 if (!QShaderPrivate::readCount(stream, &count))
1860 return;
1861 uniformBlocks.resize(count);
1862 for (int i = 0; i < count; ++i) {
1863 QString tmp;
1864 (*stream) >> tmp;
1865 uniformBlocks[i].blockName = tmp.toUtf8();
1866 (*stream) >> tmp;
1867 uniformBlocks[i].structName = tmp.toUtf8();
1868 (*stream) >> uniformBlocks[i].size;
1869 (*stream) >> uniformBlocks[i].binding;
1870 (*stream) >> uniformBlocks[i].descriptorSet;
1871 int memberCount;
1872 if (!QShaderPrivate::readCount(stream, &memberCount))
1873 return;
1874 uniformBlocks[i].members.resize(memberCount);
1875 for (int memberIdx = 0; memberIdx < memberCount; ++memberIdx)
1876 uniformBlocks[i].members[memberIdx] = deserializeBlockMemberVar(stream, version, 0);
1877 }
1878
1879 if (!QShaderPrivate::readCount(stream, &count))
1880 return;
1881 pushConstantBlocks.resize(count);
1882 for (int i = 0; i < count; ++i) {
1883 QString tmp;
1884 (*stream) >> tmp;
1885 pushConstantBlocks[i].name = tmp.toUtf8();
1886 (*stream) >> pushConstantBlocks[i].size;
1887 int memberCount;
1888 if (!QShaderPrivate::readCount(stream, &memberCount))
1889 return;
1890 pushConstantBlocks[i].members.resize(memberCount);
1891 for (int memberIdx = 0; memberIdx < memberCount; ++memberIdx)
1892 pushConstantBlocks[i].members[memberIdx] = deserializeBlockMemberVar(stream, version, 0);
1893 }
1894
1895 if (!QShaderPrivate::readCount(stream, &count))
1896 return;
1897 storageBlocks.resize(count);
1898 for (int i = 0; i < count; ++i) {
1899 QString tmp;
1900 (*stream) >> tmp;
1901 storageBlocks[i].blockName = tmp.toUtf8();
1902 (*stream) >> tmp;
1903 storageBlocks[i].instanceName = tmp.toUtf8();
1904 (*stream) >> storageBlocks[i].knownSize;
1905 (*stream) >> storageBlocks[i].binding;
1906 (*stream) >> storageBlocks[i].descriptorSet;
1907 int memberCount;
1908 if (!QShaderPrivate::readCount(stream, &memberCount))
1909 return;
1910 storageBlocks[i].members.resize(memberCount);
1911 for (int memberIdx = 0; memberIdx < memberCount; ++memberIdx)
1912 storageBlocks[i].members[memberIdx] = deserializeBlockMemberVar(stream, version, 0);
1913
1914 if (version > QShaderPrivate::QSB_VERSION_WITHOUT_EXTENDED_STORAGE_BUFFER_INFO) {
1915 (*stream) >> storageBlocks[i].runtimeArrayStride;
1916 (*stream) >> storageBlocks[i].qualifierFlags;
1917 }
1918 }
1919
1920 if (!QShaderPrivate::readCount(stream, &count))
1921 return;
1922 combinedImageSamplers.resize(count);
1923 for (int i = 0; i < count; ++i) {
1924 QString tmp;
1925 (*stream) >> tmp;
1926 combinedImageSamplers[i].name = tmp.toUtf8();
1927 int t;
1928 (*stream) >> t;
1929 combinedImageSamplers[i].type = QShaderDescription::VariableType(t);
1930 deserializeDecorations(stream, version, &combinedImageSamplers[i]);
1931 }
1932
1933 if (!QShaderPrivate::readCount(stream, &count))
1934 return;
1935 storageImages.resize(count);
1936 for (int i = 0; i < count; ++i) {
1937 QString tmp;
1938 (*stream) >> tmp;
1939 storageImages[i].name = tmp.toUtf8();
1940 int t;
1941 (*stream) >> t;
1942 storageImages[i].type = QShaderDescription::VariableType(t);
1943 deserializeDecorations(stream, version, &storageImages[i]);
1944 }
1945
1946 for (size_t i = 0; i < 3; ++i) {
1947 quint32 v;
1948 (*stream) >> v;
1949 localSize[i] = v;
1950 }
1951
1952 if (version > QShaderPrivate::QSB_VERSION_WITHOUT_SEPARATE_IMAGES_AND_SAMPLERS) {
1953 if (!QShaderPrivate::readCount(stream, &count))
1954 return;
1955 separateImages.resize(count);
1956 for (int i = 0; i < count; ++i) {
1957 QString tmp;
1958 (*stream) >> tmp;
1959 separateImages[i].name = tmp.toUtf8();
1960 int t;
1961 (*stream) >> t;
1962 separateImages[i].type = QShaderDescription::VariableType(t);
1963 deserializeDecorations(stream, version, &separateImages[i]);
1964 }
1965
1966 if (!QShaderPrivate::readCount(stream, &count))
1967 return;
1968 separateSamplers.resize(count);
1969 for (int i = 0; i < count; ++i) {
1970 QString tmp;
1971 (*stream) >> tmp;
1972 separateSamplers[i].name = tmp.toUtf8();
1973 int t;
1974 (*stream) >> t;
1975 separateSamplers[i].type = QShaderDescription::VariableType(t);
1976 deserializeDecorations(stream, version, &separateSamplers[i]);
1977 }
1978 }
1979
1980 if (version > QShaderPrivate::QSB_VERSION_WITHOUT_NATIVE_SHADER_INFO) {
1981 quint32 v;
1982 (*stream) >> v;
1983 tessOutVertCount = v;
1984 (*stream) >> v;
1985 tessMode = QShaderDescription::TessellationMode(v);
1986 (*stream) >> v;
1987 tessWind = QShaderDescription::TessellationWindingOrder(v);
1988 (*stream) >> v;
1989 tessPart = QShaderDescription::TessellationPartitioning(v);
1990
1991 if (!QShaderPrivate::readCount(stream, &count))
1992 return;
1993 inBuiltins.resize(count);
1994 for (int i = 0; i < count; ++i)
1995 inBuiltins[i] = deserializeBuiltinVar(stream, version);
1996
1997 if (!QShaderPrivate::readCount(stream, &count))
1998 return;
1999 outBuiltins.resize(count);
2000 for (int i = 0; i < count; ++i)
2001 outBuiltins[i] = deserializeBuiltinVar(stream, version);
2002 }
2003}
2004
2005/*!
2006 Returns \c true if the two QShaderDescription objects \a lhs and \a rhs are
2007 equal.
2008
2009 \relates QShaderDescription
2010 */
2011bool operator==(const QShaderDescription &lhs, const QShaderDescription &rhs) noexcept
2012{
2013 if (lhs.d == rhs.d)
2014 return true;
2015
2016 return lhs.d->inVars == rhs.d->inVars
2017 && lhs.d->outVars == rhs.d->outVars
2018 && lhs.d->uniformBlocks == rhs.d->uniformBlocks
2019 && lhs.d->pushConstantBlocks == rhs.d->pushConstantBlocks
2020 && lhs.d->storageBlocks == rhs.d->storageBlocks
2021 && lhs.d->combinedImageSamplers == rhs.d->combinedImageSamplers
2022 && lhs.d->separateImages == rhs.d->separateImages
2023 && lhs.d->separateSamplers == rhs.d->separateSamplers
2024 && lhs.d->storageImages == rhs.d->storageImages
2025 && lhs.d->inBuiltins == rhs.d->inBuiltins
2026 && lhs.d->outBuiltins == rhs.d->outBuiltins
2027 && lhs.d->localSize == rhs.d->localSize
2028 && lhs.d->tessOutVertCount == rhs.d->tessOutVertCount
2029 && lhs.d->tessMode == rhs.d->tessMode
2030 && lhs.d->tessWind == rhs.d->tessWind
2031 && lhs.d->tessPart == rhs.d->tessPart;
2032}
2033
2034/*!
2035 Returns \c true if the two InOutVariable objects \a lhs and \a rhs are
2036 equal.
2037
2038 \relates QShaderDescription::InOutVariable
2039 */
2040bool operator==(const QShaderDescription::InOutVariable &lhs, const QShaderDescription::InOutVariable &rhs) noexcept
2041{
2042 return lhs.name == rhs.name
2043 && lhs.type == rhs.type
2044 && lhs.location == rhs.location
2045 && lhs.binding == rhs.binding
2046 && lhs.descriptorSet == rhs.descriptorSet
2047 && lhs.imageFormat == rhs.imageFormat
2048 && lhs.imageFlags == rhs.imageFlags
2049 && lhs.arrayDims == rhs.arrayDims
2050 && lhs.perPatch == rhs.perPatch
2051 && lhs.structMembers == rhs.structMembers;
2052}
2053
2054/*!
2055 Returns \c true if the two BlockVariable objects \a lhs and \a rhs are
2056 equal.
2057
2058 \relates QShaderDescription::BlockVariable
2059 */
2060bool operator==(const QShaderDescription::BlockVariable &lhs, const QShaderDescription::BlockVariable &rhs) noexcept
2061{
2062 return lhs.name == rhs.name
2063 && lhs.type == rhs.type
2064 && lhs.offset == rhs.offset
2065 && lhs.size == rhs.size
2066 && lhs.arrayDims == rhs.arrayDims
2067 && lhs.arrayStride == rhs.arrayStride
2068 && lhs.matrixStride == rhs.matrixStride
2069 && lhs.matrixIsRowMajor == rhs.matrixIsRowMajor
2070 && lhs.structMembers == rhs.structMembers;
2071}
2072
2073/*!
2074 Returns \c true if the two UniformBlock objects \a lhs and \a rhs are
2075 equal.
2076
2077 \relates QShaderDescription::UniformBlock
2078 */
2079bool operator==(const QShaderDescription::UniformBlock &lhs, const QShaderDescription::UniformBlock &rhs) noexcept
2080{
2081 return lhs.blockName == rhs.blockName
2082 && lhs.structName == rhs.structName
2083 && lhs.size == rhs.size
2084 && lhs.binding == rhs.binding
2085 && lhs.descriptorSet == rhs.descriptorSet
2086 && lhs.members == rhs.members;
2087}
2088
2089/*!
2090 Returns \c true if the two PushConstantBlock objects \a lhs and \a rhs are
2091 equal.
2092
2093 \relates QShaderDescription::PushConstantBlock
2094 */
2095bool operator==(const QShaderDescription::PushConstantBlock &lhs, const QShaderDescription::PushConstantBlock &rhs) noexcept
2096{
2097 return lhs.name == rhs.name
2098 && lhs.size == rhs.size
2099 && lhs.members == rhs.members;
2100}
2101
2102/*!
2103 Returns \c true if the two StorageBlock objects \a lhs and \a rhs are
2104 equal.
2105
2106 \relates QShaderDescription::StorageBlock
2107 */
2108bool operator==(const QShaderDescription::StorageBlock &lhs, const QShaderDescription::StorageBlock &rhs) noexcept
2109{
2110 return lhs.blockName == rhs.blockName
2111 && lhs.instanceName == rhs.instanceName
2112 && lhs.knownSize == rhs.knownSize
2113 && lhs.binding == rhs.binding
2114 && lhs.descriptorSet == rhs.descriptorSet
2115 && lhs.runtimeArrayStride == rhs.runtimeArrayStride
2116 && lhs.qualifierFlags == rhs.qualifierFlags
2117 && lhs.members == rhs.members;
2118}
2119
2120/*!
2121 Returns \c true if the two BuiltinVariable objects \a lhs and \a rhs are
2122 equal.
2123
2124 \relates QShaderDescription::BuiltinVariable
2125 */
2126bool operator==(const QShaderDescription::BuiltinVariable &lhs, const QShaderDescription::BuiltinVariable &rhs) noexcept
2127{
2128 return lhs.type == rhs.type
2129 && lhs.varType == rhs.varType
2130 && lhs.arrayDims == rhs.arrayDims;
2131}
2132
2133QT_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]