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