Coverage Report

Created: 2026-06-07 08:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/qtbase/src/gui/rhi/qshaderdescription.cpp
Line
Count
Source
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
5
#include "qshaderdescription_p.h"
6
#include "qshader_p.h"
7
#include <QDebug>
8
#include <QDataStream>
9
#include <QJsonObject>
10
#include <QJsonArray>
11
12
QT_BEGIN_NAMESPACE
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
 */
553
QShaderDescription::QShaderDescription()
554
0
    : d(new QShaderDescriptionPrivate)
555
0
{
556
0
}
557
558
/*!
559
    \internal
560
 */
561
void QShaderDescription::detach()
562
0
{
563
0
    qAtomicDetach(d);
564
0
}
565
566
/*!
567
    Constructs a copy of \a other.
568
 */
569
QShaderDescription::QShaderDescription(const QShaderDescription &other)
570
0
    : d(other.d)
571
0
{
572
0
    d->ref.ref();
573
0
}
574
575
/*!
576
    Assigns \a other to this object.
577
 */
578
QShaderDescription &QShaderDescription::operator=(const QShaderDescription &other)
579
0
{
580
0
    qAtomicAssign(d, other.d);
581
0
    return *this;
582
0
}
583
584
/*!
585
    Destructor.
586
 */
587
QShaderDescription::~QShaderDescription()
588
0
{
589
0
    if (!d->ref.deref())
590
0
        delete d;
591
0
}
592
593
/*!
594
   \return true if the QShaderDescription contains at least one entry in one of
595
   the variable and block lists.
596
 */
597
bool QShaderDescription::isValid() const
598
0
{
599
0
    return !d->inVars.isEmpty() || !d->outVars.isEmpty()
600
0
        || !d->uniformBlocks.isEmpty() || !d->pushConstantBlocks.isEmpty() || !d->storageBlocks.isEmpty()
601
0
        || !d->combinedImageSamplers.isEmpty() || !d->storageImages.isEmpty()
602
0
        || !d->separateImages.isEmpty() || !d->separateSamplers.isEmpty()
603
0
        || !d->inBuiltins.isEmpty() || !d->outBuiltins.isEmpty();
604
0
}
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
 */
613
QByteArray QShaderDescription::toJson() const
614
0
{
615
0
    return d->makeDoc().toJson();
616
0
}
617
618
/*!
619
    Serializes this QShaderDescription to \a stream. \a version specifies
620
    the qsb version.
621
622
    \sa deserialize(), toJson()
623
 */
624
void QShaderDescription::serialize(QDataStream *stream, int version) const
625
0
{
626
0
    d->writeToStream(stream, version);
627
0
}
628
629
/*!
630
    \return a new QShaderDescription loaded from \a stream. \a version specifies
631
    the qsb version.
632
633
    \sa serialize()
634
 */
635
QShaderDescription QShaderDescription::deserialize(QDataStream *stream, int version)
636
0
{
637
0
    QShaderDescription desc;
638
0
    QShaderDescriptionPrivate::get(&desc)->loadFromStream(stream, version);
639
0
    return desc;
640
0
}
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
 */
647
QList<QShaderDescription::InOutVariable> QShaderDescription::inputVariables() const
648
0
{
649
0
    return d->inVars;
650
0
}
651
652
/*!
653
    \return the list of output variables.
654
 */
655
QList<QShaderDescription::InOutVariable> QShaderDescription::outputVariables() const
656
0
{
657
0
    return d->outVars;
658
0
}
659
660
/*!
661
    \return the list of uniform blocks.
662
 */
663
QList<QShaderDescription::UniformBlock> QShaderDescription::uniformBlocks() const
664
0
{
665
0
    return d->uniformBlocks;
666
0
}
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
 */
675
QList<QShaderDescription::PushConstantBlock> QShaderDescription::pushConstantBlocks() const
676
0
{
677
0
    return d->pushConstantBlocks;
678
0
}
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
 */
750
QList<QShaderDescription::StorageBlock> QShaderDescription::storageBlocks() const
751
0
{
752
0
    return d->storageBlocks;
753
0
}
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
  */
777
QList<QShaderDescription::InOutVariable> QShaderDescription::combinedImageSamplers() const
778
0
{
779
0
    return d->combinedImageSamplers;
780
0
}
781
782
QList<QShaderDescription::InOutVariable> QShaderDescription::separateImages() const
783
0
{
784
0
    return d->separateImages;
785
0
}
786
787
QList<QShaderDescription::InOutVariable> QShaderDescription::separateSamplers() const
788
0
{
789
0
    return d->separateSamplers;
790
0
}
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
  */
814
QList<QShaderDescription::InOutVariable> QShaderDescription::storageImages() const
815
0
{
816
0
    return d->storageImages;
817
0
}
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
 */
824
QVector<QShaderDescription::BuiltinVariable> QShaderDescription::inputBuiltinVariables() const
825
0
{
826
0
    return d->inBuiltins;
827
0
}
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
 */
833
QVector<QShaderDescription::BuiltinVariable> QShaderDescription::outputBuiltinVariables() const
834
0
{
835
0
    return d->outBuiltins;
836
0
}
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
 */
848
std::array<uint, 3> QShaderDescription::computeShaderLocalSize() const
849
0
{
850
0
    return d->localSize;
851
0
}
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
 */
863
uint QShaderDescription::tessellationOutputVertexCount() const
864
0
{
865
0
    return d->tessOutVertCount;
866
0
}
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
 */
890
QShaderDescription::TessellationMode QShaderDescription::tessellationMode() const
891
0
{
892
0
    return d->tessMode;
893
0
}
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
 */
916
QShaderDescription::TessellationWindingOrder QShaderDescription::tessellationWindingOrder() const
917
0
{
918
0
    return d->tessWind;
919
0
}
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
 */
