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