Home | History | Annotate | Download | only in Include
      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     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 
    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
    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 
    445     void clearInterstage()
    446     {
    447         clearInterpolation();
    448         patch = false;
    449         sample = false;
    450     }
    451 
    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 
    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.
    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 
    532     bool isMemory() const
    533     {
    534         return subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly || nonprivate;
    535     }
    536     bool isMemoryQualifierImageAndSSBOOnly() const
    537     {
    538         return subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly;
    539     }
    540 
    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
    551     bool isExplicitInterpolation() const
    552     {
    553         return explicitInterp;
    554     }
    555 #endif
    556 
    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 
    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 
    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 
    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 
    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 
    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 
    630     bool isPerPrimitive() const
    631     {
    632 #ifdef NV_EXTENSIONS
    633         return perPrimitiveNV;
    634 #else
    635         return false;
    636 #endif
    637     }
    638 
    639     bool isPerView() const
    640     {
    641 #ifdef NV_EXTENSIONS
    642         return perViewNV;
    643 #else
    644         return false;
    645 #endif
    646     }
    647 
    648     bool isTaskMemory() const
    649     {
    650 #ifdef NV_EXTENSIONS
    651         return perTaskNV;
    652 #else
    653         return false;
    654 #endif
    655     }
    656 
    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
    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
    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
    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     }
    741     void clearInterstageLayout()
    742     {
    743         layoutLocation = layoutLocationEnd;
    744         layoutComponent = layoutComponentEnd;
    745         layoutIndex = layoutIndexEnd;
    746         clearStreamLayout();
    747         clearXfbLayout();
    748     }
    749     void clearStreamLayout()
    750     {
    751         layoutStream = layoutStreamEnd;
    752     }
    753     void clearXfbLayout()
    754     {
    755         layoutXfbBuffer = layoutXfbBufferEnd;
    756         layoutXfbStride = layoutXfbStrideEnd;
    757         layoutXfbOffset = layoutXfbOffsetEnd;
    758     }
    759 
    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     }
    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 
    831     bool hasUniformLayout() const
    832     {
    833         return hasMatrix() ||
    834                hasPacking() ||
    835                hasOffset() ||
    836                hasBinding() ||
    837                hasSet() ||
    838                hasAlign();
    839     }
    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 
    852     bool hasMatrix() const
    853     {
    854         return layoutMatrix != ElmNone;
    855     }
    856     bool hasPacking() const
    857     {
    858         return layoutPacking != ElpNone;
    859     }
    860     bool hasOffset() const
    861     {
    862         return layoutOffset != layoutNotSet;
    863     }
    864     bool hasAlign() const
    865     {
    866         return layoutAlign != layoutNotSet;
    867     }
    868     bool hasAnyLocation() const
    869     {
    870         return hasLocation() ||
    871                hasComponent() ||
    872                hasIndex();
    873     }
    874     bool hasLocation() const
    875     {
    876         return layoutLocation != layoutLocationEnd;
    877     }
    878     bool hasComponent() const
    879     {
    880         return layoutComponent != layoutComponentEnd;
    881     }
    882     bool hasIndex() const
    883     {
    884         return layoutIndex != layoutIndexEnd;
    885     }
    886     bool hasSet() const
    887     {
    888         return layoutSet != layoutSetEnd;
    889     }
    890     bool hasBinding() const
    891     {
    892         return layoutBinding != layoutBindingEnd;
    893     }
    894     bool hasStream() const
    895     {
    896         return layoutStream != layoutStreamEnd;
    897     }
    898     bool hasFormat() const
    899     {
    900         return layoutFormat != ElfNone;
    901     }
    902     bool hasXfb() const
    903     {
    904         return hasXfbBuffer() ||
    905                hasXfbStride() ||
    906                hasXfbOffset();
    907     }
    908     bool hasXfbBuffer() const
    909     {
    910         return layoutXfbBuffer != layoutXfbBufferEnd;
    911     }
    912     bool hasXfbStride() const
    913     {
    914         return layoutXfbStride != layoutXfbStrideEnd;
    915     }
    916     bool hasXfbOffset() const
    917     {
    918         return layoutXfbOffset != layoutXfbOffsetEnd;
    919     }
    920     bool hasAttachment() const
    921     {
    922         return layoutAttachment != layoutAttachmentEnd;
    923     }
    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     }
    930     bool hasBufferReferenceAlign() const
    931     {
    932         return layoutBufferReferenceAlign != layoutBufferReferenceAlignEnd;
    933     }
    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     }
    941     bool isNonUniform() const
    942     {
    943         return nonUniform;
    944     }
    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     }
    951     bool isConstant() const
    952     {
    953         // True if is either kind of constant; specialization or regular.
    954         return isFrontEndConstant() || isSpecConstant();
    955     }
    956     void makeSpecConstant()
    957     {
    958         storage = EvqConst;
    959         specConstant = true;
    960     }
    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     }
    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     }
    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     }
   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     }
   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     }
   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     }
   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     }
   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     }
   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 
   1130     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.
   1161     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 
   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 
   1257     void setVector(int s)
   1258     {
   1259         matrixRows = 0;
   1260         matrixCols = 0;
   1261         vectorSize = s;
   1262     }
   1263 
   1264     void setMatrix(int c, int r)
   1265     {
   1266         matrixRows = r;
   1267         matrixCols = c;
   1268         vectorSize = 0;
   1269     }
   1270 
   1271     bool isScalar() const
   1272     {
   1273         return matrixCols == 0 && vectorSize == 1 && arraySizes == nullptr && userDef == nullptr;
   1274     }
   1275 
   1276     // "Image" is a superset of "Subpass"
   1277     bool isImage()   const { return basicType == EbtSampler && sampler.isImage(); }
   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:
   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) :
   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
   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) :
   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, ...
   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
   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)
   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                             }
   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.
   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'.
   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
   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 
   1450     TType* clone() const
   1451     {
   1452         TType *newType = new TType();
   1453         newType->deepCopy(*this);
   1454 
   1455         return newType;
   1456     }
   1457 
   1458     void makeVector() { vector1 = true; }
   1459 
   1460     virtual void hideMember() { basicType = EbtVoid; vectorSize = 1; }
   1461     virtual bool hiddenMember() const { return basicType == EbtVoid; }
   1462 
   1463     virtual void setFieldName(const TString& n) { fieldName = NewPoolTString(n.c_str()); }
   1464     virtual const TString& getTypeName() const
   1465     {
   1466         assert(typeName);
   1467         return *typeName;
   1468     }
   1469 
   1470     virtual const TString& getFieldName() const
   1471     {
   1472         assert(fieldName);
   1473         return *fieldName;
   1474     }
   1475 
   1476     virtual TBasicType getBasicType() const { return basicType; }
   1477     virtual const TSampler& getSampler() const { return sampler; }
   1478     virtual TSampler& getSampler() { return sampler; }
   1479 
   1480     virtual       TQualifier& getQualifier()       { return qualifier; }
   1481     virtual const TQualifier& getQualifier() const { return qualifier; }
   1482 
   1483     virtual int getVectorSize() const { return vectorSize; }  // returns 1 for either scalar or vector of size 1, valid for both
   1484     virtual int getMatrixCols() const { return matrixCols; }
   1485     virtual int getMatrixRows() const { return matrixRows; }
   1486     virtual int getOuterArraySize()  const { return arraySizes->getOuterSize(); }
   1487     virtual TIntermTyped*  getOuterArrayNode() const { return arraySizes->getOuterNode(); }
   1488     virtual int getCumulativeArraySize()  const { return arraySizes->getCumulativeSize(); }
   1489     virtual bool isArrayOfArrays() const { return arraySizes != nullptr && arraySizes->getNumDims() > 1; }
   1490     virtual int getImplicitArraySize() const { return arraySizes->getImplicitSize(); }
   1491     virtual const TArraySizes* getArraySizes() const { return arraySizes; }
   1492     virtual       TArraySizes* getArraySizes()       { return arraySizes; }
   1493     virtual TType* getReferentType() const { return referentType; }
   1494 
   1495     virtual bool isScalar() const { return ! isVector() && ! isMatrix() && ! isStruct() && ! isArray(); }
   1496     virtual bool isScalarOrVec1() const { return isScalar() || vector1; }
   1497     virtual bool isVector() const { return vectorSize > 1 || vector1; }
   1498     virtual bool isMatrix() const { return matrixCols ? true : false; }
   1499     virtual bool isArray()  const { return arraySizes != nullptr; }
   1500     virtual bool isSizedArray() const { return isArray() && arraySizes->isSized(); }
   1501     virtual bool isUnsizedArray() const { return isArray() && !arraySizes->isSized(); }
   1502     virtual bool isArrayVariablyIndexed() const { assert(isArray()); return arraySizes->isVariablyIndexed(); }
   1503     virtual void setArrayVariablyIndexed() { assert(isArray()); arraySizes->setVariablyIndexed(); }
   1504     virtual void updateImplicitArraySize(int size) { assert(isArray()); arraySizes->updateImplicitSize(size); }
   1505     virtual bool isStruct() const { return basicType == EbtStruct || basicType == EbtBlock; }
   1506     virtual bool isFloatingDomain() const { return basicType == EbtFloat || basicType == EbtDouble || basicType == EbtFloat16; }
   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     }
   1525     virtual bool isOpaque() const { return basicType == EbtSampler || basicType == EbtAtomicUint
   1526 #ifdef NV_EXTENSIONS
   1527         || basicType == EbtAccStructNV
   1528 #endif
   1529         ; }
   1530     virtual bool isBuiltIn() const { return getQualifier().builtIn != EbvNone; }
   1531 
   1532     // "Image" is a superset of "Subpass"
   1533     virtual bool isImage()   const { return basicType == EbtSampler && getSampler().isImage(); }
   1534     virtual bool isSubpass() const { return basicType == EbtSampler && getSampler().isSubpass(); }
   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>
   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
   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
   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
   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().
   1568     virtual bool containsUnsizedArray() const
   1569     {
   1570         return contains([](const TType* t) { return t->isUnsizedArray(); } );
   1571     }
   1572 
   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
   1579     virtual bool containsBuiltIn() const
   1580     {
   1581         return contains([](const TType* t) { return t->isBuiltIn(); } );
   1582     }
   1583 
   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 
   1610     virtual bool containsSpecializationSize() const
   1611     {
   1612         return contains([](const TType* t) { return t->isArray() && t->arraySizes->isOuterSpecialization(); } );
   1613     }
   1614 
   1615     virtual bool contains16BitInt() const
   1616     {
   1617         return containsBasicType(EbtInt16) || containsBasicType(EbtUint16);
   1618     }
   1619 
   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.
   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     }
   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     }
   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     }
   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.
   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     }
   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.
   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 
   1697     const char* getBasicString() const
   1698     {
   1699         return TType::getBasicString(basicType);
   1700     }
   1701 
   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 
   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 
   1953     TString getBasicTypeString() const
   1954     {
   1955         if (basicType == EbtSampler)
   1956             return sampler.getString();
   1957         else
   1958             return getBasicString();
   1959     }
   1960 
   1961     const char* getStorageQualifierString() const { return GetStorageQualifierString(qualifier.storage); }
   1962     const char* getBuiltInVariableString() const { return GetBuiltInVariableString(qualifier.builtIn); }
   1963     const char* getPrecisionQualifierString() const { return GetPrecisionQualifierString(qualifier.precision); }
   1964     const TTypeList* getStruct() const { assert(isStruct()); return structure; }
   1965     void setStruct(TTypeList* s) { assert(isStruct()); structure = s; }
   1966     TTypeList* getWritableStruct() const { assert(isStruct()); return structure; }  // This should only be used when known to not be sharing with other threads
   1967 
   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'
   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     //
   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 
   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
   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
   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
   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
   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.
   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