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