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