943
QShaderDescription::TessellationPartitioning QShaderDescription::tessellationPartitioning() const
944
0
{
945
0
    return d->tessPart;
946
0
}
947
948
static const struct TypeTab {
949
    const char k[20];
950
    QShaderDescription::VariableType v;
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
1031
static QLatin1StringView typeStr(QShaderDescription::VariableType t)
1032
0
{
1033
0
    for (size_t i = 0; i < sizeof(typeTab) / sizeof(TypeTab); ++i) {
1034
0
        if (typeTab[i].v == t)
1035
0
            return QLatin1StringView(typeTab[i].k);
1036
0
    }
1037
0
    return {};
1038
0
}
1039
1040
static const struct ImageFormatTab {
1041
    const char k[15];
1042
    QShaderDescription::ImageFormat v;
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 }
1084
};
1085
1086
static QLatin1StringView imageFormatStr(QShaderDescription::ImageFormat f)
1087
0
{
1088
0
    for (size_t i = 0; i < sizeof(imageFormatTab) / sizeof(ImageFormatTab); ++i) {
1089
0
        if (imageFormatTab[i].v == f)
1090
0
            return QLatin1StringView(imageFormatTab[i].k);
1091
0
    }
1092
0
    return {};
1093
0
}
1094
1095
static const struct BuiltinTypeTab {
1096
    const char k[21];
1097
    QShaderDescription::BuiltinType v;
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 }
1129
};
1130
1131
static QLatin1StringView builtinTypeStr(QShaderDescription::BuiltinType t)
1132
0
{
1133
0
    for (size_t i = 0; i < sizeof(builtinTypeTab) / sizeof(BuiltinTypeTab); ++i) {
1134
0
        if (builtinTypeTab[i].v == t)
1135
0
            return QLatin1StringView(builtinTypeTab[i].k);
1136
0
    }
1137
0
    return {};
1138
0
}
1139
1140
static const struct TessellationModeTab {
1141
    const char k[10];
1142
    QShaderDescription::TessellationMode v;
1143
} tessellationModeTab[] {
1144
    { "unknown", QShaderDescription::UnknownTessellationMode },
1145
    { "triangles", QShaderDescription::TrianglesTessellationMode },
1146
    { "quad", QShaderDescription::QuadTessellationMode },
1147
    { "isoline", QShaderDescription::IsolineTessellationMode }
1148
};
1149
1150
static QLatin1StringView tessModeStr(QShaderDescription::TessellationMode mode)
1151
0
{
1152
0
    for (size_t i = 0; i < sizeof(tessellationModeTab) / sizeof(TessellationModeTab); ++i) {
1153
0
        if (tessellationModeTab[i].v == mode)
1154
0
            return QLatin1StringView(tessellationModeTab[i].k);
1155
0
    }
1156
0
    return {};
1157
0
}
1158
1159
static const struct TessellationWindingOrderTab {
1160
    const char k[8];
1161
    QShaderDescription::TessellationWindingOrder v;
1162
} tessellationWindingOrderTab[] {
1163
    { "unknown", QShaderDescription::UnknownTessellationWindingOrder },
1164
    { "cw", QShaderDescription::CwTessellationWindingOrder },
1165
    { "ccw", QShaderDescription::CcwTessellationWindingOrder }
1166
};
1167
1168
static QLatin1StringView tessWindStr(QShaderDescription::TessellationWindingOrder w)
1169
0
{
1170
0
    for (size_t i = 0; i < sizeof(tessellationWindingOrderTab) / sizeof(TessellationWindingOrderTab); ++i) {
1171
0
        if (tessellationWindingOrderTab[i].v == w)
1172
0
            return QLatin1StringView(tessellationWindingOrderTab[i].k);
1173
0
    }
1174
0
    return {};
1175
0
}
1176
1177
static const struct TessellationPartitioningTab {
1178
    const char k[24];
1179
    QShaderDescription::TessellationPartitioning v;
1180
} tessellationPartitioningTab[] {
1181
    { "unknown", QShaderDescription::UnknownTessellationPartitioning },
1182
    { "equal_spacing", QShaderDescription::EqualTessellationPartitioning },
1183
    { "fractional_even_spacing", QShaderDescription::FractionalEvenTessellationPartitioning },
1184
    { "fractional_odd_spacing", QShaderDescription::FractionalOddTessellationPartitioning }
1185
};
1186
1187
static QLatin1StringView tessPartStr(QShaderDescription::TessellationPartitioning p)
1188
0
{
1189
0
    for (size_t i = 0; i < sizeof(tessellationPartitioningTab) / sizeof(TessellationPartitioningTab); ++i) {
1190
0
        if (tessellationPartitioningTab[i].v == p)
1191
0
            return QLatin1StringView(tessellationPartitioningTab[i].k);
1192
0
    }
1193
0
    return {};
1194
0
}
1195
1196
#ifndef QT_NO_DEBUG_STREAM
1197
QDebug operator<<(QDebug dbg, const QShaderDescription &sd)
1198
0
{
1199
0
    const QShaderDescriptionPrivate *d = sd.d;
1200
0
    QDebugStateSaver saver(dbg);
1201
1202
0
    if (sd.isValid()) {
1203
0
        dbg.nospace() << "QShaderDescription("
1204
0
                      << "inVars " << d->inVars
1205
0
                      << " outVars " << d->outVars
1206
0
                      << " uniformBlocks " << d->uniformBlocks
1207
0
                      << " pcBlocks " << d->pushConstantBlocks
1208
0
                      << " storageBlocks " << d->storageBlocks
1209
0
                      << " combinedSamplers " << d->combinedImageSamplers
1210
0
                      << " storageImages " << d->storageImages
1211
0
                      << " separateImages " << d->separateImages
1212
0
                      << " separateSamplers " << d->separateSamplers
1213
0
                      << " inBuiltins " << d->inBuiltins
1214
0
                      << " outBuiltins " << d->outBuiltins
1215
0
                      << ')';
1216
0
    } else {
1217
0
        dbg.nospace() << "QShaderDescription(null)";
1218
0
    }
1219
1220
0
    return dbg;
1221
0
}
1222
1223
QDebug operator<<(QDebug dbg, const QShaderDescription::InOutVariable &var)
1224
0
{
1225
0
    QDebugStateSaver saver(dbg);
1226
0
    dbg.nospace() << "InOutVariable(" << typeStr(var.type) << ' ' << var.name;
1227
0
    if (var.perPatch)
1228
0
        dbg.nospace() << " per-patch";
1229
0
    if (var.location >= 0)
1230
0
        dbg.nospace() << " location=" << var.location;
1231
0
    if (var.binding >= 0)
1232
0
        dbg.nospace() << " binding=" << var.binding;
1233
0
    if (var.descriptorSet >= 0)
1234
0
        dbg.nospace() << " set=" << var.descriptorSet;
1235
0
    if (var.imageFormat != QShaderDescription::ImageFormatUnknown)
1236
0
        dbg.nospace() << " imageFormat=" << imageFormatStr(var.imageFormat);
1237
0
    if (var.imageFlags)
1238
0
        dbg.nospace() << " imageFlags=" << var.imageFlags;
1239
0
    if (!var.arrayDims.isEmpty())
1240
0
        dbg.nospace() << " array=" << var.arrayDims;
1241
0
    if (!var.structMembers.isEmpty())
1242
0
        dbg.nospace() << " structMembers=" << var.structMembers;
1243
0
    dbg.nospace() << ')';
1244
0
    return dbg;
1245
0
}
1246
1247
QDebug operator<<(QDebug dbg, const QShaderDescription::BlockVariable &var)
1248
0
{
1249
0
    QDebugStateSaver saver(dbg);
1250
0
    dbg.nospace() << "BlockVariable(" << typeStr(var.type) << ' ' << var.name;
1251
0
    if (var.offset != -1)
1252
0
        dbg.nospace() << " offset=" << var.offset;
1253
0
    dbg.nospace() << " size=" << var.size;
1254
0
    if (!var.arrayDims.isEmpty())
1255
0
        dbg.nospace() << " array=" << var.arrayDims;
1256
0
    if (var.arrayStride)
1257
0
        dbg.nospace() << " arrayStride=" << var.arrayStride;
1258
0
    if (var.matrixStride)
1259
0
        dbg.nospace() << " matrixStride=" << var.matrixStride;
1260
0
    if (var.matrixIsRowMajor)
1261
0
        dbg.nospace() << " [rowmaj]";
1262
0
    if (!var.structMembers.isEmpty())
1263
0
        dbg.nospace() << " structMembers=" << var.structMembers;
1264
0
    dbg.nospace() << ')';
1265
0
    return dbg;
1266
0
}
1267
1268
QDebug operator<<(QDebug dbg, const QShaderDescription::UniformBlock &blk)
1269
0
{
1270
0
    QDebugStateSaver saver(dbg);
1271
0
    dbg.nospace() << "UniformBlock(" << blk.blockName << ' ' << blk.structName
1272
0
                  << " size=" << blk.size;
1273
0
    if (blk.binding >= 0)
1274
0
        dbg.nospace() << " binding=" << blk.binding;
1275
0
    if (blk.descriptorSet >= 0)
1276
0
        dbg.nospace() << " set=" << blk.descriptorSet;
1277
0
    dbg.nospace() << ' ' << blk.members << ')';
1278
0
    return dbg;
1279
0
}
1280
1281
QDebug operator<<(QDebug dbg, const QShaderDescription::PushConstantBlock &blk)
1282
0
{
1283
0
    QDebugStateSaver saver(dbg);
1284
0
    dbg.nospace() << "PushConstantBlock(" << blk.name << " size=" << blk.size << ' ' << blk.members
1285
0
                  << ')';
1286
0
    return dbg;
1287
0
}
1288
1289
QDebug operator<<(QDebug dbg, const QShaderDescription::StorageBlock &blk)
1290
0
{
1291
0
    QDebugStateSaver saver(dbg);
1292
0
    dbg.nospace() << "StorageBlock(" << blk.blockName << ' ' << blk.instanceName
1293
0
                  << " knownSize=" << blk.knownSize;
1294
0
    if (blk.binding >= 0)
1295
0
        dbg.nospace() << " binding=" << blk.binding;
1296
0
    if (blk.descriptorSet >= 0)
1297
0
        dbg.nospace() << " set=" << blk.descriptorSet;
1298
0
    if (blk.runtimeArrayStride)
1299
0
        dbg.nospace() << " runtimeArrayStride=" << blk.runtimeArrayStride;
1300
0
    if (blk.qualifierFlags)
1301
0
        dbg.nospace() << " qualifierFlags=" << blk.qualifierFlags;
1302
0
    dbg.nospace() << ' ' << blk.members << ')';
1303
0
    return dbg;
1304
0
}
1305
1306
QDebug operator<<(QDebug dbg, const QShaderDescription::BuiltinVariable &builtin)
1307
0
{
1308
0
    QDebugStateSaver saver(dbg);
1309
0
    dbg.nospace() << "BuiltinVariable(type=" << builtinTypeStr(builtin.type);
1310
0
    dbg.nospace() << " varType=" << typeStr(builtin.varType);
1311
0
    if (!builtin.arrayDims.isEmpty())
1312
0
        dbg.nospace() << " array=" << builtin.arrayDims;
1313
0
    dbg.nospace() << ")";
1314
0
    return dbg;
1315
0
}
1316
#endif
1317
1318
0
#define JSON_KEY(key) static constexpr QLatin1StringView key ## Key() noexcept { return QLatin1StringView( #key ); }
Unexecuted instantiation: qshaderdescription.cpp:structMembersKey()
Unexecuted instantiation: qshaderdescription.cpp:inputsKey()
Unexecuted instantiation: qshaderdescription.cpp:outputsKey()
Unexecuted instantiation: qshaderdescription.cpp:blockNameKey()
Unexecuted instantiation: qshaderdescription.cpp:structNameKey()
Unexecuted instantiation: qshaderdescription.cpp:sizeKey()
Unexecuted instantiation: qshaderdescription.cpp:bindingKey()
Unexecuted instantiation: qshaderdescription.cpp:setKey()
Unexecuted instantiation: qshaderdescription.cpp:offsetKey()
Unexecuted instantiation: qshaderdescription.cpp:arrayDimsKey()
Unexecuted instantiation: qshaderdescription.cpp:arrayStrideKey()
Unexecuted instantiation: qshaderdescription.cpp:matrixStrideKey()
Unexecuted instantiation: qshaderdescription.cpp:matrixRowMajorKey()
Unexecuted instantiation: qshaderdescription.cpp:membersKey()
Unexecuted instantiation: qshaderdescription.cpp:uniformBlocksKey()
Unexecuted instantiation: qshaderdescription.cpp:nameKey()
Unexecuted instantiation: qshaderdescription.cpp:pushConstantBlocksKey()
Unexecuted instantiation: qshaderdescription.cpp:instanceNameKey()
Unexecuted instantiation: qshaderdescription.cpp:knownSizeKey()
Unexecuted instantiation: qshaderdescription.cpp:runtimeArrayStrideKey()
Unexecuted instantiation: qshaderdescription.cpp:qualifierFlagsKey()
Unexecuted instantiation: qshaderdescription.cpp:storageBlocksKey()
Unexecuted instantiation: qshaderdescription.cpp:typeKey()
Unexecuted instantiation: qshaderdescription.cpp:locationKey()
Unexecuted instantiation: qshaderdescription.cpp:perPatchKey()
Unexecuted instantiation: qshaderdescription.cpp:imageFormatKey()
Unexecuted instantiation: qshaderdescription.cpp:imageFlagsKey()
Unexecuted instantiation: qshaderdescription.cpp:combinedImageSamplersKey()
Unexecuted instantiation: qshaderdescription.cpp:storageImagesKey()
Unexecuted instantiation: qshaderdescription.cpp:inBuiltinsKey()
Unexecuted instantiation: qshaderdescription.cpp:outBuiltinsKey()
Unexecuted instantiation: qshaderdescription.cpp:computeLocalSizeKey()
Unexecuted instantiation: qshaderdescription.cpp:tessellationOutputVertexCountKey()
Unexecuted instantiation: qshaderdescription.cpp:tessellationModeKey()
Unexecuted instantiation: qshaderdescription.cpp:tessellationWindingOrderKey()
Unexecuted instantiation: qshaderdescription.cpp:tessellationPartitioningKey()
Unexecuted instantiation: qshaderdescription.cpp:separateImagesKey()
Unexecuted instantiation: qshaderdescription.cpp:separateSamplersKey()
1319
JSON_KEY(name)
1320
JSON_KEY(type)
1321
JSON_KEY(location)
1322
JSON_KEY(binding)
1323
JSON_KEY(set)
1324
JSON_KEY(perPatch)
1325
JSON_KEY(imageFormat)
1326
JSON_KEY(imageFlags)
1327
JSON_KEY(offset)
1328
JSON_KEY(arrayDims)
1329
JSON_KEY(arrayStride)
1330
JSON_KEY(matrixStride)
1331
JSON_KEY(matrixRowMajor)
1332
JSON_KEY(structMembers)
1333
JSON_KEY(members)
1334
JSON_KEY(inputs)
1335
JSON_KEY(outputs)
1336
JSON_KEY(uniformBlocks)
1337
JSON_KEY(blockName)
1338
JSON_KEY(structName)
1339
JSON_KEY(instanceName)
1340
JSON_KEY(size)
1341
JSON_KEY(knownSize)
1342
JSON_KEY(pushConstantBlocks)
1343
JSON_KEY(storageBlocks)
1344
JSON_KEY(combinedImageSamplers)
1345
JSON_KEY(storageImages)
1346
JSON_KEY(inBuiltins)
1347
JSON_KEY(outBuiltins)
1348
JSON_KEY(computeLocalSize)
1349
JSON_KEY(tessellationOutputVertexCount)
1350
JSON_KEY(tessellationMode)
1351
JSON_KEY(tessellationWindingOrder)
1352
JSON_KEY(tessellationPartitioning)
1353
JSON_KEY(separateImages)
1354
JSON_KEY(separateSamplers)
1355
JSON_KEY(runtimeArrayStride)
1356
JSON_KEY(qualifierFlags)
1357
#undef JSON_KEY
1358
1359
static void addDeco(QJsonObject *obj, const QShaderDescription::InOutVariable &v)
1360
0
{
1361
0
    if (v.location >= 0)
1362
0
        (*obj)[locationKey()] = v.location;
1363
0
    if (v.binding >= 0)
1364
0
        (*obj)[bindingKey()] = v.binding;
1365
0
    if (v.descriptorSet >= 0)
1366
0
        (*obj)[setKey()] = v.descriptorSet;
1367
0
    if (v.perPatch)
1368
0
        (*obj)[perPatchKey()] = v.perPatch;
1369
0
    if (v.imageFormat != QShaderDescription::ImageFormatUnknown)
1370
0
        (*obj)[imageFormatKey()] = imageFormatStr(v.imageFormat);
1371
0
    if (v.imageFlags)
1372
0
        (*obj)[imageFlagsKey()] = int(v.imageFlags);
1373
0
    if (!v.arrayDims.isEmpty()) {
1374
0
        QJsonArray dimArr;
1375
0
        for (int dim : v.arrayDims)
1376
0
            dimArr.append(dim);
1377
0
        (*obj)[arrayDimsKey()] = dimArr;
1378
0
    }
1379
0
}
1380
1381
static void serializeDecorations(QDataStream *stream, const QShaderDescription::InOutVariable &v, int version)
1382
0
{
1383
0
    (*stream) << v.location;
1384
0
    (*stream) << v.binding;
1385
0
    (*stream) << v.descriptorSet;
1386
0
    (*stream) << int(v.imageFormat);
1387
0
    (*stream) << int(v.imageFlags);
1388
0
    (*stream) << int(v.arrayDims.size());
1389
0
    for (int dim : v.arrayDims)
1390
0
        (*stream) << dim;
1391
0
    if (version > QShaderPrivate::QSB_VERSION_WITHOUT_NATIVE_SHADER_INFO)
1392
0
        (*stream) << quint8(v.perPatch);
1393
0
}
1394
1395
static void serializeBuiltinVar(QDataStream *stream, const QShaderDescription::BuiltinVariable &v, int version)
1396
0
{
1397
0
    (*stream) << int(v.type);
1398
0
    if (version > QShaderPrivate::QSB_VERSION_WITHOUT_INPUT_OUTPUT_INTERFACE_BLOCKS) {
1399
0
        (*stream) << int(v.varType);
1400
0
        (*stream) << int(v.arrayDims.size());
1401
0
        for (int dim : v.arrayDims)
1402
0
            (*stream) << dim;
1403
0
    }
1404
0
}
1405
1406
static QJsonObject blockMemberObject(const QShaderDescription::BlockVariable &v)
1407
0
{
1408
0
    QJsonObject obj;
1409
0
    obj[nameKey()] = QString::fromUtf8(v.name);
1410
0
    obj[typeKey()] = typeStr(v.type);
1411
0
    if (v.offset != -1)
1412
0
        obj[offsetKey()] = v.offset;
1413
0
    obj[sizeKey()] = v.size;
1414
0
    if (!v.arrayDims.isEmpty()) {
1415
0
        QJsonArray dimArr;
1416
0
        for (int dim : v.arrayDims)
1417
0
            dimArr.append(dim);
1418
0
        obj[arrayDimsKey()] = dimArr;
1419
0
    }
1420
0
    if (v.arrayStride)
1421
0
        obj[arrayStrideKey()] = v.arrayStride;
1422
0
    if (v.matrixStride)
1423
0
        obj[matrixStrideKey()] = v.matrixStride;
1424
0
    if (v.matrixIsRowMajor)
1425
0
        obj[matrixRowMajorKey()] = true;
1426
0
    if (!v.structMembers.isEmpty()) {
1427
0
        QJsonArray arr;
1428
0
        for (const QShaderDescription::BlockVariable &sv : v.structMembers)
1429
0
            arr.append(blockMemberObject(sv));
1430
0
        obj[structMembersKey()] = arr;
1431
0
    }
1432
0
    return obj;
1433
0
}
1434
1435
static QJsonObject inOutObject(const QShaderDescription::InOutVariable &v)
1436
0
{
1437
0
    QJsonObject obj;
1438
0
    obj[nameKey()] = QString::fromUtf8(v.name);
1439
0
    obj[typeKey()] = typeStr(v.type);
1440
0
    addDeco(&obj, v);
1441
0
    if (!v.structMembers.isEmpty()) {
1442
0
        QJsonArray arr;
1443
0
        for (const QShaderDescription::BlockVariable &sv : v.structMembers)
1444
0
            arr.append(blockMemberObject(sv));
1445
0
        obj[structMembersKey()] = arr;
1446
0
    }
1447
0
    return obj;
1448
0
}
1449
1450
static QJsonObject builtinObject(const QShaderDescription::BuiltinVariable &v)
1451
0
{
1452
0
    QJsonObject obj;
1453
1454
0
    obj[nameKey()] = builtinTypeStr(v.type);
1455
0
    obj[typeKey()] = typeStr(v.varType);
1456
0
    if (!v.arrayDims.isEmpty()) {
1457
0
        QJsonArray dimArr;
1458
0
        for (int dim : v.arrayDims)
1459
0
            dimArr.append(dim);
1460
0
        obj[arrayDimsKey()] = dimArr;
1461
0
    }
1462
0
    return obj;
1463
0
}
1464
1465
static void serializeBlockMemberVar(QDataStream *stream, const QShaderDescription::BlockVariable &v)
1466
0
{
1467
0
    (*stream) << QString::fromUtf8(v.name);
1468
0
    (*stream) << int(v.type);
1469
0
    (*stream) << v.offset;
1470
0
    (*stream) << v.size;
1471
0
    (*stream) << int(v.arrayDims.size());
1472
0
    for (int dim : v.arrayDims)
1473
0
        (*stream) << dim;
1474
0
    (*stream) << v.arrayStride;
1475
0
    (*stream) << v.matrixStride;
1476
0
    (*stream) << v.matrixIsRowMajor;
1477
0
    (*stream) << int(v.structMembers.size());
1478
0
    for (const QShaderDescription::BlockVariable &sv : v.structMembers)
1479
0
        serializeBlockMemberVar(stream, sv);
1480
0
}
1481
1482
static void serializeInOutVar(QDataStream *stream, const QShaderDescription::InOutVariable &v,
1483
                              int version)
