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