b877c15444aa9467f489c73b5a9847ba2a0c07de
[platform/upstream/glslang.git] / glslang / Include / Types.h
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
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.
96     unsigned int getVectorSize() const { return vectorSize; }
97
98     bool isImage()       const { return image && dim != EsdSubpass; }
99     bool isSubpass()     const { return dim == EsdSubpass; }
100     bool isCombined()    const { return combined; }
101     bool isPureSampler() const { return sampler; }
102     bool isTexture()     const { return !sampler && !image; }
103     bool isShadow()      const { return shadow; }
104     bool isArrayed()     const { return arrayed; }
105     bool isMultiSample() const { return ms; }
106     bool hasReturnStruct() const { return structReturnIndex != noReturnStruct; }
107
108     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
171     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
198     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     ElpCount        // If expanding, see bitfield width below
281 };
282
283 enum TLayoutMatrix {
284     ElmNone,
285     ElmRowMajor,
286     ElmColumnMajor, // default, but different than saying nothing
287     ElmCount        // If expanding, see bitfield width below
288 };
289
290 // Union of geometry shader and tessellation shader geometry types.
291 // They don't go into TType, but rather have current state per shader or
292 // active parser type (TPublicType).
293 enum TLayoutGeometry {
294     ElgNone,
295     ElgPoints,
296     ElgLines,
297     ElgLinesAdjacency,
298     ElgLineStrip,
299     ElgTriangles,
300     ElgTrianglesAdjacency,
301     ElgTriangleStrip,
302     ElgQuads,
303     ElgIsolines,
304 };
305
306 enum TVertexSpacing {
307     EvsNone,
308     EvsEqual,
309     EvsFractionalEven,
310     EvsFractionalOdd
311 };
312
313 enum TVertexOrder {
314     EvoNone,
315     EvoCw,
316     EvoCcw
317 };
318
319 // Note: order matters, as type of format is done by comparison.
320 enum TLayoutFormat {
321     ElfNone,
322
323     // Float image
324     ElfRgba32f,
325     ElfRgba16f,
326     ElfR32f,
327     ElfRgba8,
328     ElfRgba8Snorm,
329
330     ElfEsFloatGuard,    // to help with comparisons
331
332     ElfRg32f,
333     ElfRg16f,
334     ElfR11fG11fB10f,
335     ElfR16f,
336     ElfRgba16,
337     ElfRgb10A2,
338     ElfRg16,
339     ElfRg8,
340     ElfR16,
341     ElfR8,
342     ElfRgba16Snorm,
343     ElfRg16Snorm,
344     ElfRg8Snorm,
345     ElfR16Snorm,
346     ElfR8Snorm,
347
348     ElfFloatGuard,      // to help with comparisons
349
350     // Int image
351     ElfRgba32i,
352     ElfRgba16i,
353     ElfRgba8i,
354     ElfR32i,
355
356     ElfEsIntGuard,     // to help with comparisons
357
358     ElfRg32i,
359     ElfRg16i,
360     ElfRg8i,
361     ElfR16i,
362     ElfR8i,
363
364     ElfIntGuard,       // to help with comparisons
365
366     // Uint image
367     ElfRgba32ui,
368     ElfRgba16ui,
369     ElfRgba8ui,
370     ElfR32ui,
371
372     ElfEsUintGuard,    // to help with comparisons
373
374     ElfRg32ui,
375     ElfRg16ui,
376     ElfRgb10a2ui,
377     ElfRg8ui,
378     ElfR16ui,
379     ElfR8ui,
380
381     ElfCount
382 };
383
384 enum TLayoutDepth {
385     EldNone,
386     EldAny,
387     EldGreater,
388     EldLess,
389     EldUnchanged,
390
391     EldCount
392 };
393
394 enum TBlendEquationShift {
395     // No 'EBlendNone':
396     // These are used as bit-shift amounts.  A mask of such shifts will have type 'int',
397     // and in that space, 0 means no bits set, or none.  In this enum, 0 means (1 << 0), a bit is set.
398     EBlendMultiply,
399     EBlendScreen,
400     EBlendOverlay,
401     EBlendDarken,
402     EBlendLighten,
403     EBlendColordodge,
404     EBlendColorburn,
405     EBlendHardlight,
406     EBlendSoftlight,
407     EBlendDifference,
408     EBlendExclusion,
409     EBlendHslHue,
410     EBlendHslSaturation,
411     EBlendHslColor,
412     EBlendHslLuminosity,
413     EBlendAllEquations,
414
415     EBlendCount
416 };
417
418 class TQualifier {
419 public:
420     static const int layoutNotSet = -1;
421
422     void clear()
423     {
424         precision = EpqNone;
425         invariant = false;
426         noContraction = false;
427         makeTemporary();
428         declaredBuiltIn = EbvNone;
429     }
430
431     // drop qualifiers that don't belong in a temporary variable
432     void makeTemporary()
433     {
434         semanticName = nullptr;
435         storage = EvqTemporary;
436         builtIn = EbvNone;
437         clearInterstage();
438         clearMemory();
439         specConstant = false;
440         nonUniform = false;
441         clearLayout();
442     }
443
444     void clearInterstage()
445     {
446         clearInterpolation();
447         patch = false;
448         sample = false;
449     }
450
451     void clearInterpolation()
452     {
453         centroid     = false;
454         smooth       = false;
455         flat         = false;
456         nopersp      = false;
457 #ifdef AMD_EXTENSIONS
458         explicitInterp = false;
459 #endif
460     }
461
462     void clearMemory()
463     {
464         coherent     = false;
465         volatil      = false;
466         restrict     = false;
467         readonly     = false;
468         writeonly    = false;
469     }
470
471     // Drop just the storage qualification, which perhaps should
472     // never be done, as it is fundamentally inconsistent, but need to
473     // explore what downstream consumers need.
474     // E.g., in a dereference, it is an inconsistency between:
475     // A) partially dereferenced resource is still in the storage class it started in
476     // B) partially dereferenced resource is a new temporary object
477     // If A, then nothing should change, if B, then everything should change, but this is half way.
478     void makePartialTemporary()
479     {
480         storage      = EvqTemporary;
481         specConstant = false;
482         nonUniform   = false;
483     }
484
485     const char*         semanticName;
486     TStorageQualifier   storage   : 6;
487     TBuiltInVariable    builtIn   : 8;
488     TBuiltInVariable    declaredBuiltIn : 8;
489     TPrecisionQualifier precision : 3;
490     bool invariant    : 1; // require canonical treatment for cross-shader invariance
491     bool noContraction: 1; // prevent contraction and reassociation, e.g., for 'precise' keyword, and expressions it affects
492     bool centroid     : 1;
493     bool smooth       : 1;
494     bool flat         : 1;
495     bool nopersp      : 1;
496 #ifdef AMD_EXTENSIONS
497     bool explicitInterp : 1;
498 #endif
499     bool patch        : 1;
500     bool sample       : 1;
501     bool coherent     : 1;
502     bool volatil      : 1;
503     bool restrict     : 1;
504     bool readonly     : 1;
505     bool writeonly    : 1;
506     bool specConstant : 1;  // having a constant_id is not sufficient: expressions have no id, but are still specConstant
507     bool nonUniform   : 1;
508
509     bool isMemory() const
510     {
511         return coherent || volatil || restrict || readonly || writeonly;
512     }
513     bool isInterpolation() const
514     {
515 #ifdef AMD_EXTENSIONS
516         return flat || smooth || nopersp || explicitInterp;
517 #else
518         return flat || smooth || nopersp;
519 #endif
520     }
521 #ifdef AMD_EXTENSIONS
522     bool isExplicitInterpolation() const
523     {
524         return explicitInterp;
525     }
526 #endif
527     bool isAuxiliary() const
528     {
529         return centroid || patch || sample;
530     }
531
532     bool isPipeInput() const
533     {
534         switch (storage) {
535         case EvqVaryingIn:
536         case EvqFragCoord:
537         case EvqPointCoord:
538         case EvqFace:
539         case EvqVertexId:
540         case EvqInstanceId:
541             return true;
542         default:
543             return false;
544         }
545     }
546
547     bool isPipeOutput() const
548     {
549         switch (storage) {
550         case EvqPosition:
551         case EvqPointSize:
552         case EvqClipVertex:
553         case EvqVaryingOut:
554         case EvqFragColor:
555         case EvqFragDepth:
556             return true;
557         default:
558             return false;
559         }
560     }
561
562     bool isParamInput() const
563     {
564         switch (storage) {
565         case EvqIn:
566         case EvqInOut:
567         case EvqConstReadOnly:
568             return true;
569         default:
570             return false;
571         }
572     }
573
574     bool isParamOutput() const
575     {
576         switch (storage) {
577         case EvqOut:
578         case EvqInOut:
579             return true;
580         default:
581             return false;
582         }
583     }
584
585     bool isUniformOrBuffer() const
586     {
587         switch (storage) {
588         case EvqUniform:
589         case EvqBuffer:
590             return true;
591         default:
592             return false;
593         }
594     }
595
596     bool isIo() const
597     {
598         switch (storage) {
599         case EvqUniform:
600         case EvqBuffer:
601         case EvqVaryingIn:
602         case EvqFragCoord:
603         case EvqPointCoord:
604         case EvqFace:
605         case EvqVertexId:
606         case EvqInstanceId:
607         case EvqPosition:
608         case EvqPointSize:
609         case EvqClipVertex:
610         case EvqVaryingOut:
611         case EvqFragColor:
612         case EvqFragDepth:
613             return true;
614         default:
615             return false;
616         }
617     }
618
619     // non-built-in symbols that might link between compilation units
620     bool isLinkable() const
621     {
622         switch (storage) {
623         case EvqGlobal:
624         case EvqVaryingIn:
625         case EvqVaryingOut:
626         case EvqUniform:
627         case EvqBuffer:
628         case EvqShared:
629             return true;
630         default:
631             return false;
632         }
633     }
634
635     // True if this type of IO is supposed to be arrayed with extra level for per-vertex data
636     bool isArrayedIo(EShLanguage language) const
637     {
638         switch (language) {
639         case EShLangGeometry:
640             return isPipeInput();
641         case EShLangTessControl:
642             return ! patch && (isPipeInput() || isPipeOutput());
643         case EShLangTessEvaluation:
644             return ! patch && isPipeInput();
645         default:
646             return false;
647         }
648     }
649
650     // Implementing an embedded layout-qualifier class here, since C++ can't have a real class bitfield
651     void clearLayout()  // all layout
652     {
653         clearUniformLayout();
654
655         layoutPushConstant = false;
656 #ifdef NV_EXTENSIONS
657         layoutPassthrough = false;
658         layoutViewportRelative = false;
659         // -2048 as the default value indicating layoutSecondaryViewportRelative is not set
660         layoutSecondaryViewportRelativeOffset = -2048;
661 #endif
662
663         clearInterstageLayout();
664
665         layoutSpecConstantId = layoutSpecConstantIdEnd;
666
667         layoutFormat = ElfNone;
668     }
669     void clearInterstageLayout()
670     {
671         layoutLocation = layoutLocationEnd;
672         layoutComponent = layoutComponentEnd;
673         layoutIndex = layoutIndexEnd;
674         clearStreamLayout();
675         clearXfbLayout();
676     }
677     void clearStreamLayout()
678     {
679         layoutStream = layoutStreamEnd;
680     }
681     void clearXfbLayout()
682     {
683         layoutXfbBuffer = layoutXfbBufferEnd;
684         layoutXfbStride = layoutXfbStrideEnd;
685         layoutXfbOffset = layoutXfbOffsetEnd;
686     }
687
688     bool hasNonXfbLayout() const
689     {
690         return hasUniformLayout() ||
691                hasAnyLocation() ||
692                hasStream() ||
693                hasFormat() ||
694                layoutPushConstant;
695     }
696     bool hasLayout() const
697     {
698         return hasNonXfbLayout() ||
699                hasXfb();
700     }
701     TLayoutMatrix  layoutMatrix  : 3;
702     TLayoutPacking layoutPacking : 4;
703     int layoutOffset;
704     int layoutAlign;
705
706                  unsigned int layoutLocation            :12;
707     static const unsigned int layoutLocationEnd    =  0xFFF;
708
709                  unsigned int layoutComponent           : 3;
710     static const unsigned int layoutComponentEnd    =     4;
711
712                  unsigned int layoutSet                 : 7;
713     static const unsigned int layoutSetEnd         =   0x3F;
714
715                  unsigned int layoutBinding            : 16;
716     static const unsigned int layoutBindingEnd    =  0xFFFF;
717
718                  unsigned int layoutIndex              :  8;
719     static const unsigned int layoutIndexEnd    =      0xFF;
720
721                  unsigned int layoutStream              : 8;
722     static const unsigned int layoutStreamEnd    =     0xFF;
723
724                  unsigned int layoutXfbBuffer           : 4;
725     static const unsigned int layoutXfbBufferEnd    =   0xF;
726
727                  unsigned int layoutXfbStride          : 10;
728     static const unsigned int layoutXfbStrideEnd    = 0x3FF;
729
730                  unsigned int layoutXfbOffset          : 10;
731     static const unsigned int layoutXfbOffsetEnd    = 0x3FF;
732
733                  unsigned int layoutAttachment          : 8;  // for input_attachment_index
734     static const unsigned int layoutAttachmentEnd    = 0XFF;
735
736                  unsigned int layoutSpecConstantId       : 11;
737     static const unsigned int layoutSpecConstantIdEnd = 0x7FF;
738
739     TLayoutFormat layoutFormat                         :  8;
740
741     bool layoutPushConstant;
742
743 #ifdef NV_EXTENSIONS
744     bool layoutPassthrough;
745     bool layoutViewportRelative;
746     int layoutSecondaryViewportRelativeOffset;
747 #endif
748
749     bool hasUniformLayout() const
750     {
751         return hasMatrix() ||
752                hasPacking() ||
753                hasOffset() ||
754                hasBinding() ||
755                hasSet() ||
756                hasAlign();
757     }
758     void clearUniformLayout() // only uniform specific
759     {
760         layoutMatrix = ElmNone;
761         layoutPacking = ElpNone;
762         layoutOffset = layoutNotSet;
763         layoutAlign = layoutNotSet;
764
765         layoutSet = layoutSetEnd;
766         layoutBinding = layoutBindingEnd;
767         layoutAttachment = layoutAttachmentEnd;
768     }
769
770     bool hasMatrix() const
771     {
772         return layoutMatrix != ElmNone;
773     }
774     bool hasPacking() const
775     {
776         return layoutPacking != ElpNone;
777     }
778     bool hasOffset() const
779     {
780         return layoutOffset != layoutNotSet;
781     }
782     bool hasAlign() const
783     {
784         return layoutAlign != layoutNotSet;
785     }
786     bool hasAnyLocation() const
787     {
788         return hasLocation() ||
789                hasComponent() ||
790                hasIndex();
791     }
792     bool hasLocation() const
793     {
794         return layoutLocation != layoutLocationEnd;
795     }
796     bool hasComponent() const
797     {
798         return layoutComponent != layoutComponentEnd;
799     }
800     bool hasIndex() const
801     {
802         return layoutIndex != layoutIndexEnd;
803     }
804     bool hasSet() const
805     {
806         return layoutSet != layoutSetEnd;
807     }
808     bool hasBinding() const
809     {
810         return layoutBinding != layoutBindingEnd;
811     }
812     bool hasStream() const
813     {
814         return layoutStream != layoutStreamEnd;
815     }
816     bool hasFormat() const
817     {
818         return layoutFormat != ElfNone;
819     }
820     bool hasXfb() const
821     {
822         return hasXfbBuffer() ||
823                hasXfbStride() ||
824                hasXfbOffset();
825     }
826     bool hasXfbBuffer() const
827     {
828         return layoutXfbBuffer != layoutXfbBufferEnd;
829     }
830     bool hasXfbStride() const
831     {
832         return layoutXfbStride != layoutXfbStrideEnd;
833     }
834     bool hasXfbOffset() const
835     {
836         return layoutXfbOffset != layoutXfbOffsetEnd;
837     }
838     bool hasAttachment() const
839     {
840         return layoutAttachment != layoutAttachmentEnd;
841     }
842     bool hasSpecConstantId() const
843     {
844         // Not the same thing as being a specialization constant, this
845         // is just whether or not it was declared with an ID.
846         return layoutSpecConstantId != layoutSpecConstantIdEnd;
847     }
848     bool isSpecConstant() const
849     {
850         // True if type is a specialization constant, whether or not it
851         // had a specialization-constant ID, and false if it is not a
852         // true front-end constant.
853         return specConstant;
854     }
855     bool isNonUniform() const
856     {
857         return nonUniform;
858     }
859     bool isFrontEndConstant() const
860     {
861         // True if the front-end knows the final constant value.
862         // This allows front-end constant folding.
863         return storage == EvqConst && ! specConstant;
864     }
865     bool isConstant() const
866     {
867         // True if is either kind of constant; specialization or regular.
868         return isFrontEndConstant() || isSpecConstant();
869     }
870     void makeSpecConstant()
871     {
872         storage = EvqConst;
873         specConstant = true;
874     }
875     static const char* getLayoutPackingString(TLayoutPacking packing)
876     {
877         switch (packing) {
878         case ElpPacked:   return "packed";
879         case ElpShared:   return "shared";
880         case ElpStd140:   return "std140";
881         case ElpStd430:   return "std430";
882         default:          return "none";
883         }
884     }
885     static const char* getLayoutMatrixString(TLayoutMatrix m)
886     {
887         switch (m) {
888         case ElmColumnMajor: return "column_major";
889         case ElmRowMajor:    return "row_major";
890         default:             return "none";
891         }
892     }
893     static const char* getLayoutFormatString(TLayoutFormat f)
894     {
895         switch (f) {
896         case ElfRgba32f:      return "rgba32f";
897         case ElfRgba16f:      return "rgba16f";
898         case ElfRg32f:        return "rg32f";
899         case ElfRg16f:        return "rg16f";
900         case ElfR11fG11fB10f: return "r11f_g11f_b10f";
901         case ElfR32f:         return "r32f";
902         case ElfR16f:         return "r16f";
903         case ElfRgba16:       return "rgba16";
904         case ElfRgb10A2:      return "rgb10_a2";
905         case ElfRgba8:        return "rgba8";
906         case ElfRg16:         return "rg16";
907         case ElfRg8:          return "rg8";
908         case ElfR16:          return "r16";
909         case ElfR8:           return "r8";
910         case ElfRgba16Snorm:  return "rgba16_snorm";
911         case ElfRgba8Snorm:   return "rgba8_snorm";
912         case ElfRg16Snorm:    return "rg16_snorm";
913         case ElfRg8Snorm:     return "rg8_snorm";
914         case ElfR16Snorm:     return "r16_snorm";
915         case ElfR8Snorm:      return "r8_snorm";
916
917         case ElfRgba32i:      return "rgba32i";
918         case ElfRgba16i:      return "rgba16i";
919         case ElfRgba8i:       return "rgba8i";
920         case ElfRg32i:        return "rg32i";
921         case ElfRg16i:        return "rg16i";
922         case ElfRg8i:         return "rg8i";
923         case ElfR32i:         return "r32i";
924         case ElfR16i:         return "r16i";
925         case ElfR8i:          return "r8i";
926
927         case ElfRgba32ui:     return "rgba32ui";
928         case ElfRgba16ui:     return "rgba16ui";
929         case ElfRgba8ui:      return "rgba8ui";
930         case ElfRg32ui:       return "rg32ui";
931         case ElfRg16ui:       return "rg16ui";
932         case ElfRgb10a2ui:    return "rgb10_a2ui";
933         case ElfRg8ui:        return "rg8ui";
934         case ElfR32ui:        return "r32ui";
935         case ElfR16ui:        return "r16ui";
936         case ElfR8ui:         return "r8ui";
937         default:              return "none";
938         }
939     }
940     static const char* getLayoutDepthString(TLayoutDepth d)
941     {
942         switch (d) {
943         case EldAny:       return "depth_any";
944         case EldGreater:   return "depth_greater";
945         case EldLess:      return "depth_less";
946         case EldUnchanged: return "depth_unchanged";
947         default:           return "none";
948         }
949     }
950     static const char* getBlendEquationString(TBlendEquationShift e)
951     {
952         switch (e) {
953         case EBlendMultiply:      return "blend_support_multiply";
954         case EBlendScreen:        return "blend_support_screen";
955         case EBlendOverlay:       return "blend_support_overlay";
956         case EBlendDarken:        return "blend_support_darken";
957         case EBlendLighten:       return "blend_support_lighten";
958         case EBlendColordodge:    return "blend_support_colordodge";
959         case EBlendColorburn:     return "blend_support_colorburn";
960         case EBlendHardlight:     return "blend_support_hardlight";
961         case EBlendSoftlight:     return "blend_support_softlight";
962         case EBlendDifference:    return "blend_support_difference";
963         case EBlendExclusion:     return "blend_support_exclusion";
964         case EBlendHslHue:        return "blend_support_hsl_hue";
965         case EBlendHslSaturation: return "blend_support_hsl_saturation";
966         case EBlendHslColor:      return "blend_support_hsl_color";
967         case EBlendHslLuminosity: return "blend_support_hsl_luminosity";
968         case EBlendAllEquations:  return "blend_support_all_equations";
969         default:                  return "unknown";
970         }
971     }
972     static const char* getGeometryString(TLayoutGeometry geometry)
973     {
974         switch (geometry) {
975         case ElgPoints:             return "points";
976         case ElgLines:              return "lines";
977         case ElgLinesAdjacency:     return "lines_adjacency";
978         case ElgLineStrip:          return "line_strip";
979         case ElgTriangles:          return "triangles";
980         case ElgTrianglesAdjacency: return "triangles_adjacency";
981         case ElgTriangleStrip:      return "triangle_strip";
982         case ElgQuads:              return "quads";
983         case ElgIsolines:           return "isolines";
984         default:                    return "none";
985         }
986     }
987     static const char* getVertexSpacingString(TVertexSpacing spacing)
988     {
989         switch (spacing) {
990         case EvsEqual:              return "equal_spacing";
991         case EvsFractionalEven:     return "fractional_even_spacing";
992         case EvsFractionalOdd:      return "fractional_odd_spacing";
993         default:                    return "none";
994         }
995     }
996     static const char* getVertexOrderString(TVertexOrder order)
997     {
998         switch (order) {
999         case EvoCw:                 return "cw";
1000         case EvoCcw:                return "ccw";
1001         default:                    return "none";
1002         }
1003     }
1004     static int mapGeometryToSize(TLayoutGeometry geometry)
1005     {
1006         switch (geometry) {
1007         case ElgPoints:             return 1;
1008         case ElgLines:              return 2;
1009         case ElgLinesAdjacency:     return 4;
1010         case ElgTriangles:          return 3;
1011         case ElgTrianglesAdjacency: return 6;
1012         default:                    return 0;
1013         }
1014     }
1015 };
1016
1017 // Qualifiers that don't need to be keep per object.  They have shader scope, not object scope.
1018 // So, they will not be part of TType, TQualifier, etc.
1019 struct TShaderQualifiers {
1020     TLayoutGeometry geometry; // geometry/tessellation shader in/out primitives
1021     bool pixelCenterInteger;  // fragment shader
1022     bool originUpperLeft;     // fragment shader
1023     int invocations;
1024     int vertices;             // both for tessellation "vertices" and geometry "max_vertices"
1025     TVertexSpacing spacing;
1026     TVertexOrder order;
1027     bool pointMode;
1028     int localSize[3];         // compute shader
1029     int localSizeSpecId[3];   // compute shader specialization id for gl_WorkGroupSize
1030     bool earlyFragmentTests;  // fragment input
1031     bool postDepthCoverage;   // fragment input
1032     TLayoutDepth layoutDepth;
1033     bool blendEquation;       // true if any blend equation was specified
1034     int numViews;             // multiview extenstions
1035
1036 #ifdef NV_EXTENSIONS
1037     bool layoutOverrideCoverage;    // true if layout override_coverage set
1038 #endif
1039
1040     void init()
1041     {
1042         geometry = ElgNone;
1043         originUpperLeft = false;
1044         pixelCenterInteger = false;
1045         invocations = TQualifier::layoutNotSet;
1046         vertices = TQualifier::layoutNotSet;
1047         spacing = EvsNone;
1048         order = EvoNone;
1049         pointMode = false;
1050         localSize[0] = 1;
1051         localSize[1] = 1;
1052         localSize[2] = 1;
1053         localSizeSpecId[0] = TQualifier::layoutNotSet;
1054         localSizeSpecId[1] = TQualifier::layoutNotSet;
1055         localSizeSpecId[2] = TQualifier::layoutNotSet;
1056         earlyFragmentTests = false;
1057         postDepthCoverage = false;
1058         layoutDepth = EldNone;
1059         blendEquation = false;
1060         numViews = TQualifier::layoutNotSet;
1061 #ifdef NV_EXTENSIONS
1062         layoutOverrideCoverage = false;
1063 #endif
1064     }
1065
1066     // Merge in characteristics from the 'src' qualifier.  They can override when
1067     // set, but never erase when not set.
1068     void merge(const TShaderQualifiers& src)
1069     {
1070         if (src.geometry != ElgNone)
1071             geometry = src.geometry;
1072         if (src.pixelCenterInteger)
1073             pixelCenterInteger = src.pixelCenterInteger;
1074         if (src.originUpperLeft)
1075             originUpperLeft = src.originUpperLeft;
1076         if (src.invocations != TQualifier::layoutNotSet)
1077             invocations = src.invocations;
1078         if (src.vertices != TQualifier::layoutNotSet)
1079             vertices = src.vertices;
1080         if (src.spacing != EvsNone)
1081             spacing = src.spacing;
1082         if (src.order != EvoNone)
1083             order = src.order;
1084         if (src.pointMode)
1085             pointMode = true;
1086         for (int i = 0; i < 3; ++i) {
1087             if (src.localSize[i] > 1)
1088                 localSize[i] = src.localSize[i];
1089         }
1090         for (int i = 0; i < 3; ++i) {
1091             if (src.localSizeSpecId[i] != TQualifier::layoutNotSet)
1092                 localSizeSpecId[i] = src.localSizeSpecId[i];
1093         }
1094         if (src.earlyFragmentTests)
1095             earlyFragmentTests = true;
1096         if (src.postDepthCoverage)
1097             postDepthCoverage = true;
1098         if (src.layoutDepth)
1099             layoutDepth = src.layoutDepth;
1100         if (src.blendEquation)
1101             blendEquation = src.blendEquation;
1102         if (src.numViews != TQualifier::layoutNotSet)
1103             numViews = src.numViews;
1104 #ifdef NV_EXTENSIONS
1105         if (src.layoutOverrideCoverage)
1106             layoutOverrideCoverage = src.layoutOverrideCoverage;
1107 #endif
1108     }
1109 };
1110
1111 //
1112 // TPublicType is just temporarily used while parsing and not quite the same
1113 // information kept per node in TType.  Due to the bison stack, it can't have
1114 // types that it thinks have non-trivial constructors.  It should
1115 // just be used while recognizing the grammar, not anything else.
1116 // Once enough is known about the situation, the proper information
1117 // moved into a TType, or the parse context, etc.
1118 //
1119 class TPublicType {
1120 public:
1121     TBasicType basicType;
1122     TSampler sampler;
1123     TQualifier qualifier;
1124     TShaderQualifiers shaderQualifiers;
1125     int vectorSize : 4;
1126     int matrixCols : 4;
1127     int matrixRows : 4;
1128     TArraySizes* arraySizes;
1129     const TType* userDef;
1130     TSourceLoc loc;
1131
1132     void initType(const TSourceLoc& l)
1133     {
1134         basicType = EbtVoid;
1135         vectorSize = 1;
1136         matrixRows = 0;
1137         matrixCols = 0;
1138         arraySizes = nullptr;
1139         userDef = nullptr;
1140         loc = l;
1141     }
1142
1143     void initQualifiers(bool global = false)
1144     {
1145         qualifier.clear();
1146         if (global)
1147             qualifier.storage = EvqGlobal;
1148     }
1149
1150     void init(const TSourceLoc& l, bool global = false)
1151     {
1152         initType(l);
1153         sampler.clear();
1154         initQualifiers(global);
1155         shaderQualifiers.init();
1156     }
1157
1158     void setVector(int s)
1159     {
1160         matrixRows = 0;
1161         matrixCols = 0;
1162         vectorSize = s;
1163     }
1164
1165     void setMatrix(int c, int r)
1166     {
1167         matrixRows = r;
1168         matrixCols = c;
1169         vectorSize = 0;
1170     }
1171
1172     bool isScalar() const
1173     {
1174         return matrixCols == 0 && vectorSize == 1 && arraySizes == nullptr && userDef == nullptr;
1175     }
1176
1177     // "Image" is a superset of "Subpass"
1178     bool isImage()   const { return basicType == EbtSampler && sampler.isImage(); }
1179     bool isSubpass() const { return basicType == EbtSampler && sampler.isSubpass(); }
1180 };
1181
1182 //
1183 // Base class for things that have a type.
1184 //
1185 class TType {
1186 public:
1187     POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
1188
1189     // for "empty" type (no args) or simple scalar/vector/matrix
1190     explicit TType(TBasicType t = EbtVoid, TStorageQualifier q = EvqTemporary, int vs = 1, int mc = 0, int mr = 0,
1191                    bool isVector = false) :
1192                             basicType(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), vector1(isVector && vs == 1),
1193                             arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr)
1194                             {
1195                                 sampler.clear();
1196                                 qualifier.clear();
1197                                 qualifier.storage = q;
1198                                 assert(!(isMatrix() && vectorSize != 0));  // prevent vectorSize != 0 on matrices
1199                             }
1200     // for explicit precision qualifier
1201     TType(TBasicType t, TStorageQualifier q, TPrecisionQualifier p, int vs = 1, int mc = 0, int mr = 0,
1202           bool isVector = false) :
1203                             basicType(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), vector1(isVector && vs == 1),
1204                             arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr)
1205                             {
1206                                 sampler.clear();
1207                                 qualifier.clear();
1208                                 qualifier.storage = q;
1209                                 qualifier.precision = p;
1210                                 assert(p >= EpqNone && p <= EpqHigh);
1211                                 assert(!(isMatrix() && vectorSize != 0));  // prevent vectorSize != 0 on matrices
1212                             }
1213     // for turning a TPublicType into a TType, using a shallow copy
1214     explicit TType(const TPublicType& p) :
1215                             basicType(p.basicType),
1216                             vectorSize(p.vectorSize), matrixCols(p.matrixCols), matrixRows(p.matrixRows), vector1(false),
1217                             arraySizes(p.arraySizes), structure(nullptr), fieldName(nullptr), typeName(nullptr)
1218                             {
1219                                 if (basicType == EbtSampler)
1220                                     sampler = p.sampler;
1221                                 else
1222                                     sampler.clear();
1223                                 qualifier = p.qualifier;
1224                                 if (p.userDef) {
1225                                     structure = p.userDef->getWritableStruct();  // public type is short-lived; there are no sharing issues
1226                                     typeName = NewPoolTString(p.userDef->getTypeName().c_str());
1227                                 }
1228                             }
1229     // for construction of sampler types
1230     TType(const TSampler& sampler, TStorageQualifier q = EvqUniform, TArraySizes* as = nullptr) :
1231         basicType(EbtSampler), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false),
1232         arraySizes(as), structure(nullptr), fieldName(nullptr), typeName(nullptr),
1233         sampler(sampler)
1234     {
1235         qualifier.clear();
1236         qualifier.storage = q;
1237     }
1238     // to efficiently make a dereferenced type
1239     // without ever duplicating the outer structure that will be thrown away
1240     // and using only shallow copy
1241     TType(const TType& type, int derefIndex, bool rowMajor = false)
1242                             {
1243                                 if (type.isArray()) {
1244                                     shallowCopy(type);
1245                                     if (type.getArraySizes()->getNumDims() == 1) {
1246                                         arraySizes = nullptr;
1247                                     } else {
1248                                         // want our own copy of the array, so we can edit it
1249                                         arraySizes = new TArraySizes;
1250                                         arraySizes->copyDereferenced(*type.arraySizes);
1251                                     }
1252                                 } else if (type.basicType == EbtStruct || type.basicType == EbtBlock) {
1253                                     // do a structure dereference
1254                                     const TTypeList& memberList = *type.getStruct();
1255                                     shallowCopy(*memberList[derefIndex].type);
1256                                     return;
1257                                 } else {
1258                                     // do a vector/matrix dereference
1259                                     shallowCopy(type);
1260                                     if (matrixCols > 0) {
1261                                         // dereference from matrix to vector
1262                                         if (rowMajor)
1263                                             vectorSize = matrixCols;
1264                                         else
1265                                             vectorSize = matrixRows;
1266                                         matrixCols = 0;
1267                                         matrixRows = 0;
1268                                         if (vectorSize == 1)
1269                                             vector1 = true;
1270                                     } else if (isVector()) {
1271                                         // dereference from vector to scalar
1272                                         vectorSize = 1;
1273                                         vector1 = false;
1274                                     }
1275                                 }
1276                             }
1277     // for making structures, ...
1278     TType(TTypeList* userDef, const TString& n) :
1279                             basicType(EbtStruct), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false),
1280                             arraySizes(nullptr), structure(userDef), fieldName(nullptr)
1281                             {
1282                                 sampler.clear();
1283                                 qualifier.clear();
1284                                 typeName = NewPoolTString(n.c_str());
1285                             }
1286     // For interface blocks
1287     TType(TTypeList* userDef, const TString& n, const TQualifier& q) :
1288                             basicType(EbtBlock), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false),
1289                             qualifier(q), arraySizes(nullptr), structure(userDef), fieldName(nullptr)
1290                             {
1291                                 sampler.clear();
1292                                 typeName = NewPoolTString(n.c_str());
1293                             }
1294     virtual ~TType() {}
1295
1296     // Not for use across pool pops; it will cause multiple instances of TType to point to the same information.
1297     // This only works if that information (like a structure's list of types) does not change and
1298     // the instances are sharing the same pool.
1299     void shallowCopy(const TType& copyOf)
1300     {
1301         basicType = copyOf.basicType;
1302         sampler = copyOf.sampler;
1303         qualifier = copyOf.qualifier;
1304         vectorSize = copyOf.vectorSize;
1305         matrixCols = copyOf.matrixCols;
1306         matrixRows = copyOf.matrixRows;
1307         vector1 = copyOf.vector1;
1308         arraySizes = copyOf.arraySizes;  // copying the pointer only, not the contents
1309         structure = copyOf.structure;
1310         fieldName = copyOf.fieldName;
1311         typeName = copyOf.typeName;
1312     }
1313
1314     // Make complete copy of the whole type graph rooted at 'copyOf'.
1315     void deepCopy(const TType& copyOf)
1316     {
1317         TMap<TTypeList*,TTypeList*> copied;  // to enable copying a type graph as a graph, not a tree
1318         deepCopy(copyOf, copied);
1319     }
1320
1321     // Recursively make temporary
1322     void makeTemporary()
1323     {
1324         getQualifier().makeTemporary();
1325
1326         if (isStruct())
1327             for (unsigned int i = 0; i < structure->size(); ++i)
1328                 (*structure)[i].type->makeTemporary();
1329     }
1330
1331     TType* clone() const
1332     {
1333         TType *newType = new TType();
1334         newType->deepCopy(*this);
1335
1336         return newType;
1337     }
1338
1339     void makeVector() { vector1 = true; }
1340
1341     virtual void hideMember() { basicType = EbtVoid; vectorSize = 1; }
1342     virtual bool hiddenMember() const { return basicType == EbtVoid; }
1343
1344     virtual void setFieldName(const TString& n) { fieldName = NewPoolTString(n.c_str()); }
1345     virtual const TString& getTypeName() const
1346     {
1347         assert(typeName);
1348         return *typeName;
1349     }
1350
1351     virtual const TString& getFieldName() const
1352     {
1353         assert(fieldName);
1354         return *fieldName;
1355     }
1356
1357     virtual TBasicType getBasicType() const { return basicType; }
1358     virtual const TSampler& getSampler() const { return sampler; }
1359     virtual TSampler& getSampler() { return sampler; }
1360
1361     virtual       TQualifier& getQualifier()       { return qualifier; }
1362     virtual const TQualifier& getQualifier() const { return qualifier; }
1363
1364     virtual int getVectorSize() const { return vectorSize; }  // returns 1 for either scalar or vector of size 1, valid for both
1365     virtual int getMatrixCols() const { return matrixCols; }
1366     virtual int getMatrixRows() const { return matrixRows; }
1367     virtual int getOuterArraySize()  const { return arraySizes->getOuterSize(); }
1368     virtual TIntermTyped*  getOuterArrayNode() const { return arraySizes->getOuterNode(); }
1369     virtual int getCumulativeArraySize()  const { return arraySizes->getCumulativeSize(); }
1370     virtual bool isArrayOfArrays() const { return arraySizes != nullptr && arraySizes->getNumDims() > 1; }
1371     virtual int getImplicitArraySize() const { return arraySizes->getImplicitSize(); }
1372     virtual const TArraySizes* getArraySizes() const { return arraySizes; }
1373     virtual       TArraySizes* getArraySizes()       { return arraySizes; }
1374
1375     virtual bool isScalar() const { return ! isVector() && ! isMatrix() && ! isStruct() && ! isArray(); }
1376     virtual bool isScalarOrVec1() const { return isScalar() || vector1; }
1377     virtual bool isVector() const { return vectorSize > 1 || vector1; }
1378     virtual bool isMatrix() const { return matrixCols ? true : false; }
1379     virtual bool isArray()  const { return arraySizes != nullptr; }
1380     virtual bool isSizedArray() const { return isArray() && arraySizes->isSized(); }
1381     virtual bool isUnsizedArray() const { return isArray() && !arraySizes->isSized(); }
1382     virtual bool isArrayVariablyIndexed() const { assert(isArray()); return arraySizes->isVariablyIndexed(); }
1383     virtual void setArrayVariablyIndexed() { assert(isArray()); arraySizes->setVariablyIndexed(); }
1384     virtual void updateImplicitArraySize(int size) { assert(isArray()); arraySizes->updateImplicitSize(size); }
1385     virtual bool isStruct() const { return structure != nullptr; }
1386     virtual bool isFloatingDomain() const { return basicType == EbtFloat || basicType == EbtDouble || basicType == EbtFloat16; }
1387     virtual bool isIntegerDomain() const
1388     {
1389         switch (basicType) {
1390         case EbtInt8:
1391         case EbtUint8:
1392         case EbtInt16:
1393         case EbtUint16:
1394         case EbtInt:
1395         case EbtUint:
1396         case EbtInt64:
1397         case EbtUint64:
1398         case EbtAtomicUint:
1399             return true;
1400         default:
1401             break;
1402         }
1403         return false;
1404     }
1405     virtual bool isOpaque() const { return basicType == EbtSampler || basicType == EbtAtomicUint; }
1406     virtual bool isBuiltIn() const { return getQualifier().builtIn != EbvNone; }
1407
1408     // "Image" is a superset of "Subpass"
1409     virtual bool isImage()   const { return basicType == EbtSampler && getSampler().isImage(); }
1410     virtual bool isSubpass() const { return basicType == EbtSampler && getSampler().isSubpass(); }
1411     virtual bool isTexture() const { return basicType == EbtSampler && getSampler().isTexture(); }
1412
1413     // return true if this type contains any subtype which satisfies the given predicate.
1414     template <typename P>
1415     bool contains(P predicate) const
1416     {
1417         if (predicate(this))
1418             return true;
1419
1420         const auto hasa = [predicate](const TTypeLoc& tl) { return tl.type->contains(predicate); };
1421
1422         return structure && std::any_of(structure->begin(), structure->end(), hasa);
1423     }
1424
1425     // Recursively checks if the type contains the given basic type
1426     virtual bool containsBasicType(TBasicType checkType) const
1427     {
1428         return contains([checkType](const TType* t) { return t->basicType == checkType; } );
1429     }
1430
1431     // Recursively check the structure for any arrays, needed for some error checks
1432     virtual bool containsArray() const
1433     {
1434         return contains([](const TType* t) { return t->isArray(); } );
1435     }
1436
1437     // Check the structure for any structures, needed for some error checks
1438     virtual bool containsStructure() const
1439     {
1440         return contains([this](const TType* t) { return t != this && t->isStruct(); } );
1441     }
1442
1443     // Recursively check the structure for any unsized arrays, needed for triggering a copyUp().
1444     virtual bool containsUnsizedArray() const
1445     {
1446         return contains([](const TType* t) { return t->isUnsizedArray(); } );
1447     }
1448
1449     virtual bool containsOpaque() const
1450     {
1451         return contains([](const TType* t) { return t->isOpaque(); } );
1452     }
1453
1454     // Recursively checks if the type contains a built-in variable
1455     virtual bool containsBuiltIn() const
1456     {
1457         return contains([](const TType* t) { return t->isBuiltIn(); } );
1458     }
1459
1460     virtual bool containsNonOpaque() const
1461     {
1462         const auto nonOpaque = [](const TType* t) {
1463             switch (t->basicType) {
1464             case EbtVoid:
1465             case EbtFloat:
1466             case EbtDouble:
1467             case EbtFloat16:
1468             case EbtInt8:
1469             case EbtUint8:
1470             case EbtInt16:
1471             case EbtUint16:
1472             case EbtInt:
1473             case EbtUint:
1474             case EbtInt64:
1475             case EbtUint64:
1476             case EbtBool:
1477                 return true;
1478             default:
1479                 return false;
1480             }
1481         };
1482
1483         return contains(nonOpaque);
1484     }
1485
1486     virtual bool containsSpecializationSize() const
1487     {
1488         return contains([](const TType* t) { return t->isArray() && t->arraySizes->isOuterSpecialization(); } );
1489     }
1490
1491     virtual bool contains16BitInt() const
1492     {
1493         return containsBasicType(EbtInt16) || containsBasicType(EbtUint16);
1494     }
1495
1496     virtual bool contains8BitInt() const
1497     {
1498         return containsBasicType(EbtInt8) || containsBasicType(EbtUint8);
1499     }
1500
1501     // Array editing methods.  Array descriptors can be shared across
1502     // type instances.  This allows all uses of the same array
1503     // to be updated at once.  E.g., all nodes can be explicitly sized
1504     // by tracking and correcting one implicit size.  Or, all nodes
1505     // can get the explicit size on a redeclaration that gives size.
1506     //
1507     // N.B.:  Don't share with the shared symbol tables (symbols are
1508     // marked as isReadOnly().  Such symbols with arrays that will be
1509     // edited need to copyUp() on first use, so that
1510     // A) the edits don't effect the shared symbol table, and
1511     // B) the edits are shared across all users.
1512     void updateArraySizes(const TType& type)
1513     {
1514         // For when we may already be sharing existing array descriptors,
1515         // keeping the pointers the same, just updating the contents.
1516         assert(arraySizes != nullptr);
1517         assert(type.arraySizes != nullptr);
1518         *arraySizes = *type.arraySizes;
1519     }
1520     void copyArraySizes(const TArraySizes& s)
1521     {
1522         // For setting a fresh new set of array sizes, not yet worrying about sharing.
1523         arraySizes = new TArraySizes;
1524         *arraySizes = s;
1525     }
1526     void transferArraySizes(TArraySizes* s)
1527     {
1528         // For setting an already allocated set of sizes that this type can use
1529         // (no copy made).
1530         arraySizes = s;
1531     }
1532     void clearArraySizes()
1533     {
1534         arraySizes = nullptr;
1535     }
1536
1537     // Add inner array sizes, to any existing sizes, via copy; the
1538     // sizes passed in can still be reused for other purposes.
1539     void copyArrayInnerSizes(const TArraySizes* s)
1540     {
1541         if (s != nullptr) {
1542             if (arraySizes == nullptr)
1543                 copyArraySizes(*s);
1544             else
1545                 arraySizes->addInnerSizes(*s);
1546         }
1547     }
1548     void changeOuterArraySize(int s) { arraySizes->changeOuterSize(s); }
1549
1550     // Recursively make the implicit array size the explicit array size.
1551     // Expicit arrays are compile-time or link-time sized, never run-time sized.
1552     // Sometimes, policy calls for an array to be run-time sized even if it was
1553     // never variably indexed: Don't turn a 'skipNonvariablyIndexed' array into
1554     // an explicit array.
1555     void adoptImplicitArraySizes(bool skipNonvariablyIndexed)
1556     {
1557         if (isUnsizedArray() && !(skipNonvariablyIndexed || isArrayVariablyIndexed()))
1558             changeOuterArraySize(getImplicitArraySize());
1559         if (isStruct() && structure->size() > 0) {
1560             int lastMember = (int)structure->size() - 1;
1561             for (int i = 0; i < lastMember; ++i)
1562                 (*structure)[i].type->adoptImplicitArraySizes(false);
1563             // implement the "last member of an SSBO" policy
1564             (*structure)[lastMember].type->adoptImplicitArraySizes(getQualifier().storage == EvqBuffer);
1565         }
1566     }
1567
1568     const char* getBasicString() const
1569     {
1570         return TType::getBasicString(basicType);
1571     }
1572
1573     static const char* getBasicString(TBasicType t)
1574     {
1575         switch (t) {
1576         case EbtVoid:              return "void";
1577         case EbtFloat:             return "float";
1578         case EbtDouble:            return "double";
1579         case EbtFloat16:           return "float16_t";
1580         case EbtInt8:              return "int8_t";
1581         case EbtUint8:             return "uint8_t";
1582         case EbtInt16:             return "int16_t";
1583         case EbtUint16:            return "uint16_t";
1584         case EbtInt:               return "int";
1585         case EbtUint:              return "uint";
1586         case EbtInt64:             return "int64_t";
1587         case EbtUint64:            return "uint64_t";
1588         case EbtBool:              return "bool";
1589         case EbtAtomicUint:        return "atomic_uint";
1590         case EbtSampler:           return "sampler/image";
1591         case EbtStruct:            return "structure";
1592         case EbtBlock:             return "block";
1593         default:                   return "unknown type";
1594         }
1595     }
1596
1597     TString getCompleteString() const
1598     {
1599         TString typeString;
1600
1601         const auto appendStr  = [&](const char* s)  { typeString.append(s); };
1602         const auto appendUint = [&](unsigned int u) { typeString.append(std::to_string(u).c_str()); };
1603         const auto appendInt  = [&](int i)          { typeString.append(std::to_string(i).c_str()); };
1604
1605         if (qualifier.hasLayout()) {
1606             // To reduce noise, skip this if the only layout is an xfb_buffer
1607             // with no triggering xfb_offset.
1608             TQualifier noXfbBuffer = qualifier;
1609             noXfbBuffer.layoutXfbBuffer = TQualifier::layoutXfbBufferEnd;
1610             if (noXfbBuffer.hasLayout()) {
1611                 appendStr("layout(");
1612                 if (qualifier.hasAnyLocation()) {
1613                     appendStr(" location=");
1614                     appendUint(qualifier.layoutLocation);
1615                     if (qualifier.hasComponent()) {
1616                         appendStr(" component=");
1617                         appendUint(qualifier.layoutComponent);
1618                     }
1619                     if (qualifier.hasIndex()) {
1620                         appendStr(" index=");
1621                         appendUint(qualifier.layoutIndex);
1622                     }
1623                 }
1624                 if (qualifier.hasSet()) {
1625                     appendStr(" set=");
1626                     appendUint(qualifier.layoutSet);
1627                 }
1628                 if (qualifier.hasBinding()) {
1629                     appendStr(" binding=");
1630                     appendUint(qualifier.layoutBinding);
1631                 }
1632                 if (qualifier.hasStream()) {
1633                     appendStr(" stream=");
1634                     appendUint(qualifier.layoutStream);
1635                 }
1636                 if (qualifier.hasMatrix()) {
1637                     appendStr(" ");
1638                     appendStr(TQualifier::getLayoutMatrixString(qualifier.layoutMatrix));
1639                 }
1640                 if (qualifier.hasPacking()) {
1641                     appendStr(" ");
1642                     appendStr(TQualifier::getLayoutPackingString(qualifier.layoutPacking));
1643                 }
1644                 if (qualifier.hasOffset()) {
1645                     appendStr(" offset=");
1646                     appendInt(qualifier.layoutOffset);
1647                 }
1648                 if (qualifier.hasAlign()) {
1649                     appendStr(" align=");
1650                     appendInt(qualifier.layoutAlign);
1651                 }
1652                 if (qualifier.hasFormat()) {
1653                     appendStr(" ");
1654                     appendStr(TQualifier::getLayoutFormatString(qualifier.layoutFormat));
1655                 }
1656                 if (qualifier.hasXfbBuffer() && qualifier.hasXfbOffset()) {
1657                     appendStr(" xfb_buffer=");
1658                     appendUint(qualifier.layoutXfbBuffer);
1659                 }
1660                 if (qualifier.hasXfbOffset()) {
1661                     appendStr(" xfb_offset=");
1662                     appendUint(qualifier.layoutXfbOffset);
1663                 }
1664                 if (qualifier.hasXfbStride()) {
1665                     appendStr(" xfb_stride=");
1666                     appendUint(qualifier.layoutXfbStride);
1667                 }
1668                 if (qualifier.hasAttachment()) {
1669                     appendStr(" input_attachment_index=");
1670                     appendUint(qualifier.layoutAttachment);
1671                 }
1672                 if (qualifier.hasSpecConstantId()) {
1673                     appendStr(" constant_id=");
1674                     appendUint(qualifier.layoutSpecConstantId);
1675                 }
1676                 if (qualifier.layoutPushConstant)
1677                     appendStr(" push_constant");
1678
1679 #ifdef NV_EXTENSIONS
1680                 if (qualifier.layoutPassthrough)
1681                     appendStr(" passthrough");
1682                 if (qualifier.layoutViewportRelative)
1683                     appendStr(" layoutViewportRelative");
1684                 if (qualifier.layoutSecondaryViewportRelativeOffset != -2048) {
1685                     appendStr(" layoutSecondaryViewportRelativeOffset=");
1686                     appendInt(qualifier.layoutSecondaryViewportRelativeOffset);
1687                 }
1688 #endif
1689
1690                 appendStr(")");
1691             }
1692         }
1693
1694         if (qualifier.invariant)
1695             appendStr(" invariant");
1696         if (qualifier.noContraction)
1697             appendStr(" noContraction");
1698         if (qualifier.centroid)
1699             appendStr(" centroid");
1700         if (qualifier.smooth)
1701             appendStr(" smooth");
1702         if (qualifier.flat)
1703             appendStr(" flat");
1704         if (qualifier.nopersp)
1705             appendStr(" noperspective");
1706 #ifdef AMD_EXTENSIONS
1707         if (qualifier.explicitInterp)
1708             appendStr(" __explicitInterpAMD");
1709 #endif
1710         if (qualifier.patch)
1711             appendStr(" patch");
1712         if (qualifier.sample)
1713             appendStr(" sample");
1714         if (qualifier.coherent)
1715             appendStr(" coherent");
1716         if (qualifier.volatil)
1717             appendStr(" volatile");
1718         if (qualifier.restrict)
1719             appendStr(" restrict");
1720         if (qualifier.readonly)
1721             appendStr(" readonly");
1722         if (qualifier.writeonly)
1723             appendStr(" writeonly");
1724         if (qualifier.specConstant)
1725             appendStr(" specialization-constant");
1726         if (qualifier.nonUniform)
1727             appendStr(" nonuniform");
1728         appendStr(" ");
1729         appendStr(getStorageQualifierString());
1730         if (isArray()) {
1731             for(int i = 0; i < (int)arraySizes->getNumDims(); ++i) {
1732                 int size = arraySizes->getDimSize(i);
1733                 if (size == UnsizedArraySize && i == 0 && arraySizes->isVariablyIndexed())
1734                     appendStr(" runtime-sized array of");
1735                 else {
1736                     if (size == UnsizedArraySize) {
1737                         appendStr(" unsized");
1738                         if (i == 0) {
1739                             appendStr(" ");
1740                             appendInt(arraySizes->getImplicitSize());
1741                         }
1742                     } else {
1743                         appendStr(" ");
1744                         appendInt(arraySizes->getDimSize(i));
1745                     }
1746                     appendStr("-element array of");
1747                 }
1748             }
1749         }
1750         if (qualifier.precision != EpqNone) {
1751             appendStr(" ");
1752             appendStr(getPrecisionQualifierString());
1753         }
1754         if (isMatrix()) {
1755             appendStr(" ");
1756             appendInt(matrixCols);
1757             appendStr("X");
1758             appendInt(matrixRows);
1759             appendStr(" matrix of");
1760         } else if (isVector()) {
1761             appendStr(" ");
1762             appendInt(vectorSize);
1763             appendStr("-component vector of");
1764         }
1765
1766         appendStr(" ");
1767         typeString.append(getBasicTypeString());
1768
1769         if (qualifier.builtIn != EbvNone) {
1770             appendStr(" ");
1771             appendStr(getBuiltInVariableString());
1772         }
1773
1774         // Add struct/block members
1775         if (structure) {
1776             appendStr("{");
1777             for (size_t i = 0; i < structure->size(); ++i) {
1778                 if (! (*structure)[i].type->hiddenMember()) {
1779                     typeString.append((*structure)[i].type->getCompleteString());
1780                     typeString.append(" ");
1781                     typeString.append((*structure)[i].type->getFieldName());
1782                     if (i < structure->size() - 1)
1783                         appendStr(", ");
1784                 }
1785             }
1786             appendStr("}");
1787         }
1788
1789         return typeString;
1790     }
1791
1792     TString getBasicTypeString() const
1793     {
1794         if (basicType == EbtSampler)
1795             return sampler.getString();
1796         else
1797             return getBasicString();
1798     }
1799
1800     const char* getStorageQualifierString() const { return GetStorageQualifierString(qualifier.storage); }
1801     const char* getBuiltInVariableString() const { return GetBuiltInVariableString(qualifier.builtIn); }
1802     const char* getPrecisionQualifierString() const { return GetPrecisionQualifierString(qualifier.precision); }
1803     const TTypeList* getStruct() const { return structure; }
1804     void setStruct(TTypeList* s) { structure = s; }
1805     TTypeList* getWritableStruct() const { return structure; }  // This should only be used when known to not be sharing with other threads
1806
1807     int computeNumComponents() const
1808     {
1809         int components = 0;
1810
1811         if (getBasicType() == EbtStruct || getBasicType() == EbtBlock) {
1812             for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); tl++)
1813                 components += ((*tl).type)->computeNumComponents();
1814         } else if (matrixCols)
1815             components = matrixCols * matrixRows;
1816         else
1817             components = vectorSize;
1818
1819         if (arraySizes != nullptr) {
1820             components *= arraySizes->getCumulativeSize();
1821         }
1822
1823         return components;
1824     }
1825
1826     // append this type's mangled name to the passed in 'name'
1827     void appendMangledName(TString& name) const
1828     {
1829         buildMangledName(name);
1830         name += ';' ;
1831     }
1832
1833     // Do two structure types match?  They could be declared independently,
1834     // in different places, but still might satisfy the definition of matching.
1835     // From the spec:
1836     //
1837     // "Structures must have the same name, sequence of type names, and
1838     //  type definitions, and member names to be considered the same type.
1839     //  This rule applies recursively for nested or embedded types."
1840     //
1841     bool sameStructType(const TType& right) const
1842     {
1843         // Most commonly, they are both nullptr, or the same pointer to the same actual structure
1844         if (structure == right.structure)
1845             return true;
1846
1847         // Both being nullptr was caught above, now they both have to be structures of the same number of elements
1848         if (structure == nullptr || right.structure == nullptr ||
1849             structure->size() != right.structure->size())
1850             return false;
1851
1852         // Structure names have to match
1853         if (*typeName != *right.typeName)
1854             return false;
1855
1856         // Compare the names and types of all the members, which have to match
1857         for (unsigned int i = 0; i < structure->size(); ++i) {
1858             if ((*structure)[i].type->getFieldName() != (*right.structure)[i].type->getFieldName())
1859                 return false;
1860
1861             if (*(*structure)[i].type != *(*right.structure)[i].type)
1862                 return false;
1863         }
1864
1865         return true;
1866     }
1867
1868     // See if two types match, in all aspects except arrayness
1869     bool sameElementType(const TType& right) const
1870     {
1871         return basicType == right.basicType && sameElementShape(right);
1872     }
1873
1874     // See if two type's arrayness match
1875     bool sameArrayness(const TType& right) const
1876     {
1877         return ((arraySizes == nullptr && right.arraySizes == nullptr) ||
1878                 (arraySizes != nullptr && right.arraySizes != nullptr && *arraySizes == *right.arraySizes));
1879     }
1880
1881     // See if two type's arrayness match in everything except their outer dimension
1882     bool sameInnerArrayness(const TType& right) const
1883     {
1884         assert(arraySizes != nullptr && right.arraySizes != nullptr);
1885         return arraySizes->sameInnerArrayness(*right.arraySizes);
1886     }
1887
1888     // See if two type's elements match in all ways except basic type
1889     bool sameElementShape(const TType& right) const
1890     {
1891         return    sampler == right.sampler    &&
1892                vectorSize == right.vectorSize &&
1893                matrixCols == right.matrixCols &&
1894                matrixRows == right.matrixRows &&
1895                   vector1 == right.vector1    &&
1896                sameStructType(right);
1897     }
1898
1899     // See if two types match in all ways (just the actual type, not qualification)
1900     bool operator==(const TType& right) const
1901     {
1902         return sameElementType(right) && sameArrayness(right);
1903     }
1904
1905     bool operator!=(const TType& right) const
1906     {
1907         return ! operator==(right);
1908     }
1909
1910 protected:
1911     // Require consumer to pick between deep copy and shallow copy.
1912     TType(const TType& type);
1913     TType& operator=(const TType& type);
1914
1915     // Recursively copy a type graph, while preserving the graph-like
1916     // quality. That is, don't make more than one copy of a structure that
1917     // gets reused multiple times in the type graph.
1918     void deepCopy(const TType& copyOf, TMap<TTypeList*,TTypeList*>& copiedMap)
1919     {
1920         shallowCopy(copyOf);
1921
1922         if (copyOf.arraySizes) {
1923             arraySizes = new TArraySizes;
1924             *arraySizes = *copyOf.arraySizes;
1925         }
1926
1927         if (copyOf.structure) {
1928             auto prevCopy = copiedMap.find(copyOf.structure);
1929             if (prevCopy != copiedMap.end())
1930                 structure = prevCopy->second;
1931             else {
1932                 structure = new TTypeList;
1933                 copiedMap[copyOf.structure] = structure;
1934                 for (unsigned int i = 0; i < copyOf.structure->size(); ++i) {
1935                     TTypeLoc typeLoc;
1936                     typeLoc.loc = (*copyOf.structure)[i].loc;
1937                     typeLoc.type = new TType();
1938                     typeLoc.type->deepCopy(*(*copyOf.structure)[i].type, copiedMap);
1939                     structure->push_back(typeLoc);
1940                 }
1941             }
1942         }
1943
1944         if (copyOf.fieldName)
1945             fieldName = NewPoolTString(copyOf.fieldName->c_str());
1946         if (copyOf.typeName)
1947             typeName = NewPoolTString(copyOf.typeName->c_str());
1948     }
1949
1950
1951     void buildMangledName(TString&) const;
1952
1953     TBasicType basicType : 8;
1954     int vectorSize       : 4;  // 1 means either scalar or 1-component vector; see vector1 to disambiguate.
1955     int matrixCols       : 4;
1956     int matrixRows       : 4;
1957     bool vector1         : 1;  // Backward-compatible tracking of a 1-component vector distinguished from a scalar.
1958                                // GLSL 4.5 never has a 1-component vector; so this will always be false until such
1959                                // functionality is added.
1960                                // HLSL does have a 1-component vectors, so this will be true to disambiguate
1961                                // from a scalar.
1962     TQualifier qualifier;
1963
1964     TArraySizes* arraySizes;    // nullptr unless an array; can be shared across types
1965     TTypeList* structure;       // nullptr unless this is a struct; can be shared across types
1966     TString *fieldName;         // for structure field names
1967     TString *typeName;          // for structure type name
1968     TSampler sampler;
1969 };
1970
1971 } // end namespace glslang
1972
1973 #endif // _TYPES_INCLUDED_