1484
0
{
1485
0
    (*stream) << QString::fromUtf8(v.name);
1486
0
    (*stream) << int(v.type);
1487
0
    serializeDecorations(stream, v, version);
1488
0
    if (version > QShaderPrivate::QSB_VERSION_WITHOUT_INPUT_OUTPUT_INTERFACE_BLOCKS) {
1489
0
        (*stream) << int(v.structMembers.size());
1490
0
        for (const QShaderDescription::BlockVariable &sv : v.structMembers)
1491
0
            serializeBlockMemberVar(stream, sv);
1492
0
    }
1493
0
}
1494
1495
QJsonDocument QShaderDescriptionPrivate::makeDoc()
1496
0
{
1497
0
    QJsonObject root;
1498
1499
0
    QJsonArray jinputs;
1500
0
    for (const QShaderDescription::InOutVariable &v : std::as_const(inVars))
1501
0
        jinputs.append(inOutObject(v));
1502
0
    if (!jinputs.isEmpty())
1503
0
        root[inputsKey()] = jinputs;
1504
1505
0
    QJsonArray joutputs;
1506
0
    for (const QShaderDescription::InOutVariable &v : std::as_const(outVars))
1507
0
        joutputs.append(inOutObject(v));
1508
0
    if (!joutputs.isEmpty())
1509
0
        root[outputsKey()] = joutputs;
1510
1511
0
    QJsonArray juniformBlocks;
1512
0
    for (const QShaderDescription::UniformBlock &b : std::as_const(uniformBlocks)) {
1513
0
        QJsonObject juniformBlock;
1514
0
        juniformBlock[blockNameKey()] = QString::fromUtf8(b.blockName);
1515
0
        juniformBlock[structNameKey()] = QString::fromUtf8(b.structName);
1516
0
        juniformBlock[sizeKey()] = b.size;
1517
0
        if (b.binding >= 0)
1518
0
            juniformBlock[bindingKey()] = b.binding;
1519
0
        if (b.descriptorSet >= 0)
1520
0
            juniformBlock[setKey()] = b.descriptorSet;
1521
0
        QJsonArray members;
1522
0
        for (const QShaderDescription::BlockVariable &v : b.members)
1523
0
            members.append(blockMemberObject(v));
1524
0
        juniformBlock[membersKey()] = members;
1525
0
        juniformBlocks.append(juniformBlock);
1526
0
    }
1527
0
    if (!juniformBlocks.isEmpty())
1528
0
        root[uniformBlocksKey()] = juniformBlocks;
1529
1530
0
    QJsonArray jpushConstantBlocks;
1531
0
    for (const QShaderDescription::PushConstantBlock &b : std::as_const(pushConstantBlocks)) {
1532
0
        QJsonObject jpushConstantBlock;
1533
0
        jpushConstantBlock[nameKey()] = QString::fromUtf8(b.name);
1534
0
        jpushConstantBlock[sizeKey()] = b.size;
1535
0
        QJsonArray members;
1536
0
        for (const QShaderDescription::BlockVariable &v : b.members)
1537
0
            members.append(blockMemberObject(v));
1538
0
        jpushConstantBlock[membersKey()] = members;
1539
0
        jpushConstantBlocks.append(jpushConstantBlock);
1540
0
    }
1541
0
    if (!jpushConstantBlocks.isEmpty())
1542
0
        root[pushConstantBlocksKey()] = jpushConstantBlocks;
1543
1544
0
    QJsonArray jstorageBlocks;
1545
0
    for (const QShaderDescription::StorageBlock &b : std::as_const(storageBlocks)) {
1546
0
        QJsonObject jstorageBlock;
1547
0
        jstorageBlock[blockNameKey()] = QString::fromUtf8(b.blockName);
1548
0
        jstorageBlock[instanceNameKey()] = QString::fromUtf8(b.instanceName);
1549
0
        jstorageBlock[knownSizeKey()] = b.knownSize;
1550
0
        if (b.binding >= 0)
1551
0
            jstorageBlock[bindingKey()] = b.binding;
1552
0
        if (b.descriptorSet >= 0)
1553
0
            jstorageBlock[setKey()] = b.descriptorSet;
1554
0
        if (b.runtimeArrayStride)
1555
0
            jstorageBlock[runtimeArrayStrideKey()] = b.runtimeArrayStride;
1556
0
        if (b.qualifierFlags)
1557
0
            jstorageBlock[qualifierFlagsKey()] = int(b.qualifierFlags);
1558
0
        QJsonArray members;
1559
0
        for (const QShaderDescription::BlockVariable &v : b.members)
1560
0
            members.append(blockMemberObject(v));
1561
0
        jstorageBlock[membersKey()] = members;
1562
0
        jstorageBlocks.append(jstorageBlock);
1563
0
    }
1564
0
    if (!jstorageBlocks.isEmpty())
1565
0
        root[storageBlocksKey()] = jstorageBlocks;
1566
1567
0
    QJsonArray jcombinedSamplers;
1568
0
    for (const QShaderDescription::InOutVariable &v : std::as_const(combinedImageSamplers)) {
1569
0
        QJsonObject sampler;
1570
0
        sampler[nameKey()] = QString::fromUtf8(v.name);
1571
0
        sampler[typeKey()] = typeStr(v.type);
1572
0
        addDeco(&sampler, v);
1573
0
        jcombinedSamplers.append(sampler);
1574
0
    }
1575
0
    if (!jcombinedSamplers.isEmpty())
1576
0
        root[combinedImageSamplersKey()] = jcombinedSamplers;
1577
1578
0
    QJsonArray jstorageImages;
1579
0
    for (const QShaderDescription::InOutVariable &v : std::as_const(storageImages)) {
1580
0
        QJsonObject image;
1581
0
        image[nameKey()] = QString::fromUtf8(v.name);
1582
0
        image[typeKey()] = typeStr(v.type);
1583
0
        addDeco(&image, v);
1584
0
        jstorageImages.append(image);
1585
0
    }
1586
0
    if (!jstorageImages.isEmpty())
1587
0
        root[storageImagesKey()] = jstorageImages;
1588
1589
0
    QJsonArray jinBuiltins;
1590
0
    for (const QShaderDescription::BuiltinVariable &v : std::as_const(inBuiltins))
1591
0
        jinBuiltins.append(builtinObject(v));
1592
0
    if (!jinBuiltins.isEmpty())
1593
0
        root[inBuiltinsKey()] = jinBuiltins;
1594
1595
0
    QJsonArray joutBuiltins;
1596
0
    for (const QShaderDescription::BuiltinVariable &v : std::as_const(outBuiltins))
1597
0
        joutBuiltins.append(builtinObject(v));
1598
0
    if (!joutBuiltins.isEmpty())
1599
0
        root[outBuiltinsKey()] = joutBuiltins;
1600
1601
0
    if (localSize[0] || localSize[1] || localSize[2]) {
1602
0
        QJsonArray jlocalSize;
1603
0
        for (size_t i = 0; i < 3; ++i)
1604
0
            jlocalSize.append(QJsonValue(int(localSize[i])));
1605
0
        root[computeLocalSizeKey()] = jlocalSize;
1606
0
    }
1607
1608
0
    if (tessOutVertCount)
1609
0
        root[tessellationOutputVertexCountKey()] = int(tessOutVertCount);
1610
1611
0
    if (tessMode != QShaderDescription::UnknownTessellationMode)
1612
0
        root[tessellationModeKey()] = tessModeStr(tessMode);
1613
1614
0
    if (tessWind != QShaderDescription::UnknownTessellationWindingOrder)
1615
0
        root[tessellationWindingOrderKey()] = tessWindStr(tessWind);
1616
1617
0
    if (tessPart != QShaderDescription::UnknownTessellationPartitioning)
1618
0
        root[tessellationPartitioningKey()] = tessPartStr(tessPart);
1619
1620
0
    QJsonArray jseparateImages;
1621
0
    for (const QShaderDescription::InOutVariable &v : std::as_const(separateImages)) {
1622
0
        QJsonObject image;
1623
0
        image[nameKey()] = QString::fromUtf8(v.name);
1624
0
        image[typeKey()] = typeStr(v.type);
1625
0
        addDeco(&image, v);
1626
0
        jseparateImages.append(image);
1627
0
    }
1628
0
    if (!jseparateImages.isEmpty())
1629
0
        root[separateImagesKey()] = jseparateImages;
1630
1631
0
    QJsonArray jseparateSamplers;
1632
0
    for (const QShaderDescription::InOutVariable &v : std::as_const(separateSamplers)) {
1633
0
        QJsonObject sampler;
1634
0
        sampler[nameKey()] = QString::fromUtf8(v.name);
1635
0
        sampler[typeKey()] = typeStr(v.type);
1636
0
        addDeco(&sampler, v);
1637
0
        jseparateSamplers.append(sampler);
1638
0
    }
1639
0
    if (!jseparateSamplers.isEmpty())
1640
0
        root[separateSamplersKey()] = jseparateSamplers;
1641
1642
0
    return QJsonDocument(root);
1643
0
}
1644
1645
void QShaderDescriptionPrivate::writeToStream(QDataStream *stream, int version)
1646
0
{
1647
0
    (*stream) << int(inVars.size());
1648
0
    for (const QShaderDescription::InOutVariable &v : std::as_const(inVars))
1649
0
        serializeInOutVar(stream, v, version);
1650
1651
0
    (*stream) << int(outVars.size());
1652
0
    for (const QShaderDescription::InOutVariable &v : std::as_const(outVars))
1653
0
        serializeInOutVar(stream, v, version);
1654
1655
0
    (*stream) << int(uniformBlocks.size());
1656
0
    for (const QShaderDescription::UniformBlock &b : std::as_const(uniformBlocks)) {
1657
0
        (*stream) << QString::fromUtf8(b.blockName);
1658
0
        (*stream) << QString::fromUtf8(b.structName);
1659
0
        (*stream) << b.size;
1660
0
        (*stream) << b.binding;
1661
0
        (*stream) << b.descriptorSet;
1662
0
        (*stream) << int(b.members.size());
1663
0
        for (const QShaderDescription::BlockVariable &v : b.members)
1664
0
            serializeBlockMemberVar(stream, v);
1665
0
    }
1666
1667
0
    (*stream) << int(pushConstantBlocks.size());
1668
0
    for (const QShaderDescription::PushConstantBlock &b : std::as_const(pushConstantBlocks)) {
1669
0
        (*stream) << QString::fromUtf8(b.name);
1670
0
        (*stream) << b.size;
1671
0
        (*stream) << int(b.members.size());
1672
0
        for (const QShaderDescription::BlockVariable &v : b.members)
1673
0
            serializeBlockMemberVar(stream, v);
1674
0
    }
1675
1676
0
    (*stream) << int(storageBlocks.size());
1677
0
    for (const QShaderDescription::StorageBlock &b : std::as_const(storageBlocks)) {
1678
0
        (*stream) << QString::fromUtf8(b.blockName);
1679
0
        (*stream) << QString::fromUtf8(b.instanceName);
1680
0
        (*stream) << b.knownSize;
1681
0
        (*stream) << b.binding;
1682
0
        (*stream) << b.descriptorSet;
1683
0
        (*stream) << int(b.members.size());
1684
0
        for (const QShaderDescription::BlockVariable &v : b.members)
1685
0
            serializeBlockMemberVar(stream, v);
1686
0
        if (version > QShaderPrivate::QSB_VERSION_WITHOUT_EXTENDED_STORAGE_BUFFER_INFO) {
1687
0
            (*stream) << b.runtimeArrayStride;
1688
0
            (*stream) << b.qualifierFlags;
1689
0
        }
1690
0
    }
1691
1692
0
    (*stream) << int(combinedImageSamplers.size());
1693
0
    for (const QShaderDescription::InOutVariable &v : std::as_const(combinedImageSamplers)) {
1694
0
        (*stream) << QString::fromUtf8(v.name);
1695
0
        (*stream) << int(v.type);
1696
0
        serializeDecorations(stream, v, version);
1697
0
    }
1698
1699
0
    (*stream) << int(storageImages.size());
1700
0
    for (const QShaderDescription::InOutVariable &v : std::as_const(storageImages)) {
1701
0
        (*stream) << QString::fromUtf8(v.name);
1702
0
        (*stream) << int(v.type);
1703
0
        serializeDecorations(stream, v, version);
1704
0
    }
1705
1706
0
    for (size_t i = 0; i < 3; ++i)
1707
0
        (*stream) << quint32(localSize[i]);
1708
1709
0
    (*stream) << int(separateImages.size());
1710
0
    for (const QShaderDescription::InOutVariable &v : std::as_const(separateImages)) {
1711
0
        (*stream) << QString::fromUtf8(v.name);
1712
0
        (*stream) << int(v.type);
1713
0
        serializeDecorations(stream, v, version);
1714
0
    }
1715
1716
0
    (*stream) << int(separateSamplers.size());
1717
0
    for (const QShaderDescription::InOutVariable &v : std::as_const(separateSamplers)) {
1718
0
        (*stream) << QString::fromUtf8(v.name);
1719
0
        (*stream) << int(v.type);
1720
0
        serializeDecorations(stream, v, version);
1721
0
    }
1722
1723
0
    if (version > QShaderPrivate::QSB_VERSION_WITHOUT_NATIVE_SHADER_INFO) {
1724
0
        (*stream) << quint32(tessOutVertCount);
1725
0
        (*stream) << quint32(tessMode);
1726
0
        (*stream) << quint32(tessWind);
1727
0
        (*stream) << quint32(tessPart);
1728
1729
0
        (*stream) << int(inBuiltins.size());
1730
0
        for (const QShaderDescription::BuiltinVariable &v : std::as_const(inBuiltins))
1731
0
            serializeBuiltinVar(stream, v, version);
1732
1733
0
        (*stream) << int(outBuiltins.size());
1734
0
        for (const QShaderDescription::BuiltinVariable &v : std::as_const(outBuiltins))
1735
0
            serializeBuiltinVar(stream, v, version);
1736
0
    }
1737
0
}
1738
1739
static void deserializeDecorations(QDataStream *stream, int version, QShaderDescription::InOutVariable *v)
1740
0
{
1741
0
    (*stream) >> v->location;
1742
0
    (*stream) >> v->binding;
1743
0
    (*stream) >> v->descriptorSet;
1744
0
    int f;
1745
0
    (*stream) >> f;
1746
0
    v->imageFormat = QShaderDescription::ImageFormat(f);
1747
0
    (*stream) >> f;
1748
0
    v->imageFlags = QShaderDescription::ImageFlags(f);
1749
1750
0
    if (version > QShaderPrivate::QSB_VERSION_WITHOUT_VAR_ARRAYDIMS) {
1751
0
        (*stream) >> f;
1752
0
        v->arrayDims.resize(f);
1753
0
        for (int i = 0; i < f; ++i)
1754
0
            (*stream) >> v->arrayDims[i];
1755
0
    }
1756
1757
0
    if (version > QShaderPrivate::QSB_VERSION_WITHOUT_NATIVE_SHADER_INFO) {
1758
0
        quint8 b;
1759
0
        (*stream) >> b;
1760
0
        v->perPatch = b;
1761
0
    }
1762
0
}
1763
1764
static QShaderDescription::BuiltinVariable deserializeBuiltinVar(QDataStream *stream, int version)
1765
0
{
1766
0
    QShaderDescription::BuiltinVariable var;
1767
0
    int t;
1768
0
    (*stream) >> t;
1769
0
    var.type = QShaderDescription::BuiltinType(t);
1770
0
    if (version > QShaderPrivate::QSB_VERSION_WITHOUT_INPUT_OUTPUT_INTERFACE_BLOCKS) {
1771
0
        (*stream) >> t;
1772
0
        var.varType = QShaderDescription::VariableType(t);
1773
0
        int count;
1774
0
        (*stream) >> count;
1775
0
        var.arrayDims.resize(count);
1776
0
        for (int i = 0; i < count; ++i)
1777
0
            (*stream) >> var.arrayDims[i];
1778
0
    }
1779
0
    return var;
1780
0
}
1781
1782
static QShaderDescription::BlockVariable deserializeBlockMemberVar(QDataStream *stream, int version)
1783
0
{
1784
0
    QShaderDescription::BlockVariable var;
1785
0
    QString tmp;
1786
0
    (*stream) >> tmp;
1787
0
    var.name = tmp.toUtf8();
1788
0
    int t;
1789
0
    (*stream) >> t;
1790
0
    var.type = QShaderDescription::VariableType(t);
1791
0
    (*stream) >> var.offset;
1792
0
    (*stream) >> var.size;
1793
0
    int count;
1794
0
    (*stream) >> count;
1795
0
    var.arrayDims.resize(count);
1796
0
    for (int i = 0; i < count; ++i)
1797
0
        (*stream) >> var.arrayDims[i];
1798
0
    (*stream) >> var.arrayStride;
1799
0
    (*stream) >> var.matrixStride;
1800
0
    (*stream) >> var.matrixIsRowMajor;
1801
0
    (*stream) >> count;
1802
0
    var.structMembers.resize(count);
1803
0
    for (int i = 0; i < count; ++i)
1804
0
        var.structMembers[i] = deserializeBlockMemberVar(stream, version);
1805
0
    return var;
1806
0
}
1807
1808
static QShaderDescription::InOutVariable deserializeInOutVar(QDataStream *stream, int version)
1809
0
{
1810
0
    QShaderDescription::InOutVariable var;
1811
0
    QString tmp;
1812
0
    (*stream) >> tmp;
1813
0
    var.name = tmp.toUtf8();
1814
0
    int t;
1815
0
    (*stream) >> t;
1816
0
    var.type = QShaderDescription::VariableType(t);
1817
0
    deserializeDecorations(stream, version, &var);
1818
0
    if (version > QShaderPrivate::QSB_VERSION_WITHOUT_INPUT_OUTPUT_INTERFACE_BLOCKS) {
1819
0
        int count;
1820
0
        (*stream) >> count;
1821
0
        var.structMembers.resize(count);
1822
0
        for (int i = 0; i < count; ++i)
1823
0
            var.structMembers[i] = deserializeBlockMemberVar(stream, version);
1824
0
    }
1825
0
    return var;
1826
0
}
1827
1828
void QShaderDescriptionPrivate::loadFromStream(QDataStream *stream, int version)
1829
0
{
1830
0
    Q_ASSERT(ref.loadRelaxed() == 1); // must be detached
1831
1832
0
    int count;
1833
0
    (*stream) >> count;
1834
0
    inVars.resize(count);
1835
0
    for (int i = 0; i < count; ++i)
1836
0
        inVars[i] = deserializeInOutVar(stream, version);
1837
1838
0
    (*stream) >> count;
1839
0
    outVars.resize(count);
1840
0
    for (int i = 0; i < count; ++i)
1841
0
        outVars[i] = deserializeInOutVar(stream, version);
1842
1843
0
    (*stream) >> count;
1844
0
    uniformBlocks.resize(count);
1845
0
    for (int i = 0; i < count; ++i) {
1846
0
        QString tmp;
1847
0
        (*stream) >> tmp;
1848
0
        uniformBlocks[i].blockName = tmp.toUtf8();
1849
0
        (*stream) >> tmp;
1850
0
        uniformBlocks[i].structName = tmp.toUtf8();
1851
0
        (*stream) >> uniformBlocks[i].size;
1852
0
        (*stream) >> uniformBlocks[i].binding;
1853
0
        (*stream) >> uniformBlocks[i].descriptorSet;
1854
0
        int memberCount;
1855
0
        (*stream) >> memberCount;
1856
0
        uniformBlocks[i].members.resize(memberCount);
1857
0
        for (int memberIdx = 0; memberIdx < memberCount; ++memberIdx)
1858
0
            uniformBlocks[i].members[memberIdx] = deserializeBlockMemberVar(stream, version);
1859
0
    }
1860
1861
0
    (*stream) >> count;
1862
0
    pushConstantBlocks.resize(count);
1863
0
    for (int i = 0; i < count; ++i) {
1864
0
        QString tmp;
1865
0
        (*stream) >> tmp;
1866
0
        pushConstantBlocks[i].name = tmp.toUtf8();
1867
0
        (*stream) >> pushConstantBlocks[i].size;
1868
0
        int memberCount;
1869
0
        (*stream) >> memberCount;
1870
0
        pushConstantBlocks[i].members.resize(memberCount);
1871
0
        for (int memberIdx = 0; memberIdx < memberCount; ++memberIdx)
1872
0
            pushConstantBlocks[i].members[memberIdx] = deserializeBlockMemberVar(stream, version);
1873
0
    }
1874
1875
0
    (*stream) >> count;
1876
0
    storageBlocks.resize(count);
1877
0
    for (int i = 0; i < count; ++i) {
1878
0
        QString tmp;
1879
0
        (*stream) >> tmp;
1880
0
        storageBlocks[i].blockName = tmp.toUtf8();
1881
0
        (*stream) >> tmp;
1882
0
        storageBlocks[i].instanceName = tmp.toUtf8();
1883
0
        (*stream) >> storageBlocks[i].knownSize;
1884
0
        (*stream) >> storageBlocks[i].binding;
1885
0
        (*stream) >> storageBlocks[i].descriptorSet;
1886
0
        int memberCount;
1887
0
        (*stream) >> memberCount;
1888
0
        storageBlocks[i].members.resize(memberCount);
1889
0
        for (int memberIdx = 0; memberIdx < memberCount; ++memberIdx)
1890
0
            storageBlocks[i].members[memberIdx] = deserializeBlockMemberVar(stream, version);
1891
1892
0
        if (version > QShaderPrivate::QSB_VERSION_WITHOUT_EXTENDED_STORAGE_BUFFER_INFO) {
1893
0
            (*stream) >> storageBlocks[i].runtimeArrayStride;
1894
0
            (*stream) >> storageBlocks[i].qualifierFlags;
1895
0
        }
1896
0
    }
1897
1898
0
    (*stream) >> count;
1899
0
    combinedImageSamplers.resize(count);
1900
0
    for (int i = 0; i < count; ++i) {
1901
0
        QString tmp;
1902
0
        (*stream) >> tmp;
1903
0
        combinedImageSamplers[i].name = tmp.toUtf8();
1904
0
        int t;
1905
0
        (*stream) >> t;
1906
0
        combinedImageSamplers[i].type = QShaderDescription::VariableType(t);
1907
0
        deserializeDecorations(stream, version, &combinedImageSamplers[i]);
1908
0
    }
1909
1910
0
    (*stream) >> count;
1911
0
    storageImages.resize(count);
1912
0
    for (int i = 0; i < count; ++i) {
1913
0
        QString tmp;
1914
0
        (*stream) >> tmp;
1915
0
        storageImages[i].name = tmp.toUtf8();
1916
0
        int t;
1917
0
        (*stream) >> t;
1918
0
        storageImages[i].type = QShaderDescription::VariableType(t);
1919
0
        deserializeDecorations(stream, version, &storageImages[i]);
1920
0
    }
1921
1922
0
    for (size_t i = 0; i < 3; ++i) {
1923
0
        quint32 v;
1924
0
        (*stream) >> v;
1925
0
        localSize[i] = v;
1926
0
    }
1927
1928
0
    if (version > QShaderPrivate::QSB_VERSION_WITHOUT_SEPARATE_IMAGES_AND_SAMPLERS) {
1929
0
        (*stream) >> count;
1930
0
        separateImages.resize(count);
1931
0
        for (int i = 0; i < count; ++i) {
1932
0
            QString tmp;
1933
0
            (*stream) >> tmp;
1934
0
            separateImages[i].name = tmp.toUtf8();
1935
0
            int t;
1936
0
            (*stream) >> t;
1937
0
            separateImages[i].type = QShaderDescription::VariableType(t);
1938
0
            deserializeDecorations(stream, version, &separateImages[i]);
1939
0
        }
1940
1941
0
        (*stream) >> count;
1942
0
        separateSamplers.resize(count);
1943
0
        for (int i = 0; i < count; ++i) {
1944
0
            QString tmp;
1945
0
            (*stream) >> tmp;
1946
0
            separateSamplers[i].name = tmp.toUtf8();
1947
0
            int t;
1948
0
            (*stream) >> t;
1949
0
            separateSamplers[i].type = QShaderDescription::VariableType(t);
1950
0
            deserializeDecorations(stream, version, &separateSamplers[i]);
1951
0
        }
1952
0
    }
1953
1954
0
    if (version > QShaderPrivate::QSB_VERSION_WITHOUT_NATIVE_SHADER_INFO) {
1955
0
        quint32 v;
1956
0
        (*stream) >> v;
1957
0
        tessOutVertCount = v;
1958
0
        (*stream) >> v;
1959
0
        tessMode = QShaderDescription::TessellationMode(v);
1960
0
        (*stream) >> v;
1961
0
        tessWind = QShaderDescription::TessellationWindingOrder(v);
1962
0
        (*stream) >> v;
1963
0
        tessPart = QShaderDescription::TessellationPartitioning(v);
1964
1965
0
        (*stream) >> count;
1966
0
        inBuiltins.resize(count);
1967
0
        for (int i = 0; i < count; ++i)
1968
0
            inBuiltins[i] = deserializeBuiltinVar(stream, version);
1969
1970
0
        (*stream) >> count;
1971
0
        outBuiltins.resize(count);
1972
0
        for (int i = 0; i < count; ++i)
1973
0
            outBuiltins[i] = deserializeBuiltinVar(stream, version);
1974
0
    }
1975
0
}
1976
1977
/*!
1978
    Returns \c true if the two QShaderDescription objects \a lhs and \a rhs are
1979
    equal.
1980
1981
    \relates QShaderDescription
1982
 */
