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