93909a30b930814a7d1390924d1f189e6c840f2b
[platform/upstream/glslang.git] / glslang / Include / Types.h
1 //
2 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
3 // Copyright (C) 2012-2016 LunarG, Inc.
4 // Copyright (C) 2015-2016 Google, Inc.
5 // Copyright (C) 2017 ARM Limited.
6 // Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
7 //
8 // All rights reserved.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions
12 // are met:
13 //
14 //    Redistributions of source code must retain the above copyright
15 //    notice, this list of conditions and the following disclaimer.
16 //
17 //    Redistributions in binary form must reproduce the above
18 //    copyright notice, this list of conditions and the following
19 //    disclaimer in the documentation and/or other materials provided
20 //    with the distribution.
21 //
22 //    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
23 //    contributors may be used to endorse or promote products derived
24 //    from this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
29 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
30 // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
31 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
32 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
33 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
34 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
36 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 // POSSIBILITY OF SUCH DAMAGE.
38 //
39
40 #ifndef _TYPES_INCLUDED
41 #define _TYPES_INCLUDED
42
43 #include "../Include/Common.h"
44 #include "../Include/BaseTypes.h"
45 #include "../Public/ShaderLang.h"
46 #include "arrays.h"
47 #include "SpirvIntrinsics.h"
48
49 #include <algorithm>
50
51 namespace glslang {
52
53 class TIntermAggregate;
54
55 const int GlslangMaxTypeLength = 200;  // TODO: need to print block/struct one member per line, so this can stay bounded
56
57 const char* const AnonymousPrefix = "anon@"; // for something like a block whose members can be directly accessed
58 inline bool IsAnonymous(const TString& name)
59 {
60     return name.compare(0, 5, AnonymousPrefix) == 0;
61 }
62
63 //
64 // Details within a sampler type
65 //
66 enum TSamplerDim {
67     EsdNone,
68     Esd1D,
69     Esd2D,
70     Esd3D,
71     EsdCube,
72     EsdRect,
73     EsdBuffer,
74     EsdSubpass,  // goes only with non-sampled image (image is true)
75     EsdNumDims
76 };
77
78 struct TSampler {   // misnomer now; includes images, textures without sampler, and textures with sampler
79     TBasicType type : 8;  // type returned by sampler
80     TSamplerDim dim : 8;
81     bool    arrayed : 1;
82     bool     shadow : 1;
83     bool         ms : 1;
84     bool      image : 1;  // image, combined should be false
85     bool   combined : 1;  // true means texture is combined with a sampler, false means texture with no sampler
86     bool    sampler : 1;  // true means a pure sampler, other fields should be clear()
87
88 #ifdef GLSLANG_WEB
89     bool is1D()          const { return false; }
90     bool isBuffer()      const { return false; }
91     bool isRect()        const { return false; }
92     bool isSubpass()     const { return false; }
93     bool isCombined()    const { return true; }
94     bool isImage()       const { return false; }
95     bool isImageClass()  const { return false; }
96     bool isMultiSample() const { return false; }
97     bool isExternal()    const { return false; }
98     void setExternal(bool e) { }
99     bool isYuv()         const { return false; }
100 #else
101     unsigned int vectorSize : 3;  // vector return type size.
102     // Some languages support structures as sample results.  Storing the whole structure in the
103     // TSampler is too large, so there is an index to a separate table.
104     static const unsigned structReturnIndexBits = 4;                        // number of index bits to use.
105     static const unsigned structReturnSlots = (1<<structReturnIndexBits)-1; // number of valid values
106     static const unsigned noReturnStruct = structReturnSlots;               // value if no return struct type.
107     // Index into a language specific table of texture return structures.
108     unsigned int structReturnIndex : structReturnIndexBits;
109
110     bool   external : 1;  // GL_OES_EGL_image_external
111     bool        yuv : 1;  // GL_EXT_YUV_target
112
113 #ifdef ENABLE_HLSL
114     unsigned int getVectorSize() const { return vectorSize; }
115     void clearReturnStruct() { structReturnIndex = noReturnStruct; }
116     bool hasReturnStruct() const { return structReturnIndex != noReturnStruct; }
117     unsigned getStructReturnIndex() const { return structReturnIndex; }
118 #endif
119
120     bool is1D()          const { return dim == Esd1D; }
121     bool is2D()          const { return dim == Esd2D; }
122     bool isBuffer()      const { return dim == EsdBuffer; }
123     bool isRect()        const { return dim == EsdRect; }
124     bool isSubpass()     const { return dim == EsdSubpass; }
125     bool isCombined()    const { return combined; }
126     bool isImage()       const { return image && !isSubpass(); }
127     bool isImageClass()  const { return image; }
128     bool isMultiSample() const { return ms; }
129     bool isExternal()    const { return external; }
130     void setExternal(bool e) { external = e; }
131     bool isYuv()         const { return yuv; }
132 #endif
133     bool isTexture()     const { return !sampler && !image; }
134     bool isPureSampler() const { return sampler; }
135
136     void setCombined(bool c) { combined = c; }
137     void setBasicType(TBasicType t) { type = t; }
138     TBasicType getBasicType()  const { return type; }
139     bool isShadow()      const { return shadow; }
140     bool isArrayed()     const { return arrayed; }
141
142     void clear()
143     {
144         type = EbtVoid;
145         dim = EsdNone;
146         arrayed = false;
147         shadow = false;
148         ms = false;
149         image = false;
150         combined = false;
151         sampler = false;
152 #ifndef GLSLANG_WEB
153         external = false;
154         yuv = false;
155 #endif
156
157 #ifdef ENABLE_HLSL
158         clearReturnStruct();
159         // by default, returns a single vec4;
160         vectorSize = 4;
161 #endif
162     }
163
164     // make a combined sampler and texture
165     void set(TBasicType t, TSamplerDim d, bool a = false, bool s = false, bool m = false)
166     {
167         clear();
168         type = t;
169         dim = d;
170         arrayed = a;
171         shadow = s;
172         ms = m;
173         combined = true;
174     }
175
176     // make an image
177     void setImage(TBasicType t, TSamplerDim d, bool a = false, bool s = false, bool m = false)
178     {
179         clear();
180         type = t;
181         dim = d;
182         arrayed = a;
183         shadow = s;
184         ms = m;
185         image = true;
186     }
187
188     // make a texture with no sampler
189     void setTexture(TBasicType t, TSamplerDim d, bool a = false, bool s = false, bool m = false)
190     {
191         clear();
192         type = t;
193         dim = d;
194         arrayed = a;
195         shadow = s;
196         ms = m;
197     }
198
199     // make a pure sampler, no texture, no image, nothing combined, the 'sampler' keyword
200     void setPureSampler(bool s)
201     {
202         clear();
203         sampler = true;
204         shadow = s;
205     }
206
207 #ifndef GLSLANG_WEB
208     // make a subpass input attachment
209     void setSubpass(TBasicType t, bool m = false)
210     {
211         clear();
212         type = t;
213         image = true;
214         dim = EsdSubpass;
215         ms = m;
216     }
217 #endif
218
219     bool operator==(const TSampler& right) const
220     {
221         return      type == right.type &&
222                      dim == right.dim &&
223                  arrayed == right.arrayed &&
224                   shadow == right.shadow &&
225          isMultiSample() == right.isMultiSample() &&
226           isImageClass() == right.isImageClass() &&
227             isCombined() == right.isCombined() &&
228          isPureSampler() == right.isPureSampler() &&
229             isExternal() == right.isExternal() &&
230                  isYuv() == right.isYuv()
231 #ifdef ENABLE_HLSL
232       && getVectorSize() == right.getVectorSize() &&
233   getStructReturnIndex() == right.getStructReturnIndex()
234 #endif
235         ;
236     }
237
238     bool operator!=(const TSampler& right) const
239     {
240         return ! operator==(right);
241     }
242
243     TString getString() const
244     {
245         TString s;
246
247         if (isPureSampler()) {
248             s.append("sampler");
249             return s;
250         }
251
252         switch (type) {
253         case EbtInt:    s.append("i");   break;
254         case EbtUint:   s.append("u");   break;
255 #ifndef GLSLANG_WEB
256         case EbtFloat16: s.append("f16"); break;
257         case EbtInt8:   s.append("i8");  break;
258         case EbtUint16: s.append("u8");  break;
259         case EbtInt16:  s.append("i16"); break;
260         case EbtUint8:  s.append("u16"); break;
261         case EbtInt64:  s.append("i64"); break;
262         case EbtUint64: s.append("u64"); break;
263 #endif
264         default:  break;
265         }
266         if (isImageClass()) {
267             if (isSubpass())
268                 s.append("subpass");
269             else
270                 s.append("image");
271         } else if (isCombined()) {
272             s.append("sampler");
273         } else {
274             s.append("texture");
275         }
276         if (isExternal()) {
277             s.append("ExternalOES");
278             return s;
279         }
280         if (isYuv()) {
281             return "__" + s + "External2DY2YEXT";
282         }
283         switch (dim) {
284         case Esd2D:      s.append("2D");      break;
285         case Esd3D:      s.append("3D");      break;
286         case EsdCube:    s.append("Cube");    break;
287 #ifndef GLSLANG_WEB
288         case Esd1D:      s.append("1D");      break;
289         case EsdRect:    s.append("2DRect");  break;
290         case EsdBuffer:  s.append("Buffer");  break;
291         case EsdSubpass: s.append("Input"); break;
292 #endif
293         default:  break;  // some compilers want this
294         }
295         if (isMultiSample())
296             s.append("MS");
297         if (arrayed)
298             s.append("Array");
299         if (shadow)
300             s.append("Shadow");
301
302         return s;
303     }
304 };
305
306 //
307 // Need to have association of line numbers to types in a list for building structs.
308 //
309 class TType;
310 struct TTypeLoc {
311     TType* type;
312     TSourceLoc loc;
313 };
314 typedef TVector<TTypeLoc> TTypeList;
315
316 typedef TVector<TString*> TIdentifierList;
317
318 //
319 // Following are a series of helper enums for managing layouts and qualifiers,
320 // used for TPublicType, TType, others.
321 //
322
323 enum TLayoutPacking {
324     ElpNone,
325     ElpShared,      // default, but different than saying nothing
326     ElpStd140,
327     ElpStd430,
328     ElpPacked,
329     ElpScalar,
330     ElpCount        // If expanding, see bitfield width below
331 };
332
333 enum TLayoutMatrix {
334     ElmNone,
335     ElmRowMajor,
336     ElmColumnMajor, // default, but different than saying nothing
337     ElmCount        // If expanding, see bitfield width below
338 };
339
340 // Union of geometry shader and tessellation shader geometry types.
341 // They don't go into TType, but rather have current state per shader or
342 // active parser type (TPublicType).
343 enum TLayoutGeometry {
344     ElgNone,
345     ElgPoints,
346     ElgLines,
347     ElgLinesAdjacency,
348     ElgLineStrip,
349     ElgTriangles,
350     ElgTrianglesAdjacency,
351     ElgTriangleStrip,
352     ElgQuads,
353     ElgIsolines,
354 };
355
356 enum TVertexSpacing {
357     EvsNone,
358     EvsEqual,
359     EvsFractionalEven,
360     EvsFractionalOdd
361 };
362
363 enum TVertexOrder {
364     EvoNone,
365     EvoCw,
366     EvoCcw
367 };
368
369 // Note: order matters, as type of format is done by comparison.
370 enum TLayoutFormat {
371     ElfNone,
372
373     // Float image
374     ElfRgba32f,
375     ElfRgba16f,
376     ElfR32f,
377     ElfRgba8,
378     ElfRgba8Snorm,
379
380     ElfEsFloatGuard,    // to help with comparisons
381
382     ElfRg32f,
383     ElfRg16f,
384     ElfR11fG11fB10f,
385     ElfR16f,
386     ElfRgba16,
387     ElfRgb10A2,
388     ElfRg16,
389     ElfRg8,
390     ElfR16,
391     ElfR8,
392     ElfRgba16Snorm,
393     ElfRg16Snorm,
394     ElfRg8Snorm,
395     ElfR16Snorm,
396     ElfR8Snorm,
397
398     ElfFloatGuard,      // to help with comparisons
399
400     // Int image
401     ElfRgba32i,
402     ElfRgba16i,
403     ElfRgba8i,
404     ElfR32i,
405
406     ElfEsIntGuard,     // to help with comparisons
407
408     ElfRg32i,
409     ElfRg16i,
410     ElfRg8i,
411     ElfR16i,
412     ElfR8i,
413     ElfR64i,
414
415     ElfIntGuard,       // to help with comparisons
416
417     // Uint image
418     ElfRgba32ui,
419     ElfRgba16ui,
420     ElfRgba8ui,
421     ElfR32ui,
422
423     ElfEsUintGuard,    // to help with comparisons
424
425     ElfRg32ui,
426     ElfRg16ui,
427     ElfRgb10a2ui,
428     ElfRg8ui,
429     ElfR16ui,
430     ElfR8ui,
431     ElfR64ui,
432
433     ElfCount
434 };
435
436 enum TLayoutDepth {
437     EldNone,
438     EldAny,
439     EldGreater,
440     EldLess,
441     EldUnchanged,
442
443     EldCount
444 };
445
446 enum TLayoutStencil {
447     ElsNone,
448     ElsRefUnchangedFrontAMD,
449     ElsRefGreaterFrontAMD,
450     ElsRefLessFrontAMD,
451     ElsRefUnchangedBackAMD,
452     ElsRefGreaterBackAMD,
453     ElsRefLessBackAMD,
454
455     ElsCount
456 };
457
458 enum TBlendEquationShift {
459     // No 'EBlendNone':
460     // These are used as bit-shift amounts.  A mask of such shifts will have type 'int',
461     // and in that space, 0 means no bits set, or none.  In this enum, 0 means (1 << 0), a bit is set.
462     EBlendMultiply,
463     EBlendScreen,
464     EBlendOverlay,
465     EBlendDarken,
466     EBlendLighten,
467     EBlendColordodge,
468     EBlendColorburn,
469     EBlendHardlight,
470     EBlendSoftlight,
471     EBlendDifference,
472     EBlendExclusion,
473     EBlendHslHue,
474     EBlendHslSaturation,
475     EBlendHslColor,
476     EBlendHslLuminosity,
477     EBlendAllEquations,
478
479     EBlendCount
480 };
481
482 enum TInterlockOrdering {
483     EioNone,
484     EioPixelInterlockOrdered,
485     EioPixelInterlockUnordered,
486     EioSampleInterlockOrdered,
487     EioSampleInterlockUnordered,
488     EioShadingRateInterlockOrdered,
489     EioShadingRateInterlockUnordered,
490
491     EioCount,
492 };
493
494 enum TShaderInterface
495 {
496     // Includes both uniform blocks and buffer blocks
497     EsiUniform = 0,
498     EsiInput,
499     EsiOutput,
500     EsiNone,
501
502     EsiCount
503 };
504
505 class TQualifier {
506 public:
507     static const int layoutNotSet = -1;
508
509     void clear()
510     {
511         precision = EpqNone;
512         invariant = false;
513         makeTemporary();
514         declaredBuiltIn = EbvNone;
515 #ifndef GLSLANG_WEB
516         noContraction = false;
517         nullInit = false;
518         spirvByReference = false;
519         spirvLiteral = false;
520 #endif
521         defaultBlock = false;
522     }
523
524     // drop qualifiers that don't belong in a temporary variable
525     void makeTemporary()
526     {
527         semanticName = nullptr;
528         storage = EvqTemporary;
529         builtIn = EbvNone;
530         clearInterstage();
531         clearMemory();
532         specConstant = false;
533         nonUniform = false;
534         nullInit = false;
535         defaultBlock = false;
536         clearLayout();
537 #ifndef GLSLANG_WEB
538         spirvStorageClass = -1;
539         spirvDecorate = nullptr;
540         spirvByReference = false;
541         spirvLiteral = false;
542 #endif
543     }
544
545     void clearInterstage()
546     {
547         clearInterpolation();
548 #ifndef GLSLANG_WEB
549         patch = false;
550         sample = false;
551 #endif
552     }
553
554     void clearInterpolation()
555     {
556         centroid     = false;
557         smooth       = false;
558         flat         = false;
559 #ifndef GLSLANG_WEB
560         nopersp      = false;
561         explicitInterp = false;
562         pervertexNV = false;
563         perPrimitiveNV = false;
564         perViewNV = false;
565         perTaskNV = false;
566 #endif
567         pervertexEXT = false;
568     }
569
570     void clearMemory()
571     {
572 #ifndef GLSLANG_WEB
573         coherent     = false;
574         devicecoherent = false;
575         queuefamilycoherent = false;
576         workgroupcoherent = false;
577         subgroupcoherent  = false;
578         shadercallcoherent = false;
579         nonprivate = false;
580         volatil      = false;
581         restrict     = false;
582         readonly     = false;
583         writeonly    = false;
584 #endif
585     }
586
587     const char*         semanticName;
588     TStorageQualifier   storage   : 6;
589     TBuiltInVariable    builtIn   : 9;
590     TBuiltInVariable    declaredBuiltIn : 9;
591     static_assert(EbvLast < 256, "need to increase size of TBuiltInVariable bitfields!");
592     TPrecisionQualifier precision : 3;
593     bool invariant    : 1; // require canonical treatment for cross-shader invariance
594     bool centroid     : 1;
595     bool smooth       : 1;
596     bool flat         : 1;
597     // having a constant_id is not sufficient: expressions have no id, but are still specConstant
598     bool specConstant : 1;
599     bool nonUniform   : 1;
600     bool explicitOffset   : 1;
601     bool defaultBlock : 1; // default blocks with matching names have structures merged when linking
602
603 #ifdef GLSLANG_WEB
604     bool isWriteOnly() const { return false; }
605     bool isReadOnly() const { return false; }
606     bool isRestrict() const { return false; }
607     bool isCoherent() const { return false; }
608     bool isVolatile() const { return false; }
609     bool isSample() const { return false; }
610     bool isMemory() const { return false; }
611     bool isMemoryQualifierImageAndSSBOOnly() const { return false; }
612     bool bufferReferenceNeedsVulkanMemoryModel() const { return false; }
613     bool isInterpolation() const { return flat || smooth; }
614     bool isExplicitInterpolation() const { return false; }
615     bool isAuxiliary() const { return centroid; }
616     bool isPatch() const { return false; }
617     bool isNoContraction() const { return false; }
618     void setNoContraction() { }
619     bool isPervertexNV() const { return false; }
620     bool isPervertexEXT() const { return pervertexEXT; }
621     void setNullInit() {}
622     bool isNullInit() const { return false; }
623     void setSpirvByReference() { }
624     bool isSpirvByReference() { return false; }
625     void setSpirvLiteral() { }
626     bool isSpirvLiteral() { return false; }
627 #else
628     bool noContraction: 1; // prevent contraction and reassociation, e.g., for 'precise' keyword, and expressions it affects
629     bool nopersp      : 1;
630     bool explicitInterp : 1;
631     bool pervertexNV  : 1;
632     bool pervertexEXT : 1;
633     bool perPrimitiveNV : 1;
634     bool perViewNV : 1;
635     bool perTaskNV : 1;
636     bool patch        : 1;
637     bool sample       : 1;
638     bool restrict     : 1;
639     bool readonly     : 1;
640     bool writeonly    : 1;
641     bool coherent     : 1;
642     bool volatil      : 1;
643     bool devicecoherent : 1;
644     bool queuefamilycoherent : 1;
645     bool workgroupcoherent : 1;
646     bool subgroupcoherent  : 1;
647     bool shadercallcoherent : 1;
648     bool nonprivate   : 1;
649     bool nullInit : 1;
650     bool spirvByReference : 1;
651     bool spirvLiteral : 1;
652     bool isWriteOnly() const { return writeonly; }
653     bool isReadOnly() const { return readonly; }
654     bool isRestrict() const { return restrict; }
655     bool isCoherent() const { return coherent; }
656     bool isVolatile() const { return volatil; }
657     bool isSample() const { return sample; }
658     bool isMemory() const
659     {
660         return shadercallcoherent || subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly || nonprivate;
661     }
662     bool isMemoryQualifierImageAndSSBOOnly() const
663     {
664         return shadercallcoherent || subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly;
665     }
666     bool bufferReferenceNeedsVulkanMemoryModel() const
667     {
668         // include qualifiers that map to load/store availability/visibility/nonprivate memory access operands
669         return subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || nonprivate;
670     }
671     bool isInterpolation() const
672     {
673         return flat || smooth || nopersp || explicitInterp;
674     }
675     bool isExplicitInterpolation() const
676     {
677         return explicitInterp;
678     }
679     bool isAuxiliary() const
680     {
681         return centroid || patch || sample || pervertexNV || pervertexEXT;
682     }
683     bool isPatch() const { return patch; }
684     bool isNoContraction() const { return noContraction; }
685     void setNoContraction() { noContraction = true; }
686     bool isPervertexNV() const { return pervertexNV; }
687     bool isPervertexEXT() const { return pervertexEXT; }
688     void setNullInit() { nullInit = true; }
689     bool isNullInit() const { return nullInit; }
690     void setSpirvByReference() { spirvByReference = true; }
691     bool isSpirvByReference() const { return spirvByReference; }
692     void setSpirvLiteral() { spirvLiteral = true; }
693     bool isSpirvLiteral() const { return spirvLiteral; }
694 #endif
695
696     bool isPipeInput() const
697     {
698         switch (storage) {
699         case EvqVaryingIn:
700         case EvqFragCoord:
701         case EvqPointCoord:
702         case EvqFace:
703         case EvqVertexId:
704         case EvqInstanceId:
705             return true;
706         default:
707             return false;
708         }
709     }
710
711     bool isPipeOutput() const
712     {
713         switch (storage) {
714         case EvqPosition:
715         case EvqPointSize:
716         case EvqClipVertex:
717         case EvqVaryingOut:
718         case EvqFragColor:
719         case EvqFragDepth:
720         case EvqFragStencil:
721             return true;
722         default:
723             return false;
724         }
725     }
726
727     bool isParamInput() const
728     {
729         switch (storage) {
730         case EvqIn:
731         case EvqInOut:
732         case EvqConstReadOnly:
733             return true;
734         default:
735             return false;
736         }
737     }
738
739     bool isParamOutput() const
740     {
741         switch (storage) {
742         case EvqOut:
743         case EvqInOut:
744             return true;
745         default:
746             return false;
747         }
748     }
749
750     bool isUniformOrBuffer() const
751     {
752         switch (storage) {
753         case EvqUniform:
754         case EvqBuffer:
755             return true;
756         default:
757             return false;
758         }
759     }
760
761     bool isUniform() const
762     {
763         switch (storage) {
764         case EvqUniform:
765             return true;
766         default:
767             return false;
768         }
769     }
770
771     bool isIo() const
772     {
773         switch (storage) {
774         case EvqUniform:
775         case EvqBuffer:
776         case EvqVaryingIn:
777         case EvqFragCoord:
778         case EvqPointCoord:
779         case EvqFace:
780         case EvqVertexId:
781         case EvqInstanceId:
782         case EvqPosition:
783         case EvqPointSize:
784         case EvqClipVertex:
785         case EvqVaryingOut:
786         case EvqFragColor:
787         case EvqFragDepth:
788         case EvqFragStencil:
789             return true;
790         default:
791             return false;
792         }
793     }
794
795     // non-built-in symbols that might link between compilation units
796     bool isLinkable() const
797     {
798         switch (storage) {
799         case EvqGlobal:
800         case EvqVaryingIn:
801         case EvqVaryingOut:
802         case EvqUniform:
803         case EvqBuffer:
804         case EvqShared:
805             return true;
806         default:
807             return false;
808         }
809     }
810
811     TBlockStorageClass getBlockStorage() const {
812         if (storage == EvqUniform && !isPushConstant()) {
813             return EbsUniform;
814         }
815         else if (storage == EvqUniform) {
816             return EbsPushConstant;
817         }
818         else if (storage == EvqBuffer) {
819             return EbsStorageBuffer;
820         }
821         return EbsNone;
822     }
823
824     void setBlockStorage(TBlockStorageClass newBacking) {
825 #ifndef GLSLANG_WEB
826         layoutPushConstant = (newBacking == EbsPushConstant);
827 #endif
828         switch (newBacking) {
829         case EbsUniform :
830             if (layoutPacking == ElpStd430) {
831                 // std430 would not be valid
832                 layoutPacking = ElpStd140;
833             }
834             storage = EvqUniform;
835             break;
836         case EbsStorageBuffer : 
837             storage = EvqBuffer;
838             break;
839 #ifndef GLSLANG_WEB
840         case EbsPushConstant :
841             storage = EvqUniform;
842             layoutSet = TQualifier::layoutSetEnd;
843             layoutBinding = TQualifier::layoutBindingEnd;
844             break;
845 #endif
846         default:
847             break;
848         }
849     }
850
851 #ifdef GLSLANG_WEB
852     bool isPerView() const { return false; }
853     bool isTaskMemory() const { return false; }
854     bool isArrayedIo(EShLanguage language) const { return false; }
855 #else
856     bool isPerPrimitive() const { return perPrimitiveNV; }
857     bool isPerView() const { return perViewNV; }
858     bool isTaskMemory() const { return perTaskNV; }
859     bool isAnyPayload() const {
860         return storage == EvqPayload || storage == EvqPayloadIn;
861     }
862     bool isAnyCallable() const {
863         return storage == EvqCallableData || storage == EvqCallableDataIn;
864     }
865
866     // True if this type of IO is supposed to be arrayed with extra level for per-vertex data
867     bool isArrayedIo(EShLanguage language) const
868     {
869         switch (language) {
870         case EShLangGeometry:
871             return isPipeInput();
872         case EShLangTessControl:
873             return ! patch && (isPipeInput() || isPipeOutput());
874         case EShLangTessEvaluation:
875             return ! patch && isPipeInput();
876         case EShLangFragment:
877             return (pervertexNV || pervertexEXT) && isPipeInput();
878         case EShLangMeshNV:
879             return ! perTaskNV && isPipeOutput();
880
881         default:
882             return false;
883         }
884     }
885 #endif
886
887     // Implementing an embedded layout-qualifier class here, since C++ can't have a real class bitfield
888     void clearLayout()  // all layout
889     {
890         clearUniformLayout();
891
892 #ifndef GLSLANG_WEB
893         layoutPushConstant = false;
894         layoutBufferReference = false;
895         layoutPassthrough = false;
896         layoutViewportRelative = false;
897         // -2048 as the default value indicating layoutSecondaryViewportRelative is not set
898         layoutSecondaryViewportRelativeOffset = -2048;
899         layoutShaderRecord = false;
900         layoutBufferReferenceAlign = layoutBufferReferenceAlignEnd;
901         layoutFormat = ElfNone;
902 #endif
903
904         clearInterstageLayout();
905
906         layoutSpecConstantId = layoutSpecConstantIdEnd;
907     }
908     void clearInterstageLayout()
909     {
910         layoutLocation = layoutLocationEnd;
911         layoutComponent = layoutComponentEnd;
912 #ifndef GLSLANG_WEB
913         layoutIndex = layoutIndexEnd;
914         clearStreamLayout();
915         clearXfbLayout();
916 #endif
917     }
918
919 #ifndef GLSLANG_WEB
920     void clearStreamLayout()
921     {
922         layoutStream = layoutStreamEnd;
923     }
924     void clearXfbLayout()
925     {
926         layoutXfbBuffer = layoutXfbBufferEnd;
927         layoutXfbStride = layoutXfbStrideEnd;
928         layoutXfbOffset = layoutXfbOffsetEnd;
929     }
930 #endif
931
932     bool hasNonXfbLayout() const
933     {
934         return hasUniformLayout() ||
935                hasAnyLocation() ||
936                hasStream() ||
937                hasFormat() ||
938                isShaderRecord() ||
939                isPushConstant() ||
940                hasBufferReference();
941     }
942     bool hasLayout() const
943     {
944         return hasNonXfbLayout() ||
945                hasXfb();
946     }
947
948     TLayoutMatrix  layoutMatrix  : 3;
949     TLayoutPacking layoutPacking : 4;
950     int layoutOffset;
951     int layoutAlign;
952
953                  unsigned int layoutLocation             : 12;
954     static const unsigned int layoutLocationEnd      =  0xFFF;
955
956                  unsigned int layoutComponent            :  3;
957     static const unsigned int layoutComponentEnd      =     4;
958
959                  unsigned int layoutSet                  :  7;
960     static const unsigned int layoutSetEnd           =   0x3F;
961
962                  unsigned int layoutBinding              : 16;
963     static const unsigned int layoutBindingEnd      =  0xFFFF;
964
965                  unsigned int layoutIndex                :  8;
966     static const unsigned int layoutIndexEnd      =      0xFF;
967
968                  unsigned int layoutStream               :  8;
969     static const unsigned int layoutStreamEnd      =     0xFF;
970
971                  unsigned int layoutXfbBuffer            :  4;
972     static const unsigned int layoutXfbBufferEnd      =   0xF;
973
974                  unsigned int layoutXfbStride            : 14;
975     static const unsigned int layoutXfbStrideEnd     = 0x3FFF;
976
977                  unsigned int layoutXfbOffset            : 13;
978     static const unsigned int layoutXfbOffsetEnd     = 0x1FFF;
979
980                  unsigned int layoutAttachment           :  8;  // for input_attachment_index
981     static const unsigned int layoutAttachmentEnd      = 0XFF;
982
983                  unsigned int layoutSpecConstantId       : 11;
984     static const unsigned int layoutSpecConstantIdEnd = 0x7FF;
985
986 #ifndef GLSLANG_WEB
987     // stored as log2 of the actual alignment value
988                  unsigned int layoutBufferReferenceAlign :  6;
989     static const unsigned int layoutBufferReferenceAlignEnd = 0x3F;
990
991     TLayoutFormat layoutFormat                           :  8;
992
993     bool layoutPushConstant;
994     bool layoutBufferReference;
995     bool layoutPassthrough;
996     bool layoutViewportRelative;
997     int layoutSecondaryViewportRelativeOffset;
998     bool layoutShaderRecord;
999
1000     // GL_EXT_spirv_intrinsics
1001     int spirvStorageClass;
1002     TSpirvDecorate* spirvDecorate;
1003 #endif
1004
1005     bool hasUniformLayout() const
1006     {
1007         return hasMatrix() ||
1008                hasPacking() ||
1009                hasOffset() ||
1010                hasBinding() ||
1011                hasSet() ||
1012                hasAlign();
1013     }
1014     void clearUniformLayout() // only uniform specific
1015     {
1016         layoutMatrix = ElmNone;
1017         layoutPacking = ElpNone;
1018         layoutOffset = layoutNotSet;
1019         layoutAlign = layoutNotSet;
1020
1021         layoutSet = layoutSetEnd;
1022         layoutBinding = layoutBindingEnd;
1023 #ifndef GLSLANG_WEB
1024         layoutAttachment = layoutAttachmentEnd;
1025 #endif
1026     }
1027
1028     bool hasMatrix() const
1029     {
1030         return layoutMatrix != ElmNone;
1031     }
1032     bool hasPacking() const
1033     {
1034         return layoutPacking != ElpNone;
1035     }
1036     bool hasAlign() const
1037     {
1038         return layoutAlign != layoutNotSet;
1039     }
1040     bool hasAnyLocation() const
1041     {
1042         return hasLocation() ||
1043                hasComponent() ||
1044                hasIndex();
1045     }
1046     bool hasLocation() const
1047     {
1048         return layoutLocation != layoutLocationEnd;
1049     }
1050     bool hasSet() const
1051     {
1052         return layoutSet != layoutSetEnd;
1053     }
1054     bool hasBinding() const
1055     {
1056         return layoutBinding != layoutBindingEnd;
1057     }
1058 #ifdef GLSLANG_WEB
1059     bool hasOffset() const { return false; }
1060     bool isNonPerspective() const { return false; }
1061     bool hasIndex() const { return false; }
1062     unsigned getIndex() const { return 0; }
1063     bool hasComponent() const { return false; }
1064     bool hasStream() const { return false; }
1065     bool hasFormat() const { return false; }
1066     bool hasXfb() const { return false; }
1067     bool hasXfbBuffer() const { return false; }
1068     bool hasXfbStride() const { return false; }
1069     bool hasXfbOffset() const { return false; }
1070     bool hasAttachment() const { return false; }
1071     TLayoutFormat getFormat() const { return ElfNone; }
1072     bool isPushConstant() const { return false; }
1073     bool isShaderRecord() const { return false; }
1074     bool hasBufferReference() const { return false; }
1075     bool hasBufferReferenceAlign() const { return false; }
1076     bool isNonUniform() const { return false; }
1077 #else
1078     bool hasOffset() const
1079     {
1080         return layoutOffset != layoutNotSet;
1081     }
1082     bool isNonPerspective() const { return nopersp; }
1083     bool hasIndex() const
1084     {
1085         return layoutIndex != layoutIndexEnd;
1086     }
1087     unsigned getIndex() const { return layoutIndex; }
1088     bool hasComponent() const
1089     {
1090         return layoutComponent != layoutComponentEnd;
1091     }
1092     bool hasStream() const
1093     {
1094         return layoutStream != layoutStreamEnd;
1095     }
1096     bool hasFormat() const
1097     {
1098         return layoutFormat != ElfNone;
1099     }
1100     bool hasXfb() const
1101     {
1102         return hasXfbBuffer() ||
1103                hasXfbStride() ||
1104                hasXfbOffset();
1105     }
1106     bool hasXfbBuffer() const
1107     {
1108         return layoutXfbBuffer != layoutXfbBufferEnd;
1109     }
1110     bool hasXfbStride() const
1111     {
1112         return layoutXfbStride != layoutXfbStrideEnd;
1113     }
1114     bool hasXfbOffset() const
1115     {
1116         return layoutXfbOffset != layoutXfbOffsetEnd;
1117     }
1118     bool hasAttachment() const
1119     {
1120         return layoutAttachment != layoutAttachmentEnd;
1121     }
1122     TLayoutFormat getFormat() const { return layoutFormat; }
1123     bool isPushConstant() const { return layoutPushConstant; }
1124     bool isShaderRecord() const { return layoutShaderRecord; }
1125     bool hasBufferReference() const { return layoutBufferReference; }
1126     bool hasBufferReferenceAlign() const
1127     {
1128         return layoutBufferReferenceAlign != layoutBufferReferenceAlignEnd;
1129     }
1130     bool isNonUniform() const
1131     {
1132         return nonUniform;
1133     }
1134
1135     // GL_EXT_spirv_intrinsics
1136     bool hasSprivDecorate() const { return spirvDecorate != nullptr; }
1137     void setSpirvDecorate(int decoration, const TIntermAggregate* args = nullptr);
1138     void setSpirvDecorateId(int decoration, const TIntermAggregate* args);
1139     void setSpirvDecorateString(int decoration, const TIntermAggregate* args);
1140     const TSpirvDecorate& getSpirvDecorate() const { assert(spirvDecorate); return *spirvDecorate; }
1141     TSpirvDecorate& getSpirvDecorate() { assert(spirvDecorate); return *spirvDecorate; }
1142     TString getSpirvDecorateQualifierString() const;
1143 #endif
1144     bool hasSpecConstantId() const
1145     {
1146         // Not the same thing as being a specialization constant, this
1147         // is just whether or not it was declared with an ID.
1148         return layoutSpecConstantId != layoutSpecConstantIdEnd;
1149     }
1150     bool isSpecConstant() const
1151     {
1152         // True if type is a specialization constant, whether or not it
1153         // had a specialization-constant ID, and false if it is not a
1154         // true front-end constant.
1155         return specConstant;
1156     }
1157     bool isFrontEndConstant() const
1158     {
1159         // True if the front-end knows the final constant value.
1160         // This allows front-end constant folding.
1161         return storage == EvqConst && ! specConstant;
1162     }
1163     bool isConstant() const
1164     {
1165         // True if is either kind of constant; specialization or regular.
1166         return isFrontEndConstant() || isSpecConstant();
1167     }
1168     void makeSpecConstant()
1169     {
1170         storage = EvqConst;
1171         specConstant = true;
1172     }
1173     static const char* getLayoutPackingString(TLayoutPacking packing)
1174     {
1175         switch (packing) {
1176         case ElpStd140:   return "std140";
1177 #ifndef GLSLANG_WEB
1178         case ElpPacked:   return "packed";
1179         case ElpShared:   return "shared";
1180         case ElpStd430:   return "std430";
1181         case ElpScalar:   return "scalar";
1182 #endif
1183         default:          return "none";
1184         }
1185     }
1186     static const char* getLayoutMatrixString(TLayoutMatrix m)
1187     {
1188         switch (m) {
1189         case ElmColumnMajor: return "column_major";
1190         case ElmRowMajor:    return "row_major";
1191         default:             return "none";
1192         }
1193     }
1194 #ifdef GLSLANG_WEB
1195     static const char* getLayoutFormatString(TLayoutFormat f) { return "none"; }
1196 #else
1197     static const char* getLayoutFormatString(TLayoutFormat f)
1198     {
1199         switch (f) {
1200         case ElfRgba32f:      return "rgba32f";
1201         case ElfRgba16f:      return "rgba16f";
1202         case ElfRg32f:        return "rg32f";
1203         case ElfRg16f:        return "rg16f";
1204         case ElfR11fG11fB10f: return "r11f_g11f_b10f";
1205         case ElfR32f:         return "r32f";
1206         case ElfR16f:         return "r16f";
1207         case ElfRgba16:       return "rgba16";
1208         case ElfRgb10A2:      return "rgb10_a2";
1209         case ElfRgba8:        return "rgba8";
1210         case ElfRg16:         return "rg16";
1211         case ElfRg8:          return "rg8";
1212         case ElfR16:          return "r16";
1213         case ElfR8:           return "r8";
1214         case ElfRgba16Snorm:  return "rgba16_snorm";
1215         case ElfRgba8Snorm:   return "rgba8_snorm";
1216         case ElfRg16Snorm:    return "rg16_snorm";
1217         case ElfRg8Snorm:     return "rg8_snorm";
1218         case ElfR16Snorm:     return "r16_snorm";
1219         case ElfR8Snorm:      return "r8_snorm";
1220
1221         case ElfRgba32i:      return "rgba32i";
1222         case ElfRgba16i:      return "rgba16i";
1223         case ElfRgba8i:       return "rgba8i";
1224         case ElfRg32i:        return "rg32i";
1225         case ElfRg16i:        return "rg16i";
1226         case ElfRg8i:         return "rg8i";
1227         case ElfR32i:         return "r32i";
1228         case ElfR16i:         return "r16i";
1229         case ElfR8i:          return "r8i";
1230
1231         case ElfRgba32ui:     return "rgba32ui";
1232         case ElfRgba16ui:     return "rgba16ui";
1233         case ElfRgba8ui:      return "rgba8ui";
1234         case ElfRg32ui:       return "rg32ui";
1235         case ElfRg16ui:       return "rg16ui";
1236         case ElfRgb10a2ui:    return "rgb10_a2ui";
1237         case ElfRg8ui:        return "rg8ui";
1238         case ElfR32ui:        return "r32ui";
1239         case ElfR16ui:        return "r16ui";
1240         case ElfR8ui:         return "r8ui";
1241         case ElfR64ui:        return "r64ui";
1242         case ElfR64i:         return "r64i";
1243         default:              return "none";
1244         }
1245     }
1246     static const char* getLayoutDepthString(TLayoutDepth d)
1247     {
1248         switch (d) {
1249         case EldAny:       return "depth_any";
1250         case EldGreater:   return "depth_greater";
1251         case EldLess:      return "depth_less";
1252         case EldUnchanged: return "depth_unchanged";
1253         default:           return "none";
1254         }
1255     }
1256     static const char* getLayoutStencilString(TLayoutStencil s)
1257     {
1258         switch (s) {
1259         case ElsRefUnchangedFrontAMD: return "stencil_ref_unchanged_front_amd";
1260         case ElsRefGreaterFrontAMD:   return "stencil_ref_greater_front_amd";
1261         case ElsRefLessFrontAMD:      return "stencil_ref_less_front_amd";
1262         case ElsRefUnchangedBackAMD:  return "stencil_ref_unchanged_back_amd";
1263         case ElsRefGreaterBackAMD:    return "stencil_ref_greater_back_amd";
1264         case ElsRefLessBackAMD:       return "stencil_ref_less_back_amd";
1265         default:                      return "none";
1266         }
1267     }
1268     static const char* getBlendEquationString(TBlendEquationShift e)
1269     {
1270         switch (e) {
1271         case EBlendMultiply:      return "blend_support_multiply";
1272         case EBlendScreen:        return "blend_support_screen";
1273         case EBlendOverlay:       return "blend_support_overlay";
1274         case EBlendDarken:        return "blend_support_darken";
1275         case EBlendLighten:       return "blend_support_lighten";
1276         case EBlendColordodge:    return "blend_support_colordodge";
1277         case EBlendColorburn:     return "blend_support_colorburn";
1278         case EBlendHardlight:     return "blend_support_hardlight";
1279         case EBlendSoftlight:     return "blend_support_softlight";
1280         case EBlendDifference:    return "blend_support_difference";
1281         case EBlendExclusion:     return "blend_support_exclusion";
1282         case EBlendHslHue:        return "blend_support_hsl_hue";
1283         case EBlendHslSaturation: return "blend_support_hsl_saturation";
1284         case EBlendHslColor:      return "blend_support_hsl_color";
1285         case EBlendHslLuminosity: return "blend_support_hsl_luminosity";
1286         case EBlendAllEquations:  return "blend_support_all_equations";
1287         default:                  return "unknown";
1288         }
1289     }
1290     static const char* getGeometryString(TLayoutGeometry geometry)
1291     {
1292         switch (geometry) {
1293         case ElgPoints:             return "points";
1294         case ElgLines:              return "lines";
1295         case ElgLinesAdjacency:     return "lines_adjacency";
1296         case ElgLineStrip:          return "line_strip";
1297         case ElgTriangles:          return "triangles";
1298         case ElgTrianglesAdjacency: return "triangles_adjacency";
1299         case ElgTriangleStrip:      return "triangle_strip";
1300         case ElgQuads:              return "quads";
1301         case ElgIsolines:           return "isolines";
1302         default:                    return "none";
1303         }
1304     }
1305     static const char* getVertexSpacingString(TVertexSpacing spacing)
1306     {
1307         switch (spacing) {
1308         case EvsEqual:              return "equal_spacing";
1309         case EvsFractionalEven:     return "fractional_even_spacing";
1310         case EvsFractionalOdd:      return "fractional_odd_spacing";
1311         default:                    return "none";
1312         }
1313     }
1314     static const char* getVertexOrderString(TVertexOrder order)
1315     {
1316         switch (order) {
1317         case EvoCw:                 return "cw";
1318         case EvoCcw:                return "ccw";
1319         default:                    return "none";
1320         }
1321     }
1322     static int mapGeometryToSize(TLayoutGeometry geometry)
1323     {
1324         switch (geometry) {
1325         case ElgPoints:             return 1;
1326         case ElgLines:              return 2;
1327         case ElgLinesAdjacency:     return 4;
1328         case ElgTriangles:          return 3;
1329         case ElgTrianglesAdjacency: return 6;
1330         default:                    return 0;
1331         }
1332     }
1333     static const char* getInterlockOrderingString(TInterlockOrdering order)
1334     {
1335         switch (order) {
1336         case EioPixelInterlockOrdered:          return "pixel_interlock_ordered";
1337         case EioPixelInterlockUnordered:        return "pixel_interlock_unordered";
1338         case EioSampleInterlockOrdered:         return "sample_interlock_ordered";
1339         case EioSampleInterlockUnordered:       return "sample_interlock_unordered";
1340         case EioShadingRateInterlockOrdered:    return "shading_rate_interlock_ordered";
1341         case EioShadingRateInterlockUnordered:  return "shading_rate_interlock_unordered";
1342         default:                                return "none";
1343         }
1344     }
1345 #endif
1346 };
1347
1348 // Qualifiers that don't need to be keep per object.  They have shader scope, not object scope.
1349 // So, they will not be part of TType, TQualifier, etc.
1350 struct TShaderQualifiers {
1351     TLayoutGeometry geometry; // geometry/tessellation shader in/out primitives
1352     bool pixelCenterInteger;  // fragment shader
1353     bool originUpperLeft;     // fragment shader
1354     int invocations;
1355     int vertices;             // for tessellation "vertices", geometry & mesh "max_vertices"
1356     TVertexSpacing spacing;
1357     TVertexOrder order;
1358     bool pointMode;
1359     int localSize[3];         // compute shader
1360     bool localSizeNotDefault[3];        // compute shader
1361     int localSizeSpecId[3];   // compute shader specialization id for gl_WorkGroupSize
1362 #ifndef GLSLANG_WEB
1363     bool earlyFragmentTests;  // fragment input
1364     bool postDepthCoverage;   // fragment input
1365     bool earlyAndLateFragmentTestsAMD; //fragment input
1366     TLayoutDepth layoutDepth;
1367     TLayoutStencil layoutStencil;
1368     bool blendEquation;       // true if any blend equation was specified
1369     int numViews;             // multiview extenstions
1370     TInterlockOrdering interlockOrdering;
1371     bool layoutOverrideCoverage;        // true if layout override_coverage set
1372     bool layoutDerivativeGroupQuads;    // true if layout derivative_group_quadsNV set
1373     bool layoutDerivativeGroupLinear;   // true if layout derivative_group_linearNV set
1374     int primitives;                     // mesh shader "max_primitives"DerivativeGroupLinear;   // true if layout derivative_group_linearNV set
1375     bool layoutPrimitiveCulling;        // true if layout primitive_culling set
1376     TLayoutDepth getDepth() const { return layoutDepth; }
1377     TLayoutStencil getStencil() const { return layoutStencil; }
1378 #else
1379     TLayoutDepth getDepth() const { return EldNone; }
1380 #endif
1381
1382     void init()
1383     {
1384         geometry = ElgNone;
1385         originUpperLeft = false;
1386         pixelCenterInteger = false;
1387         invocations = TQualifier::layoutNotSet;
1388         vertices = TQualifier::layoutNotSet;
1389         spacing = EvsNone;
1390         order = EvoNone;
1391         pointMode = false;
1392         localSize[0] = 1;
1393         localSize[1] = 1;
1394         localSize[2] = 1;
1395         localSizeNotDefault[0] = false;
1396         localSizeNotDefault[1] = false;
1397         localSizeNotDefault[2] = false;
1398         localSizeSpecId[0] = TQualifier::layoutNotSet;
1399         localSizeSpecId[1] = TQualifier::layoutNotSet;
1400         localSizeSpecId[2] = TQualifier::layoutNotSet;
1401 #ifndef GLSLANG_WEB
1402         earlyFragmentTests = false;
1403         earlyAndLateFragmentTestsAMD = false;
1404         postDepthCoverage = false;
1405         layoutDepth = EldNone;
1406         layoutStencil = ElsNone;
1407         blendEquation = false;
1408         numViews = TQualifier::layoutNotSet;
1409         layoutOverrideCoverage      = false;
1410         layoutDerivativeGroupQuads  = false;
1411         layoutDerivativeGroupLinear = false;
1412         layoutPrimitiveCulling      = false;
1413         primitives                  = TQualifier::layoutNotSet;
1414         interlockOrdering = EioNone;
1415 #endif
1416     }
1417
1418 #ifdef GLSLANG_WEB
1419     bool hasBlendEquation() const { return false; }
1420 #else
1421     bool hasBlendEquation() const { return blendEquation; }
1422 #endif
1423
1424     // Merge in characteristics from the 'src' qualifier.  They can override when
1425     // set, but never erase when not set.
1426     void merge(const TShaderQualifiers& src)
1427     {
1428         if (src.geometry != ElgNone)
1429             geometry = src.geometry;
1430         if (src.pixelCenterInteger)
1431             pixelCenterInteger = src.pixelCenterInteger;
1432         if (src.originUpperLeft)
1433             originUpperLeft = src.originUpperLeft;
1434         if (src.invocations != TQualifier::layoutNotSet)
1435             invocations = src.invocations;
1436         if (src.vertices != TQualifier::layoutNotSet)
1437             vertices = src.vertices;
1438         if (src.spacing != EvsNone)
1439             spacing = src.spacing;
1440         if (src.order != EvoNone)
1441             order = src.order;
1442         if (src.pointMode)
1443             pointMode = true;
1444         for (int i = 0; i < 3; ++i) {
1445             if (src.localSize[i] > 1)
1446                 localSize[i] = src.localSize[i];
1447         }
1448         for (int i = 0; i < 3; ++i) {
1449             localSizeNotDefault[i] = src.localSizeNotDefault[i] || localSizeNotDefault[i];
1450         }
1451         for (int i = 0; i < 3; ++i) {
1452             if (src.localSizeSpecId[i] != TQualifier::layoutNotSet)
1453                 localSizeSpecId[i] = src.localSizeSpecId[i];
1454         }
1455 #ifndef GLSLANG_WEB
1456         if (src.earlyFragmentTests)
1457             earlyFragmentTests = true;
1458         if (src.earlyAndLateFragmentTestsAMD)
1459             earlyAndLateFragmentTestsAMD = true;
1460         if (src.postDepthCoverage)
1461             postDepthCoverage = true;
1462         if (src.layoutDepth)
1463             layoutDepth = src.layoutDepth;
1464         if (src.layoutStencil)
1465             layoutStencil = src.layoutStencil;
1466         if (src.blendEquation)
1467             blendEquation = src.blendEquation;
1468         if (src.numViews != TQualifier::layoutNotSet)
1469             numViews = src.numViews;
1470         if (src.layoutOverrideCoverage)
1471             layoutOverrideCoverage = src.layoutOverrideCoverage;
1472         if (src.layoutDerivativeGroupQuads)
1473             layoutDerivativeGroupQuads = src.layoutDerivativeGroupQuads;
1474         if (src.layoutDerivativeGroupLinear)
1475             layoutDerivativeGroupLinear = src.layoutDerivativeGroupLinear;
1476         if (src.primitives != TQualifier::layoutNotSet)
1477             primitives = src.primitives;
1478         if (src.interlockOrdering != EioNone)
1479             interlockOrdering = src.interlockOrdering;
1480         if (src.layoutPrimitiveCulling)
1481             layoutPrimitiveCulling = src.layoutPrimitiveCulling;
1482 #endif
1483     }
1484 };
1485
1486 //
1487 // TPublicType is just temporarily used while parsing and not quite the same
1488 // information kept per node in TType.  Due to the bison stack, it can't have
1489 // types that it thinks have non-trivial constructors.  It should
1490 // just be used while recognizing the grammar, not anything else.
1491 // Once enough is known about the situation, the proper information
1492 // moved into a TType, or the parse context, etc.
1493 //
1494 class TPublicType {
1495 public:
1496     TBasicType basicType;
1497     TSampler sampler;
1498     TQualifier qualifier;
1499     TShaderQualifiers shaderQualifiers;
1500     int vectorSize : 4;
1501     int matrixCols : 4;
1502     int matrixRows : 4;
1503     bool coopmat   : 1;
1504     TArraySizes* arraySizes;
1505     const TType* userDef;
1506     TSourceLoc loc;
1507     TArraySizes* typeParameters;
1508 #ifndef GLSLANG_WEB
1509     // SPIR-V type defined by spirv_type directive
1510     TSpirvType* spirvType;
1511 #endif
1512
1513 #ifdef GLSLANG_WEB
1514     bool isCoopmat() const { return false; }
1515 #else
1516     bool isCoopmat() const { return coopmat; }
1517 #endif
1518
1519     void initType(const TSourceLoc& l)
1520     {
1521         basicType = EbtVoid;
1522         vectorSize = 1;
1523         matrixRows = 0;
1524         matrixCols = 0;
1525         arraySizes = nullptr;
1526         userDef = nullptr;
1527         loc = l;
1528         typeParameters = nullptr;
1529         coopmat = false;
1530 #ifndef GLSLANG_WEB
1531         spirvType = nullptr;
1532 #endif
1533     }
1534
1535     void initQualifiers(bool global = false)
1536     {
1537         qualifier.clear();
1538         if (global)
1539             qualifier.storage = EvqGlobal;
1540     }
1541
1542     void init(const TSourceLoc& l, bool global = false)
1543     {
1544         initType(l);
1545         sampler.clear();
1546         initQualifiers(global);
1547         shaderQualifiers.init();
1548     }
1549
1550     void setVector(int s)
1551     {
1552         matrixRows = 0;
1553         matrixCols = 0;
1554         vectorSize = s;
1555     }
1556
1557     void setMatrix(int c, int r)
1558     {
1559         matrixRows = r;
1560         matrixCols = c;
1561         vectorSize = 0;
1562     }
1563
1564     bool isScalar() const
1565     {
1566         return matrixCols == 0 && vectorSize == 1 && arraySizes == nullptr && userDef == nullptr;
1567     }
1568
1569 #ifndef GLSLANG_WEB
1570     // GL_EXT_spirv_intrinsics
1571     void setSpirvType(const TSpirvInstruction& spirvInst, const TSpirvTypeParameters* typeParams = nullptr);
1572 #endif
1573
1574     // "Image" is a superset of "Subpass"
1575     bool isImage()   const { return basicType == EbtSampler && sampler.isImage(); }
1576     bool isSubpass() const { return basicType == EbtSampler && sampler.isSubpass(); }
1577 };
1578
1579 //
1580 // Base class for things that have a type.
1581 //
1582 class TType {
1583 public:
1584     POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
1585
1586     // for "empty" type (no args) or simple scalar/vector/matrix
1587     explicit TType(TBasicType t = EbtVoid, TStorageQualifier q = EvqTemporary, int vs = 1, int mc = 0, int mr = 0,
1588                    bool isVector = false) :
1589                             basicType(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), vector1(isVector && vs == 1), coopmat(false),
1590                             arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(nullptr)
1591 #ifndef GLSLANG_WEB
1592                             , spirvType(nullptr)
1593 #endif
1594                             {
1595                                 sampler.clear();
1596                                 qualifier.clear();
1597                                 qualifier.storage = q;
1598                                 assert(!(isMatrix() && vectorSize != 0));  // prevent vectorSize != 0 on matrices
1599                             }
1600     // for explicit precision qualifier
1601     TType(TBasicType t, TStorageQualifier q, TPrecisionQualifier p, int vs = 1, int mc = 0, int mr = 0,
1602           bool isVector = false) :
1603                             basicType(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), vector1(isVector && vs == 1), coopmat(false),
1604                             arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(nullptr)
1605 #ifndef GLSLANG_WEB
1606                             , spirvType(nullptr)
1607 #endif
1608                             {
1609                                 sampler.clear();
1610                                 qualifier.clear();
1611                                 qualifier.storage = q;
1612                                 qualifier.precision = p;
1613                                 assert(p >= EpqNone && p <= EpqHigh);
1614                                 assert(!(isMatrix() && vectorSize != 0));  // prevent vectorSize != 0 on matrices
1615                             }
1616     // for turning a TPublicType into a TType, using a shallow copy
1617     explicit TType(const TPublicType& p) :
1618                             basicType(p.basicType),
1619                             vectorSize(p.vectorSize), matrixCols(p.matrixCols), matrixRows(p.matrixRows), vector1(false), coopmat(p.coopmat),
1620                             arraySizes(p.arraySizes), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(p.typeParameters)
1621 #ifndef GLSLANG_WEB
1622                             , spirvType(p.spirvType)
1623 #endif
1624                             {
1625                                 if (basicType == EbtSampler)
1626                                     sampler = p.sampler;
1627                                 else
1628                                     sampler.clear();
1629                                 qualifier = p.qualifier;
1630                                 if (p.userDef) {
1631                                     if (p.userDef->basicType == EbtReference) {
1632                                         basicType = EbtReference;
1633                                         referentType = p.userDef->referentType;
1634                                     } else {
1635                                         structure = p.userDef->getWritableStruct();  // public type is short-lived; there are no sharing issues
1636                                     }
1637                                     typeName = NewPoolTString(p.userDef->getTypeName().c_str());
1638                                 }
1639                                 if (p.isCoopmat() && p.typeParameters && p.typeParameters->getNumDims() > 0) {
1640                                     int numBits = p.typeParameters->getDimSize(0);
1641                                     if (p.basicType == EbtFloat && numBits == 16) {
1642                                         basicType = EbtFloat16;
1643                                         qualifier.precision = EpqNone;
1644                                     } else if (p.basicType == EbtUint && numBits == 8) {
1645                                         basicType = EbtUint8;
1646                                         qualifier.precision = EpqNone;
1647                                     } else if (p.basicType == EbtInt && numBits == 8) {
1648                                         basicType = EbtInt8;
1649                                         qualifier.precision = EpqNone;
1650                                     }
1651                                 }
1652                             }
1653     // for construction of sampler types
1654     TType(const TSampler& sampler, TStorageQualifier q = EvqUniform, TArraySizes* as = nullptr) :
1655         basicType(EbtSampler), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), coopmat(false),
1656         arraySizes(as), structure(nullptr), fieldName(nullptr), typeName(nullptr),
1657         sampler(sampler), typeParameters(nullptr)
1658 #ifndef GLSLANG_WEB
1659         , spirvType(nullptr)
1660 #endif
1661     {
1662         qualifier.clear();
1663         qualifier.storage = q;
1664     }
1665     // to efficiently make a dereferenced type
1666     // without ever duplicating the outer structure that will be thrown away
1667     // and using only shallow copy
1668     TType(const TType& type, int derefIndex, bool rowMajor = false)
1669                             {
1670                                 if (type.isArray()) {
1671                                     shallowCopy(type);
1672                                     if (type.getArraySizes()->getNumDims() == 1) {
1673                                         arraySizes = nullptr;
1674                                     } else {
1675                                         // want our own copy of the array, so we can edit it
1676                                         arraySizes = new TArraySizes;
1677                                         arraySizes->copyDereferenced(*type.arraySizes);
1678                                     }
1679                                 } else if (type.basicType == EbtStruct || type.basicType == EbtBlock) {
1680                                     // do a structure dereference
1681                                     const TTypeList& memberList = *type.getStruct();
1682                                     shallowCopy(*memberList[derefIndex].type);
1683                                     return;
1684                                 } else {
1685                                     // do a vector/matrix dereference
1686                                     shallowCopy(type);
1687                                     if (matrixCols > 0) {
1688                                         // dereference from matrix to vector
1689                                         if (rowMajor)
1690                                             vectorSize = matrixCols;
1691                                         else
1692                                             vectorSize = matrixRows;
1693                                         matrixCols = 0;
1694                                         matrixRows = 0;
1695                                         if (vectorSize == 1)
1696                                             vector1 = true;
1697                                     } else if (isVector()) {
1698                                         // dereference from vector to scalar
1699                                         vectorSize = 1;
1700                                         vector1 = false;
1701                                     } else if (isCoopMat()) {
1702                                         coopmat = false;
1703                                         typeParameters = nullptr;
1704                                     }
1705                                 }
1706                             }
1707     // for making structures, ...
1708     TType(TTypeList* userDef, const TString& n) :
1709                             basicType(EbtStruct), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), coopmat(false),
1710                             arraySizes(nullptr), structure(userDef), fieldName(nullptr), typeParameters(nullptr)
1711 #ifndef GLSLANG_WEB
1712                             , spirvType(nullptr)
1713 #endif
1714                             {
1715                                 sampler.clear();
1716                                 qualifier.clear();
1717                                 typeName = NewPoolTString(n.c_str());
1718                             }
1719     // For interface blocks
1720     TType(TTypeList* userDef, const TString& n, const TQualifier& q) :
1721                             basicType(EbtBlock), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), coopmat(false),
1722                             qualifier(q), arraySizes(nullptr), structure(userDef), fieldName(nullptr), typeParameters(nullptr)
1723 #ifndef GLSLANG_WEB
1724                             , spirvType(nullptr)
1725 #endif
1726                             {
1727                                 sampler.clear();
1728                                 typeName = NewPoolTString(n.c_str());
1729                             }
1730     // for block reference (first parameter must be EbtReference)
1731     explicit TType(TBasicType t, const TType &p, const TString& n) :
1732                             basicType(t), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false),
1733                             arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr)
1734 #ifndef GLSLANG_WEB
1735                             , spirvType(nullptr)
1736 #endif
1737                             {
1738                                 assert(t == EbtReference);
1739                                 typeName = NewPoolTString(n.c_str());
1740                                 qualifier.clear();
1741                                 qualifier.storage = p.qualifier.storage;
1742                                 referentType = p.clone();
1743                             }
1744     virtual ~TType() {}
1745
1746     // Not for use across pool pops; it will cause multiple instances of TType to point to the same information.
1747     // This only works if that information (like a structure's list of types) does not change and
1748     // the instances are sharing the same pool.
1749     void shallowCopy(const TType& copyOf)
1750     {
1751         basicType = copyOf.basicType;
1752         sampler = copyOf.sampler;
1753         qualifier = copyOf.qualifier;
1754         vectorSize = copyOf.vectorSize;
1755         matrixCols = copyOf.matrixCols;
1756         matrixRows = copyOf.matrixRows;
1757         vector1 = copyOf.vector1;
1758         arraySizes = copyOf.arraySizes;  // copying the pointer only, not the contents
1759         fieldName = copyOf.fieldName;
1760         typeName = copyOf.typeName;
1761         if (isStruct()) {
1762             structure = copyOf.structure;
1763         } else {
1764             referentType = copyOf.referentType;
1765         }
1766         typeParameters = copyOf.typeParameters;
1767 #ifndef GLSLANG_WEB
1768         spirvType = copyOf.spirvType;
1769 #endif
1770         coopmat = copyOf.isCoopMat();
1771     }
1772
1773     // Make complete copy of the whole type graph rooted at 'copyOf'.
1774     void deepCopy(const TType& copyOf)
1775     {
1776         TMap<TTypeList*,TTypeList*> copied;  // to enable copying a type graph as a graph, not a tree
1777         deepCopy(copyOf, copied);
1778     }
1779
1780     // Recursively make temporary
1781     void makeTemporary()
1782     {
1783         getQualifier().makeTemporary();
1784
1785         if (isStruct())
1786             for (unsigned int i = 0; i < structure->size(); ++i)
1787                 (*structure)[i].type->makeTemporary();
1788     }
1789
1790     TType* clone() const
1791     {
1792         TType *newType = new TType();
1793         newType->deepCopy(*this);
1794
1795         return newType;
1796     }
1797
1798     void makeVector() { vector1 = true; }
1799
1800     virtual void hideMember() { basicType = EbtVoid; vectorSize = 1; }
1801     virtual bool hiddenMember() const { return basicType == EbtVoid; }
1802
1803     virtual void setFieldName(const TString& n) { fieldName = NewPoolTString(n.c_str()); }
1804     virtual const TString& getTypeName() const
1805     {
1806         assert(typeName);
1807         return *typeName;
1808     }
1809
1810     virtual const TString& getFieldName() const
1811     {
1812         assert(fieldName);
1813         return *fieldName;
1814     }
1815     TShaderInterface getShaderInterface() const
1816     {
1817         if (basicType != EbtBlock)
1818             return EsiNone;
1819
1820         switch (qualifier.storage) {
1821         default:
1822             return EsiNone;
1823         case EvqVaryingIn:
1824             return EsiInput;
1825         case EvqVaryingOut:
1826             return EsiOutput;
1827         case EvqUniform:
1828         case EvqBuffer:
1829             return EsiUniform;
1830         }
1831     }
1832
1833     virtual TBasicType getBasicType() const { return basicType; }
1834     virtual const TSampler& getSampler() const { return sampler; }
1835     virtual TSampler& getSampler() { return sampler; }
1836
1837     virtual       TQualifier& getQualifier()       { return qualifier; }
1838     virtual const TQualifier& getQualifier() const { return qualifier; }
1839
1840     virtual int getVectorSize() const { return vectorSize; }  // returns 1 for either scalar or vector of size 1, valid for both
1841     virtual int getMatrixCols() const { return matrixCols; }
1842     virtual int getMatrixRows() const { return matrixRows; }
1843     virtual int getOuterArraySize()  const { return arraySizes->getOuterSize(); }
1844     virtual TIntermTyped*  getOuterArrayNode() const { return arraySizes->getOuterNode(); }
1845     virtual int getCumulativeArraySize()  const { return arraySizes->getCumulativeSize(); }
1846 #ifdef GLSLANG_WEB
1847     bool isArrayOfArrays() const { return false; }
1848 #else
1849     bool isArrayOfArrays() const { return arraySizes != nullptr && arraySizes->getNumDims() > 1; }
1850 #endif
1851     virtual int getImplicitArraySize() const { return arraySizes->getImplicitSize(); }
1852     virtual const TArraySizes* getArraySizes() const { return arraySizes; }
1853     virtual       TArraySizes* getArraySizes()       { return arraySizes; }
1854     virtual TType* getReferentType() const { return referentType; }
1855     virtual const TArraySizes* getTypeParameters() const { return typeParameters; }
1856     virtual       TArraySizes* getTypeParameters()       { return typeParameters; }
1857
1858     virtual bool isScalar() const { return ! isVector() && ! isMatrix() && ! isStruct() && ! isArray(); }
1859     virtual bool isScalarOrVec1() const { return isScalar() || vector1; }
1860     virtual bool isScalarOrVector() const { return !isMatrix() && !isStruct() && !isArray(); }
1861     virtual bool isVector() const { return vectorSize > 1 || vector1; }
1862     virtual bool isMatrix() const { return matrixCols ? true : false; }
1863     virtual bool isArray()  const { return arraySizes != nullptr; }
1864     virtual bool isSizedArray() const { return isArray() && arraySizes->isSized(); }
1865     virtual bool isUnsizedArray() const { return isArray() && !arraySizes->isSized(); }
1866     virtual bool isArrayVariablyIndexed() const { assert(isArray()); return arraySizes->isVariablyIndexed(); }
1867     virtual void setArrayVariablyIndexed() { assert(isArray()); arraySizes->setVariablyIndexed(); }
1868     virtual void updateImplicitArraySize(int size) { assert(isArray()); arraySizes->updateImplicitSize(size); }
1869     virtual bool isStruct() const { return basicType == EbtStruct || basicType == EbtBlock; }
1870     virtual bool isFloatingDomain() const { return basicType == EbtFloat || basicType == EbtDouble || basicType == EbtFloat16; }
1871     virtual bool isIntegerDomain() const
1872     {
1873         switch (basicType) {
1874         case EbtInt8:
1875         case EbtUint8:
1876         case EbtInt16:
1877         case EbtUint16:
1878         case EbtInt:
1879         case EbtUint:
1880         case EbtInt64:
1881         case EbtUint64:
1882         case EbtAtomicUint:
1883             return true;
1884         default:
1885             break;
1886         }
1887         return false;
1888     }
1889     virtual bool isOpaque() const { return basicType == EbtSampler
1890 #ifndef GLSLANG_WEB
1891             || basicType == EbtAtomicUint || basicType == EbtAccStruct || basicType == EbtRayQuery
1892 #endif
1893         ; }
1894     virtual bool isBuiltIn() const { return getQualifier().builtIn != EbvNone; }
1895
1896     // "Image" is a superset of "Subpass"
1897     virtual bool isImage()   const { return basicType == EbtSampler && getSampler().isImage(); }
1898     virtual bool isSubpass() const { return basicType == EbtSampler && getSampler().isSubpass(); }
1899     virtual bool isTexture() const { return basicType == EbtSampler && getSampler().isTexture(); }
1900     // Check the block-name convention of creating a block without populating it's members:
1901     virtual bool isUnusableName() const { return isStruct() && structure == nullptr; }
1902     virtual bool isParameterized()  const { return typeParameters != nullptr; }
1903 #ifdef GLSLANG_WEB
1904     bool isAtomic() const { return false; }
1905     bool isCoopMat() const { return false; }
1906     bool isReference() const { return false; }
1907     bool isSpirvType() const { return false; }
1908 #else
1909     bool isAtomic() const { return basicType == EbtAtomicUint; }
1910     bool isCoopMat() const { return coopmat; }
1911     bool isReference() const { return getBasicType() == EbtReference; }
1912     bool isSpirvType() const { return getBasicType() == EbtSpirvType; }
1913 #endif
1914
1915     // return true if this type contains any subtype which satisfies the given predicate.
1916     template <typename P>
1917     bool contains(P predicate) const
1918     {
1919         if (predicate(this))
1920             return true;
1921
1922         const auto hasa = [predicate](const TTypeLoc& tl) { return tl.type->contains(predicate); };
1923
1924         return isStruct() && std::any_of(structure->begin(), structure->end(), hasa);
1925     }
1926
1927     // Recursively checks if the type contains the given basic type
1928     virtual bool containsBasicType(TBasicType checkType) const
1929     {
1930         return contains([checkType](const TType* t) { return t->basicType == checkType; } );
1931     }
1932
1933     // Recursively check the structure for any arrays, needed for some error checks
1934     virtual bool containsArray() const
1935     {
1936         return contains([](const TType* t) { return t->isArray(); } );
1937     }
1938
1939     // Check the structure for any structures, needed for some error checks
1940     virtual bool containsStructure() const
1941     {
1942         return contains([this](const TType* t) { return t != this && t->isStruct(); } );
1943     }
1944
1945     // Recursively check the structure for any unsized arrays, needed for triggering a copyUp().
1946     virtual bool containsUnsizedArray() const
1947     {
1948         return contains([](const TType* t) { return t->isUnsizedArray(); } );
1949     }
1950
1951     virtual bool containsOpaque() const
1952     {
1953         return contains([](const TType* t) { return t->isOpaque(); } );
1954     }
1955
1956     // Recursively checks if the type contains a built-in variable
1957     virtual bool containsBuiltIn() const
1958     {
1959         return contains([](const TType* t) { return t->isBuiltIn(); } );
1960     }
1961
1962     virtual bool containsNonOpaque() const
1963     {
1964         const auto nonOpaque = [](const TType* t) {
1965             switch (t->basicType) {
1966             case EbtVoid:
1967             case EbtFloat:
1968             case EbtDouble:
1969             case EbtFloat16:
1970             case EbtInt8:
1971             case EbtUint8:
1972             case EbtInt16:
1973             case EbtUint16:
1974             case EbtInt:
1975             case EbtUint:
1976             case EbtInt64:
1977             case EbtUint64:
1978             case EbtBool:
1979             case EbtReference:
1980                 return true;
1981             default:
1982                 return false;
1983             }
1984         };
1985
1986         return contains(nonOpaque);
1987     }
1988
1989     virtual bool containsSpecializationSize() const
1990     {
1991         return contains([](const TType* t) { return t->isArray() && t->arraySizes->isOuterSpecialization(); } );
1992     }
1993
1994 #ifdef GLSLANG_WEB
1995     bool containsDouble() const { return false; }
1996     bool contains16BitFloat() const { return false; }
1997     bool contains64BitInt() const { return false; }
1998     bool contains16BitInt() const { return false; }
1999     bool contains8BitInt() const { return false; }
2000     bool containsCoopMat() const { return false; }
2001     bool containsReference() const { return false; }
2002 #else
2003     bool containsDouble() const
2004     {
2005         return containsBasicType(EbtDouble);
2006     }
2007     bool contains16BitFloat() const
2008     {
2009         return containsBasicType(EbtFloat16);
2010     }
2011     bool contains64BitInt() const
2012     {
2013         return containsBasicType(EbtInt64) || containsBasicType(EbtUint64);
2014     }
2015     bool contains16BitInt() const
2016     {
2017         return containsBasicType(EbtInt16) || containsBasicType(EbtUint16);
2018     }
2019     bool contains8BitInt() const
2020     {
2021         return containsBasicType(EbtInt8) || containsBasicType(EbtUint8);
2022     }
2023     bool containsCoopMat() const
2024     {
2025         return contains([](const TType* t) { return t->coopmat; } );
2026     }
2027     bool containsReference() const
2028     {
2029         return containsBasicType(EbtReference);
2030     }
2031 #endif
2032
2033     // Array editing methods.  Array descriptors can be shared across
2034     // type instances.  This allows all uses of the same array
2035     // to be updated at once.  E.g., all nodes can be explicitly sized
2036     // by tracking and correcting one implicit size.  Or, all nodes
2037     // can get the explicit size on a redeclaration that gives size.
2038     //
2039     // N.B.:  Don't share with the shared symbol tables (symbols are
2040     // marked as isReadOnly().  Such symbols with arrays that will be
2041     // edited need to copyUp() on first use, so that
2042     // A) the edits don't effect the shared symbol table, and
2043     // B) the edits are shared across all users.
2044     void updateArraySizes(const TType& type)
2045     {
2046         // For when we may already be sharing existing array descriptors,
2047         // keeping the pointers the same, just updating the contents.
2048         assert(arraySizes != nullptr);
2049         assert(type.arraySizes != nullptr);
2050         *arraySizes = *type.arraySizes;
2051     }
2052     void copyArraySizes(const TArraySizes& s)
2053     {
2054         // For setting a fresh new set of array sizes, not yet worrying about sharing.
2055         arraySizes = new TArraySizes;
2056         *arraySizes = s;
2057     }
2058     void transferArraySizes(TArraySizes* s)
2059     {
2060         // For setting an already allocated set of sizes that this type can use
2061         // (no copy made).
2062         arraySizes = s;
2063     }
2064     void clearArraySizes()
2065     {
2066         arraySizes = nullptr;
2067     }
2068
2069     // Add inner array sizes, to any existing sizes, via copy; the
2070     // sizes passed in can still be reused for other purposes.
2071     void copyArrayInnerSizes(const TArraySizes* s)
2072     {
2073         if (s != nullptr) {
2074             if (arraySizes == nullptr)
2075                 copyArraySizes(*s);
2076             else
2077                 arraySizes->addInnerSizes(*s);
2078         }
2079     }
2080     void changeOuterArraySize(int s) { arraySizes->changeOuterSize(s); }
2081
2082     // Recursively make the implicit array size the explicit array size.
2083     // Expicit arrays are compile-time or link-time sized, never run-time sized.
2084     // Sometimes, policy calls for an array to be run-time sized even if it was
2085     // never variably indexed: Don't turn a 'skipNonvariablyIndexed' array into
2086     // an explicit array.
2087     void adoptImplicitArraySizes(bool skipNonvariablyIndexed)
2088     {
2089         if (isUnsizedArray() && !(skipNonvariablyIndexed || isArrayVariablyIndexed()))
2090             changeOuterArraySize(getImplicitArraySize());
2091         // For multi-dim per-view arrays, set unsized inner dimension size to 1
2092         if (qualifier.isPerView() && arraySizes && arraySizes->isInnerUnsized())
2093             arraySizes->clearInnerUnsized();
2094         if (isStruct() && structure->size() > 0) {
2095             int lastMember = (int)structure->size() - 1;
2096             for (int i = 0; i < lastMember; ++i)
2097                 (*structure)[i].type->adoptImplicitArraySizes(false);
2098             // implement the "last member of an SSBO" policy
2099             (*structure)[lastMember].type->adoptImplicitArraySizes(getQualifier().storage == EvqBuffer);
2100         }
2101     }
2102
2103
2104     void updateTypeParameters(const TType& type)
2105     {
2106         // For when we may already be sharing existing array descriptors,
2107         // keeping the pointers the same, just updating the contents.
2108         assert(typeParameters != nullptr);
2109         assert(type.typeParameters != nullptr);
2110         *typeParameters = *type.typeParameters;
2111     }
2112     void copyTypeParameters(const TArraySizes& s)
2113     {
2114         // For setting a fresh new set of type parameters, not yet worrying about sharing.
2115         typeParameters = new TArraySizes;
2116         *typeParameters = s;
2117     }
2118     void transferTypeParameters(TArraySizes* s)
2119     {
2120         // For setting an already allocated set of sizes that this type can use
2121         // (no copy made).
2122         typeParameters = s;
2123     }
2124     void clearTypeParameters()
2125     {
2126         typeParameters = nullptr;
2127     }
2128
2129     // Add inner array sizes, to any existing sizes, via copy; the
2130     // sizes passed in can still be reused for other purposes.
2131     void copyTypeParametersInnerSizes(const TArraySizes* s)
2132     {
2133         if (s != nullptr) {
2134             if (typeParameters == nullptr)
2135                 copyTypeParameters(*s);
2136             else
2137                 typeParameters->addInnerSizes(*s);
2138         }
2139     }
2140
2141     const char* getBasicString() const
2142     {
2143         return TType::getBasicString(basicType);
2144     }
2145
2146     static const char* getBasicString(TBasicType t)
2147     {
2148         switch (t) {
2149         case EbtFloat:             return "float";
2150         case EbtInt:               return "int";
2151         case EbtUint:              return "uint";
2152         case EbtSampler:           return "sampler/image";
2153 #ifndef GLSLANG_WEB
2154         case EbtVoid:              return "void";
2155         case EbtDouble:            return "double";
2156         case EbtFloat16:           return "float16_t";
2157         case EbtInt8:              return "int8_t";
2158         case EbtUint8:             return "uint8_t";
2159         case EbtInt16:             return "int16_t";
2160         case EbtUint16:            return "uint16_t";
2161         case EbtInt64:             return "int64_t";
2162         case EbtUint64:            return "uint64_t";
2163         case EbtBool:              return "bool";
2164         case EbtAtomicUint:        return "atomic_uint";
2165         case EbtStruct:            return "structure";
2166         case EbtBlock:             return "block";
2167         case EbtAccStruct:         return "accelerationStructureNV";
2168         case EbtRayQuery:          return "rayQueryEXT";
2169         case EbtReference:         return "reference";
2170         case EbtString:            return "string";
2171         case EbtSpirvType:         return "spirv_type";
2172 #endif
2173         default:                   return "unknown type";
2174         }
2175     }
2176
2177 #ifdef GLSLANG_WEB
2178     TString getCompleteString() const { return ""; }
2179     const char* getStorageQualifierString() const { return ""; }
2180     const char* getBuiltInVariableString() const { return ""; }
2181     const char* getPrecisionQualifierString() const { return ""; }
2182     TString getBasicTypeString() const { return ""; }
2183 #else
2184     TString getCompleteString(bool syntactic = false, bool getQualifiers = true, bool getPrecision = true,
2185                               bool getType = true, TString name = "", TString structName = "") const
2186     {
2187         TString typeString;
2188
2189         const auto appendStr  = [&](const char* s)  { typeString.append(s); };
2190         const auto appendUint = [&](unsigned int u) { typeString.append(std::to_string(u).c_str()); };
2191         const auto appendInt  = [&](int i)          { typeString.append(std::to_string(i).c_str()); };
2192
2193         if (getQualifiers) {
2194           if (qualifier.hasSprivDecorate())
2195             appendStr(qualifier.getSpirvDecorateQualifierString().c_str());
2196
2197           if (qualifier.hasLayout()) {
2198             // To reduce noise, skip this if the only layout is an xfb_buffer
2199             // with no triggering xfb_offset.
2200             TQualifier noXfbBuffer = qualifier;
2201             noXfbBuffer.layoutXfbBuffer = TQualifier::layoutXfbBufferEnd;
2202             if (noXfbBuffer.hasLayout()) {
2203               appendStr("layout(");
2204               if (qualifier.hasAnyLocation()) {
2205                 appendStr(" location=");
2206                 appendUint(qualifier.layoutLocation);
2207                 if (qualifier.hasComponent()) {
2208                   appendStr(" component=");
2209                   appendUint(qualifier.layoutComponent);
2210                 }
2211                 if (qualifier.hasIndex()) {
2212                   appendStr(" index=");
2213                   appendUint(qualifier.layoutIndex);
2214                 }
2215               }
2216               if (qualifier.hasSet()) {
2217                 appendStr(" set=");
2218                 appendUint(qualifier.layoutSet);
2219               }
2220               if (qualifier.hasBinding()) {
2221                 appendStr(" binding=");
2222                 appendUint(qualifier.layoutBinding);
2223               }
2224               if (qualifier.hasStream()) {
2225                 appendStr(" stream=");
2226                 appendUint(qualifier.layoutStream);
2227               }
2228               if (qualifier.hasMatrix()) {
2229                 appendStr(" ");
2230                 appendStr(TQualifier::getLayoutMatrixString(qualifier.layoutMatrix));
2231               }
2232               if (qualifier.hasPacking()) {
2233                 appendStr(" ");
2234                 appendStr(TQualifier::getLayoutPackingString(qualifier.layoutPacking));
2235               }
2236               if (qualifier.hasOffset()) {
2237                 appendStr(" offset=");
2238                 appendInt(qualifier.layoutOffset);
2239               }
2240               if (qualifier.hasAlign()) {
2241                 appendStr(" align=");
2242                 appendInt(qualifier.layoutAlign);
2243               }
2244               if (qualifier.hasFormat()) {
2245                 appendStr(" ");
2246                 appendStr(TQualifier::getLayoutFormatString(qualifier.layoutFormat));
2247               }
2248               if (qualifier.hasXfbBuffer() && qualifier.hasXfbOffset()) {
2249                 appendStr(" xfb_buffer=");
2250                 appendUint(qualifier.layoutXfbBuffer);
2251               }
2252               if (qualifier.hasXfbOffset()) {
2253                 appendStr(" xfb_offset=");
2254                 appendUint(qualifier.layoutXfbOffset);
2255               }
2256               if (qualifier.hasXfbStride()) {
2257                 appendStr(" xfb_stride=");
2258                 appendUint(qualifier.layoutXfbStride);
2259               }
2260               if (qualifier.hasAttachment()) {
2261                 appendStr(" input_attachment_index=");
2262                 appendUint(qualifier.layoutAttachment);
2263               }
2264               if (qualifier.hasSpecConstantId()) {
2265                 appendStr(" constant_id=");
2266                 appendUint(qualifier.layoutSpecConstantId);
2267               }
2268               if (qualifier.layoutPushConstant)
2269                 appendStr(" push_constant");
2270               if (qualifier.layoutBufferReference)
2271                 appendStr(" buffer_reference");
2272               if (qualifier.hasBufferReferenceAlign()) {
2273                 appendStr(" buffer_reference_align=");
2274                 appendUint(1u << qualifier.layoutBufferReferenceAlign);
2275               }
2276
2277               if (qualifier.layoutPassthrough)
2278                 appendStr(" passthrough");
2279               if (qualifier.layoutViewportRelative)
2280                 appendStr(" layoutViewportRelative");
2281               if (qualifier.layoutSecondaryViewportRelativeOffset != -2048) {
2282                 appendStr(" layoutSecondaryViewportRelativeOffset=");
2283                 appendInt(qualifier.layoutSecondaryViewportRelativeOffset);
2284               }
2285               if (qualifier.layoutShaderRecord)
2286                 appendStr(" shaderRecordNV");
2287
2288               appendStr(")");
2289             }
2290           }
2291
2292           if (qualifier.invariant)
2293             appendStr(" invariant");
2294           if (qualifier.noContraction)
2295             appendStr(" noContraction");
2296           if (qualifier.centroid)
2297             appendStr(" centroid");
2298           if (qualifier.smooth)
2299             appendStr(" smooth");
2300           if (qualifier.flat)
2301             appendStr(" flat");
2302           if (qualifier.nopersp)
2303             appendStr(" noperspective");
2304           if (qualifier.explicitInterp)
2305             appendStr(" __explicitInterpAMD");
2306           if (qualifier.pervertexNV)
2307             appendStr(" pervertexNV");
2308           if (qualifier.pervertexEXT)
2309               appendStr(" pervertexEXT");
2310           if (qualifier.perPrimitiveNV)
2311             appendStr(" perprimitiveNV");
2312           if (qualifier.perViewNV)
2313             appendStr(" perviewNV");
2314           if (qualifier.perTaskNV)
2315             appendStr(" taskNV");
2316           if (qualifier.patch)
2317             appendStr(" patch");
2318           if (qualifier.sample)
2319             appendStr(" sample");
2320           if (qualifier.coherent)
2321             appendStr(" coherent");
2322           if (qualifier.devicecoherent)
2323             appendStr(" devicecoherent");
2324           if (qualifier.queuefamilycoherent)
2325             appendStr(" queuefamilycoherent");
2326           if (qualifier.workgroupcoherent)
2327             appendStr(" workgroupcoherent");
2328           if (qualifier.subgroupcoherent)
2329             appendStr(" subgroupcoherent");
2330           if (qualifier.shadercallcoherent)
2331             appendStr(" shadercallcoherent");
2332           if (qualifier.nonprivate)
2333             appendStr(" nonprivate");
2334           if (qualifier.volatil)
2335             appendStr(" volatile");
2336           if (qualifier.restrict)
2337             appendStr(" restrict");
2338           if (qualifier.readonly)
2339             appendStr(" readonly");
2340           if (qualifier.writeonly)
2341             appendStr(" writeonly");
2342           if (qualifier.specConstant)
2343             appendStr(" specialization-constant");
2344           if (qualifier.nonUniform)
2345             appendStr(" nonuniform");
2346           if (qualifier.isNullInit())
2347             appendStr(" null-init");
2348           if (qualifier.isSpirvByReference())
2349             appendStr(" spirv_by_reference");
2350           if (qualifier.isSpirvLiteral())
2351             appendStr(" spirv_literal");
2352           appendStr(" ");
2353           appendStr(getStorageQualifierString());
2354         }
2355         if (getType) {
2356           if (syntactic) {
2357             if (getPrecision && qualifier.precision != EpqNone) {
2358               appendStr(" ");
2359               appendStr(getPrecisionQualifierString());
2360             }
2361             if (isVector() || isMatrix()) {
2362               appendStr(" ");
2363               switch (basicType) {
2364               case EbtDouble:
2365                 appendStr("d");
2366                 break;
2367               case EbtInt:
2368                 appendStr("i");
2369                 break;
2370               case EbtUint:
2371                 appendStr("u");
2372                 break;
2373               case EbtBool:
2374                 appendStr("b");
2375                 break;
2376               case EbtFloat:
2377               default:
2378                 break;
2379               }
2380               if (isVector()) {
2381                 appendStr("vec");
2382                 appendInt(vectorSize);
2383               } else {
2384                 appendStr("mat");
2385                 appendInt(matrixCols);
2386                 appendStr("x");
2387                 appendInt(matrixRows);
2388               }
2389             } else if (isStruct() && structure) {
2390                 appendStr(" ");
2391                 appendStr(structName.c_str());
2392                 appendStr("{");
2393                 bool hasHiddenMember = true;
2394                 for (size_t i = 0; i < structure->size(); ++i) {
2395                   if (!(*structure)[i].type->hiddenMember()) {
2396                     if (!hasHiddenMember)
2397                       appendStr(", ");
2398                     typeString.append((*structure)[i].type->getCompleteString(syntactic, getQualifiers, getPrecision, getType, (*structure)[i].type->getFieldName()));
2399                     hasHiddenMember = false;
2400                   }
2401                 }
2402                 appendStr("}");
2403             } else {
2404                 appendStr(" ");
2405                 switch (basicType) {
2406                 case EbtDouble:
2407                   appendStr("double");
2408                   break;
2409                 case EbtInt:
2410                   appendStr("int");
2411                   break;
2412                 case EbtUint:
2413                   appendStr("uint");
2414                   break;
2415                 case EbtBool:
2416                   appendStr("bool");
2417                   break;
2418                 case EbtFloat:
2419                   appendStr("float");
2420                   break;
2421                 default:
2422                   appendStr("unexpected");
2423                   break;
2424                 }
2425             }
2426             if (name.length() > 0) {
2427               appendStr(" ");
2428               appendStr(name.c_str());
2429             }
2430             if (isArray()) {
2431               for (int i = 0; i < (int)arraySizes->getNumDims(); ++i) {
2432                 int size = arraySizes->getDimSize(i);
2433                 if (size == UnsizedArraySize && i == 0 && arraySizes->isVariablyIndexed())
2434                   appendStr("[]");
2435                 else {
2436                   if (size == UnsizedArraySize) {
2437                     appendStr("[");
2438                     if (i == 0)
2439                       appendInt(arraySizes->getImplicitSize());
2440                     appendStr("]");
2441                   }
2442                   else {
2443                     appendStr("[");
2444                     appendInt(arraySizes->getDimSize(i));
2445                     appendStr("]");
2446                   }
2447                 }
2448               }
2449             }
2450           }
2451           else {
2452             if (isArray()) {
2453               for (int i = 0; i < (int)arraySizes->getNumDims(); ++i) {
2454                 int size = arraySizes->getDimSize(i);
2455                 if (size == UnsizedArraySize && i == 0 && arraySizes->isVariablyIndexed())
2456                   appendStr(" runtime-sized array of");
2457                 else {
2458                   if (size == UnsizedArraySize) {
2459                     appendStr(" unsized");
2460                     if (i == 0) {
2461                       appendStr(" ");
2462                       appendInt(arraySizes->getImplicitSize());
2463                     }
2464                   }
2465                   else {
2466                     appendStr(" ");
2467                     appendInt(arraySizes->getDimSize(i));
2468                   }
2469                   appendStr("-element array of");
2470                 }
2471               }
2472             }
2473             if (isParameterized()) {
2474               appendStr("<");
2475               for (int i = 0; i < (int)typeParameters->getNumDims(); ++i) {
2476                 appendInt(typeParameters->getDimSize(i));
2477                 if (i != (int)typeParameters->getNumDims() - 1)
2478                   appendStr(", ");
2479               }
2480               appendStr(">");
2481             }
2482             if (getPrecision && qualifier.precision != EpqNone) {
2483               appendStr(" ");
2484               appendStr(getPrecisionQualifierString());
2485             }
2486             if (isMatrix()) {
2487               appendStr(" ");
2488               appendInt(matrixCols);
2489               appendStr("X");
2490               appendInt(matrixRows);
2491               appendStr(" matrix of");
2492             }
2493             else if (isVector()) {
2494               appendStr(" ");
2495               appendInt(vectorSize);
2496               appendStr("-component vector of");
2497             }
2498
2499             appendStr(" ");
2500             typeString.append(getBasicTypeString());
2501
2502             if (qualifier.builtIn != EbvNone) {
2503               appendStr(" ");
2504               appendStr(getBuiltInVariableString());
2505             }
2506
2507             // Add struct/block members
2508             if (isStruct() && structure) {
2509               appendStr("{");
2510               bool hasHiddenMember = true;
2511               for (size_t i = 0; i < structure->size(); ++i) {
2512                 if (!(*structure)[i].type->hiddenMember()) {
2513                   if (!hasHiddenMember)
2514                     appendStr(", ");
2515                   typeString.append((*structure)[i].type->getCompleteString());
2516                   typeString.append(" ");
2517                   typeString.append((*structure)[i].type->getFieldName());
2518                   hasHiddenMember = false;
2519                 }
2520               }
2521               appendStr("}");
2522             }
2523           }
2524         }
2525
2526         return typeString;
2527     }
2528
2529     TString getBasicTypeString() const
2530     {
2531         if (basicType == EbtSampler)
2532             return sampler.getString();
2533         else
2534             return getBasicString();
2535     }
2536
2537     const char* getStorageQualifierString() const { return GetStorageQualifierString(qualifier.storage); }
2538     const char* getBuiltInVariableString() const { return GetBuiltInVariableString(qualifier.builtIn); }
2539     const char* getPrecisionQualifierString() const { return GetPrecisionQualifierString(qualifier.precision); }
2540 #endif
2541
2542     const TTypeList* getStruct() const { assert(isStruct()); return structure; }
2543     void setStruct(TTypeList* s) { assert(isStruct()); structure = s; }
2544     TTypeList* getWritableStruct() const { assert(isStruct()); return structure; }  // This should only be used when known to not be sharing with other threads
2545     void setBasicType(const TBasicType& t) { basicType = t; }
2546     
2547     int computeNumComponents() const
2548     {
2549         int components = 0;
2550
2551         if (getBasicType() == EbtStruct || getBasicType() == EbtBlock) {
2552             for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); tl++)
2553                 components += ((*tl).type)->computeNumComponents();
2554         } else if (matrixCols)
2555             components = matrixCols * matrixRows;
2556         else
2557             components = vectorSize;
2558
2559         if (arraySizes != nullptr) {
2560             components *= arraySizes->getCumulativeSize();
2561         }
2562
2563         return components;
2564     }
2565
2566     // append this type's mangled name to the passed in 'name'
2567     void appendMangledName(TString& name) const
2568     {
2569         buildMangledName(name);
2570         name += ';' ;
2571     }
2572
2573     // These variables are inconsistently declared inside and outside of gl_PerVertex in glslang right now.
2574     // They are declared inside of 'in gl_PerVertex', but sitting as standalone when they are 'out'puts.
2575     bool isInconsistentGLPerVertexMember(const TString& name) const
2576     {
2577         if (name == "gl_SecondaryPositionNV" ||
2578             name == "gl_PositionPerViewNV")
2579             return true;
2580         return false;
2581     }
2582
2583
2584     // Do two structure types match?  They could be declared independently,
2585     // in different places, but still might satisfy the definition of matching.
2586     // From the spec:
2587     //
2588     // "Structures must have the same name, sequence of type names, and
2589     //  type definitions, and member names to be considered the same type.
2590     //  This rule applies recursively for nested or embedded types."
2591     //
2592     // If type mismatch in structure, return member indices through lpidx and rpidx.
2593     // If matching members for either block are exhausted, return -1 for exhausted
2594     // block and the index of the unmatched member. Otherwise return {-1,-1}.
2595     //
2596     bool sameStructType(const TType& right, int* lpidx = nullptr, int* rpidx = nullptr) const
2597     {
2598         // Initialize error to general type mismatch.
2599         if (lpidx != nullptr) {
2600             *lpidx = -1;
2601             *rpidx = -1;
2602         }
2603
2604         // Most commonly, they are both nullptr, or the same pointer to the same actual structure
2605         // TODO: Why return true when neither types are structures?
2606         if ((!isStruct() && !right.isStruct()) ||
2607             (isStruct() && right.isStruct() && structure == right.structure))
2608             return true;
2609
2610         if (!isStruct() || !right.isStruct())
2611             return false;
2612
2613         // Structure names have to match
2614         if (*typeName != *right.typeName)
2615             return false;
2616
2617         // There are inconsistencies with how gl_PerVertex is setup. For now ignore those as errors if they
2618         // are known inconsistencies.
2619         bool isGLPerVertex = *typeName == "gl_PerVertex";
2620
2621         // Both being nullptr was caught above, now they both have to be structures of the same number of elements
2622         if (lpidx == nullptr &&
2623             (structure->size() != right.structure->size() && !isGLPerVertex)) {
2624             return false;
2625         }
2626
2627         // Compare the names and types of all the members, which have to match
2628         for (size_t li = 0, ri = 0; li < structure->size() || ri < right.structure->size(); ++li, ++ri) {
2629             if (lpidx != nullptr) {
2630                 *lpidx = static_cast<int>(li);
2631                 *rpidx = static_cast<int>(ri);
2632             }
2633             if (li < structure->size() && ri < right.structure->size()) {
2634                 if ((*structure)[li].type->getFieldName() == (*right.structure)[ri].type->getFieldName()) {
2635                     if (*(*structure)[li].type != *(*right.structure)[ri].type)
2636                         return false;
2637                 } else {
2638                     // Skip hidden members
2639                     if ((*structure)[li].type->hiddenMember()) {
2640                         ri--;
2641                         continue;
2642                     } else if ((*right.structure)[ri].type->hiddenMember()) {
2643                         li--;
2644                         continue;
2645                     }
2646                     // If one of the members is something that's inconsistently declared, skip over it
2647                     // for now.
2648                     if (isGLPerVertex) {
2649                         if (isInconsistentGLPerVertexMember((*structure)[li].type->getFieldName())) {
2650                             ri--;
2651                             continue;
2652                         } else if (isInconsistentGLPerVertexMember((*right.structure)[ri].type->getFieldName())) {
2653                             li--;
2654                             continue;
2655                         }
2656                     } else {
2657                         return false;
2658                     }
2659                 }
2660             // If we get here, then there should only be inconsistently declared members left
2661             } else if (li < structure->size()) {
2662                 if (!(*structure)[li].type->hiddenMember() && !isInconsistentGLPerVertexMember((*structure)[li].type->getFieldName())) {
2663                     if (lpidx != nullptr) {
2664                         *rpidx = -1;
2665                     }
2666                     return false;
2667                 }
2668             } else {
2669                 if (!(*right.structure)[ri].type->hiddenMember() && !isInconsistentGLPerVertexMember((*right.structure)[ri].type->getFieldName())) {
2670                     if (lpidx != nullptr) {
2671                         *lpidx = -1;
2672                     }
2673                     return false;
2674                 }
2675             }
2676         }
2677
2678         return true;
2679     }
2680
2681      bool sameReferenceType(const TType& right) const
2682     {
2683         if (isReference() != right.isReference())
2684             return false;
2685
2686         if (!isReference() && !right.isReference())
2687             return true;
2688
2689         assert(referentType != nullptr);
2690         assert(right.referentType != nullptr);
2691
2692         if (referentType == right.referentType)
2693             return true;
2694
2695         return *referentType == *right.referentType;
2696     }
2697
2698     // See if two types match, in all aspects except arrayness
2699     // If mismatch in structure members, return member indices in lpidx and rpidx.
2700     bool sameElementType(const TType& right, int* lpidx = nullptr, int* rpidx = nullptr) const
2701     {
2702         if (lpidx != nullptr) {
2703             *lpidx = -1;
2704             *rpidx = -1;
2705         }
2706         return basicType == right.basicType && sameElementShape(right, lpidx, rpidx);
2707     }
2708
2709     // See if two type's arrayness match
2710     bool sameArrayness(const TType& right) const
2711     {
2712         return ((arraySizes == nullptr && right.arraySizes == nullptr) ||
2713                 (arraySizes != nullptr && right.arraySizes != nullptr && *arraySizes == *right.arraySizes));
2714     }
2715
2716     // See if two type's arrayness match in everything except their outer dimension
2717     bool sameInnerArrayness(const TType& right) const
2718     {
2719         assert(arraySizes != nullptr && right.arraySizes != nullptr);
2720         return arraySizes->sameInnerArrayness(*right.arraySizes);
2721     }
2722
2723     // See if two type's parameters match
2724     bool sameTypeParameters(const TType& right) const
2725     {
2726         return ((typeParameters == nullptr && right.typeParameters == nullptr) ||
2727                 (typeParameters != nullptr && right.typeParameters != nullptr && *typeParameters == *right.typeParameters));
2728     }
2729
2730 #ifndef GLSLANG_WEB
2731     // See if two type's SPIR-V type contents match
2732     bool sameSpirvType(const TType& right) const
2733     {
2734         return ((spirvType == nullptr && right.spirvType == nullptr) ||
2735                 (spirvType != nullptr && right.spirvType != nullptr && *spirvType == *right.spirvType));
2736     }
2737 #endif
2738
2739     // See if two type's elements match in all ways except basic type
2740     // If mismatch in structure members, return member indices in lpidx and rpidx.
2741     bool sameElementShape(const TType& right, int* lpidx = nullptr, int* rpidx = nullptr) const
2742     {
2743         if (lpidx != nullptr) {
2744             *lpidx = -1;
2745             *rpidx = -1;
2746         }
2747         return ((basicType != EbtSampler && right.basicType != EbtSampler) || sampler == right.sampler) &&
2748                vectorSize == right.vectorSize &&
2749                matrixCols == right.matrixCols &&
2750                matrixRows == right.matrixRows &&
2751                   vector1 == right.vector1    &&
2752               isCoopMat() == right.isCoopMat() &&
2753                sameStructType(right, lpidx, rpidx) &&
2754                sameReferenceType(right);
2755     }
2756
2757     // See if a cooperative matrix type parameter with unspecified parameters is
2758     // an OK function parameter
2759     bool coopMatParameterOK(const TType& right) const
2760     {
2761         return isCoopMat() && right.isCoopMat() && (getBasicType() == right.getBasicType()) &&
2762                typeParameters == nullptr && right.typeParameters != nullptr;
2763     }
2764
2765     bool sameCoopMatBaseType(const TType &right) const {
2766         bool rv = coopmat && right.coopmat;
2767         if (getBasicType() == EbtFloat || getBasicType() == EbtFloat16)
2768             rv = right.getBasicType() == EbtFloat || right.getBasicType() == EbtFloat16;
2769         else if (getBasicType() == EbtUint || getBasicType() == EbtUint8)
2770             rv = right.getBasicType() == EbtUint || right.getBasicType() == EbtUint8;
2771         else if (getBasicType() == EbtInt || getBasicType() == EbtInt8)
2772             rv = right.getBasicType() == EbtInt || right.getBasicType() == EbtInt8;
2773         else
2774             rv = false;
2775         return rv;
2776     }
2777
2778
2779     // See if two types match in all ways (just the actual type, not qualification)
2780     bool operator==(const TType& right) const
2781     {
2782 #ifndef GLSLANG_WEB
2783         return sameElementType(right) && sameArrayness(right) && sameTypeParameters(right) && sameSpirvType(right);
2784 #else
2785         return sameElementType(right) && sameArrayness(right) && sameTypeParameters(right);
2786 #endif
2787     }
2788
2789     bool operator!=(const TType& right) const
2790     {
2791         return ! operator==(right);
2792     }
2793
2794     unsigned int getBufferReferenceAlignment() const
2795     {
2796 #ifndef GLSLANG_WEB
2797         if (getBasicType() == glslang::EbtReference) {
2798             return getReferentType()->getQualifier().hasBufferReferenceAlign() ?
2799                         (1u << getReferentType()->getQualifier().layoutBufferReferenceAlign) : 16u;
2800         }
2801 #endif
2802         return 0;
2803     }
2804
2805 #ifndef GLSLANG_WEB
2806     const TSpirvType& getSpirvType() const { assert(spirvType); return *spirvType; }
2807 #endif
2808
2809 protected:
2810     // Require consumer to pick between deep copy and shallow copy.
2811     TType(const TType& type);
2812     TType& operator=(const TType& type);
2813
2814     // Recursively copy a type graph, while preserving the graph-like
2815     // quality. That is, don't make more than one copy of a structure that
2816     // gets reused multiple times in the type graph.
2817     void deepCopy(const TType& copyOf, TMap<TTypeList*,TTypeList*>& copiedMap)
2818     {
2819         shallowCopy(copyOf);
2820
2821 #ifndef GLSLANG_WEB
2822         // GL_EXT_spirv_intrinsics
2823         if (copyOf.qualifier.spirvDecorate) {
2824             qualifier.spirvDecorate = new TSpirvDecorate;
2825             *qualifier.spirvDecorate = *copyOf.qualifier.spirvDecorate;
2826         }
2827
2828         if (copyOf.spirvType) {
2829             spirvType = new TSpirvType;
2830             *spirvType = *copyOf.spirvType;
2831         }
2832 #endif
2833
2834         if (copyOf.arraySizes) {
2835             arraySizes = new TArraySizes;
2836             *arraySizes = *copyOf.arraySizes;
2837         }
2838
2839         if (copyOf.typeParameters) {
2840             typeParameters = new TArraySizes;
2841             *typeParameters = *copyOf.typeParameters;
2842         }
2843
2844         if (copyOf.isStruct() && copyOf.structure) {
2845             auto prevCopy = copiedMap.find(copyOf.structure);
2846             if (prevCopy != copiedMap.end())
2847                 structure = prevCopy->second;
2848             else {
2849                 structure = new TTypeList;
2850                 copiedMap[copyOf.structure] = structure;
2851                 for (unsigned int i = 0; i < copyOf.structure->size(); ++i) {
2852                     TTypeLoc typeLoc;
2853                     typeLoc.loc = (*copyOf.structure)[i].loc;
2854                     typeLoc.type = new TType();
2855                     typeLoc.type->deepCopy(*(*copyOf.structure)[i].type, copiedMap);
2856                     structure->push_back(typeLoc);
2857                 }
2858             }
2859         }
2860
2861         if (copyOf.fieldName)
2862             fieldName = NewPoolTString(copyOf.fieldName->c_str());
2863         if (copyOf.typeName)
2864             typeName = NewPoolTString(copyOf.typeName->c_str());
2865     }
2866
2867
2868     void buildMangledName(TString&) const;
2869
2870     TBasicType basicType : 8;
2871     int vectorSize       : 4;  // 1 means either scalar or 1-component vector; see vector1 to disambiguate.
2872     int matrixCols       : 4;
2873     int matrixRows       : 4;
2874     bool vector1         : 1;  // Backward-compatible tracking of a 1-component vector distinguished from a scalar.
2875                                // GLSL 4.5 never has a 1-component vector; so this will always be false until such
2876                                // functionality is added.
2877                                // HLSL does have a 1-component vectors, so this will be true to disambiguate
2878                                // from a scalar.
2879     bool coopmat         : 1;
2880     TQualifier qualifier;
2881
2882     TArraySizes* arraySizes;    // nullptr unless an array; can be shared across types
2883     // A type can't be both a structure (EbtStruct/EbtBlock) and a reference (EbtReference), so
2884     // conserve space by making these a union
2885     union {
2886         TTypeList* structure;       // invalid unless this is a struct; can be shared across types
2887         TType *referentType;        // invalid unless this is an EbtReference
2888     };
2889     TString *fieldName;         // for structure field names
2890     TString *typeName;          // for structure type name
2891     TSampler sampler;
2892     TArraySizes* typeParameters;// nullptr unless a parameterized type; can be shared across types
2893 #ifndef GLSLANG_WEB
2894     TSpirvType* spirvType;  // SPIR-V type defined by spirv_type directive
2895 #endif
2896 };
2897
2898 } // end namespace glslang
2899
2900 #endif // _TYPES_INCLUDED_