1983
bool operator==(const QShaderDescription &lhs, const QShaderDescription &rhs) noexcept
1984
0
{
1985
0
    if (lhs.d == rhs.d)
1986
0
        return true;
1987
1988
0
    return lhs.d->inVars == rhs.d->inVars
1989
0
            && lhs.d->outVars == rhs.d->outVars
1990
0
            && lhs.d->uniformBlocks == rhs.d->uniformBlocks
1991
0
            && lhs.d->pushConstantBlocks == rhs.d->pushConstantBlocks
1992
0
            && lhs.d->storageBlocks == rhs.d->storageBlocks
1993
0
            && lhs.d->combinedImageSamplers == rhs.d->combinedImageSamplers
1994
0
            && lhs.d->separateImages == rhs.d->separateImages
1995
0
            && lhs.d->separateSamplers == rhs.d->separateSamplers
1996
0
            && lhs.d->storageImages == rhs.d->storageImages
1997
0
            && lhs.d->inBuiltins == rhs.d->inBuiltins
1998
0
            && lhs.d->outBuiltins == rhs.d->outBuiltins
1999
0
            && lhs.d->localSize == rhs.d->localSize
2000
0
            && lhs.d->tessOutVertCount == rhs.d->tessOutVertCount
2001
0
            && lhs.d->tessMode == rhs.d->tessMode
2002
0
            && lhs.d->tessWind == rhs.d->tessWind
2003
0
            && lhs.d->tessPart == rhs.d->tessPart;
2004
0
}
2005
2006
/*!
2007
    Returns \c true if the two InOutVariable objects \a lhs and \a rhs are
2008
    equal.
2009
2010
    \relates QShaderDescription::InOutVariable
2011
 */
