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