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