2012
bool operator==(const QShaderDescription::InOutVariable &lhs, const QShaderDescription::InOutVariable &rhs) noexcept
2013
0
{
2014
0
    return lhs.name == rhs.name
2015
0
            && lhs.type == rhs.type
2016
0
            && lhs.location == rhs.location
2017
0
            && lhs.binding == rhs.binding
2018
0
            && lhs.descriptorSet == rhs.descriptorSet
2019
0
            && lhs.imageFormat == rhs.imageFormat
2020
0
            && lhs.imageFlags == rhs.imageFlags
2021
0
            && lhs.arrayDims == rhs.arrayDims
2022
0
            && lhs.perPatch == rhs.perPatch
2023
0
            && lhs.structMembers == rhs.structMembers;
2024
0
}
2025
2026
/*!
2027
    Returns \c true if the two BlockVariable objects \a lhs and \a rhs are
2028
    equal.
2029
2030
    \relates QShaderDescription::BlockVariable
2031
 */
2032
bool operator==(const QShaderDescription::BlockVariable &lhs, const QShaderDescription::BlockVariable &rhs) noexcept
2033
0
{
2034
0
    return lhs.name == rhs.name
2035
0
            && lhs.type == rhs.type
2036
0
            && lhs.offset == rhs.offset
2037
0
            && lhs.size == rhs.size
2038
0
            && lhs.arrayDims == rhs.arrayDims
2039
0
            && lhs.arrayStride == rhs.arrayStride
2040
0
            && lhs.matrixStride == rhs.matrixStride
2041
0
            && lhs.matrixIsRowMajor == rhs.matrixIsRowMajor
2042
0
            && lhs.structMembers == rhs.structMembers;
2043
0
}
2044
2045
/*!
2046
    Returns \c true if the two UniformBlock objects \a lhs and \a rhs are
2047
    equal.
2048
2049
    \relates QShaderDescription::UniformBlock
2050
 */
2051
bool operator==(const QShaderDescription::UniformBlock &lhs, const QShaderDescription::UniformBlock &rhs) noexcept
2052
0
{
2053
0
    return lhs.blockName == rhs.blockName
2054
0
            && lhs.structName == rhs.structName
2055
0
            && lhs.size == rhs.size
2056
0
            && lhs.binding == rhs.binding
2057
0
            && lhs.descriptorSet == rhs.descriptorSet
2058
0
            && lhs.members == rhs.members;
2059
0
}
2060
2061
/*!
2062
    Returns \c true if the two PushConstantBlock objects \a lhs and \a rhs are
2063
    equal.
2064
2065
    \relates QShaderDescription::PushConstantBlock
2066
 */
2067
bool operator==(const QShaderDescription::PushConstantBlock &lhs, const QShaderDescription::PushConstantBlock &rhs) noexcept
2068
0
{
2069
0
    return lhs.name == rhs.name
2070
0
            && lhs.size == rhs.size
2071
0
            && lhs.members == rhs.members;
2072
0
}
2073
2074
/*!
2075
    Returns \c true if the two StorageBlock objects \a lhs and \a rhs are
2076
    equal.
2077
2078
    \relates QShaderDescription::StorageBlock
2079
 */
2080
bool operator==(const QShaderDescription::StorageBlock &lhs, const QShaderDescription::StorageBlock &rhs) noexcept
2081
0
{
2082
0
    return lhs.blockName == rhs.blockName
2083
0
            && lhs.instanceName == rhs.instanceName
2084
0
            && lhs.knownSize == rhs.knownSize
2085
0
            && lhs.binding == rhs.binding
2086
0
            && lhs.descriptorSet == rhs.descriptorSet
2087
0
            && lhs.runtimeArrayStride == rhs.runtimeArrayStride
2088
0
            && lhs.qualifierFlags == rhs.qualifierFlags
2089
0
            && lhs.members == rhs.members;
2090
0
}
2091
2092
/*!
2093
    Returns \c true if the two BuiltinVariable objects \a lhs and \a rhs are
2094
    equal.
2095
2096
    \relates QShaderDescription::BuiltinVariable
2097
 */
2098
bool operator==(const QShaderDescription::BuiltinVariable &lhs, const QShaderDescription::BuiltinVariable &rhs) noexcept
2099
0
{
2100
0
    return lhs.type == rhs.type
2101
0
            && lhs.varType == rhs.varType
2102
0
            && lhs.arrayDims == rhs.arrayDims;
2103
0
}
2104
2105
QT_END_NAMESPACE