tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

util.cpp (29670B)


      1 //
      2 // Copyright 2010 The ANGLE Project Authors. All rights reserved.
      3 // Use of this source code is governed by a BSD-style license that can be
      4 // found in the LICENSE file.
      5 //
      6 
      7 #include "compiler/translator/util.h"
      8 
      9 #include <limits>
     10 
     11 #include "common/utilities.h"
     12 #include "compiler/preprocessor/numeric_lex.h"
     13 #include "compiler/translator/ImmutableStringBuilder.h"
     14 #include "compiler/translator/SymbolTable.h"
     15 
     16 bool atoi_clamp(const char *str, unsigned int *value)
     17 {
     18    bool success = angle::pp::numeric_lex_int(str, value);
     19    if (!success)
     20        *value = std::numeric_limits<unsigned int>::max();
     21    return success;
     22 }
     23 
     24 namespace sh
     25 {
     26 
     27 namespace
     28 {
     29 // [primarySize-1][secondarySize-1] is the GL type with a basic type of float.
     30 constexpr GLenum kFloatGLType[4][4] = {
     31    // float1xS only makes sense for S == 1
     32    {
     33        GL_FLOAT,
     34        GL_NONE,
     35        GL_NONE,
     36        GL_NONE,
     37    },
     38    // float2xS is vec2 for S == 1, and mat2xS o.w.
     39    {
     40        GL_FLOAT_VEC2,
     41        GL_FLOAT_MAT2,
     42        GL_FLOAT_MAT2x3,
     43        GL_FLOAT_MAT2x4,
     44    },
     45    // float3xS is vec3 for S == 1, and mat3xS o.w.
     46    {
     47        GL_FLOAT_VEC3,
     48        GL_FLOAT_MAT3x2,
     49        GL_FLOAT_MAT3,
     50        GL_FLOAT_MAT3x4,
     51    },
     52    // float4xS is vec4 for S == 1, and mat4xS o.w.
     53    {
     54        GL_FLOAT_VEC4,
     55        GL_FLOAT_MAT4x2,
     56        GL_FLOAT_MAT4x3,
     57        GL_FLOAT_MAT4,
     58    },
     59 };
     60 // [primarySize-1] is the GL type with a basic type of int.
     61 constexpr GLenum kIntGLType[4] = {GL_INT, GL_INT_VEC2, GL_INT_VEC3, GL_INT_VEC4};
     62 // [primarySize-1] is the GL type with a basic type of uint.
     63 constexpr GLenum kUIntGLType[4] = {GL_UNSIGNED_INT, GL_UNSIGNED_INT_VEC2, GL_UNSIGNED_INT_VEC3,
     64                                   GL_UNSIGNED_INT_VEC4};
     65 // [primarySize-1] is the GL type with a basic type of bool.
     66 constexpr GLenum kBoolGLType[4] = {GL_BOOL, GL_BOOL_VEC2, GL_BOOL_VEC3, GL_BOOL_VEC4};
     67 
     68 bool IsInterpolationIn(TQualifier qualifier)
     69 {
     70    switch (qualifier)
     71    {
     72        case EvqSmoothIn:
     73        case EvqFlatIn:
     74        case EvqNoPerspectiveIn:
     75        case EvqCentroidIn:
     76        case EvqSampleIn:
     77            return true;
     78        default:
     79            return false;
     80    }
     81 }
     82 
     83 bool IsInterpolationOut(TQualifier qualifier)
     84 {
     85    switch (qualifier)
     86    {
     87        case EvqSmoothOut:
     88        case EvqFlatOut:
     89        case EvqNoPerspectiveOut:
     90        case EvqCentroidOut:
     91        case EvqSampleOut:
     92            return true;
     93        default:
     94            return false;
     95    }
     96 }
     97 }  // anonymous namespace
     98 
     99 float NumericLexFloat32OutOfRangeToInfinity(const std::string &str)
    100 {
    101    // Parses a decimal string using scientific notation into a floating point number.
    102    // Out-of-range values are converted to infinity. Values that are too small to be
    103    // represented are converted to zero.
    104 
    105    // The mantissa in decimal scientific notation. The magnitude of the mantissa integer does not
    106    // matter.
    107    unsigned int decimalMantissa = 0;
    108    size_t i                     = 0;
    109    bool decimalPointSeen        = false;
    110    bool nonZeroSeenInMantissa   = false;
    111 
    112    // The exponent offset reflects the position of the decimal point.
    113    int exponentOffset = -1;
    114 
    115    // This is just a counter for how many decimal digits are written to decimalMantissa.
    116    int mantissaDecimalDigits = 0;
    117 
    118    while (i < str.length())
    119    {
    120        const char c = str[i];
    121        if (c == 'e' || c == 'E')
    122        {
    123            break;
    124        }
    125        if (c == '.')
    126        {
    127            decimalPointSeen = true;
    128            ++i;
    129            continue;
    130        }
    131 
    132        unsigned int digit = static_cast<unsigned int>(c - '0');
    133        ASSERT(digit < 10u);
    134        if (digit != 0u)
    135        {
    136            nonZeroSeenInMantissa = true;
    137        }
    138        if (nonZeroSeenInMantissa)
    139        {
    140            // Add bits to the mantissa until space runs out in 32-bit int. This should be
    141            // enough precision to make the resulting binary mantissa accurate to 1 ULP.
    142            if (decimalMantissa <= (std::numeric_limits<unsigned int>::max() - 9u) / 10u)
    143            {
    144                decimalMantissa = decimalMantissa * 10u + digit;
    145                ++mantissaDecimalDigits;
    146            }
    147            if (!decimalPointSeen)
    148            {
    149                ++exponentOffset;
    150            }
    151        }
    152        else if (decimalPointSeen)
    153        {
    154            --exponentOffset;
    155        }
    156        ++i;
    157    }
    158    if (decimalMantissa == 0)
    159    {
    160        return 0.0f;
    161    }
    162    int exponent = 0;
    163    if (i < str.length())
    164    {
    165        ASSERT(str[i] == 'e' || str[i] == 'E');
    166        ++i;
    167        bool exponentOutOfRange = false;
    168        bool negativeExponent   = false;
    169        if (str[i] == '-')
    170        {
    171            negativeExponent = true;
    172            ++i;
    173        }
    174        else if (str[i] == '+')
    175        {
    176            ++i;
    177        }
    178        while (i < str.length())
    179        {
    180            const char c       = str[i];
    181            unsigned int digit = static_cast<unsigned int>(c - '0');
    182            ASSERT(digit < 10u);
    183            if (exponent <= (std::numeric_limits<int>::max() - 9) / 10)
    184            {
    185                exponent = exponent * 10 + digit;
    186            }
    187            else
    188            {
    189                exponentOutOfRange = true;
    190            }
    191            ++i;
    192        }
    193        if (negativeExponent)
    194        {
    195            exponent = -exponent;
    196        }
    197        if (exponentOutOfRange)
    198        {
    199            if (negativeExponent)
    200            {
    201                return 0.0f;
    202            }
    203            else
    204            {
    205                return std::numeric_limits<float>::infinity();
    206            }
    207        }
    208    }
    209    // Do the calculation in 64-bit to avoid overflow.
    210    long long exponentLong =
    211        static_cast<long long>(exponent) + static_cast<long long>(exponentOffset);
    212    if (exponentLong > std::numeric_limits<float>::max_exponent10)
    213    {
    214        return std::numeric_limits<float>::infinity();
    215    }
    216    else if (exponentLong < std::numeric_limits<float>::min_exponent10)
    217    {
    218        return 0.0f;
    219    }
    220    // The exponent is in range, so we need to actually evaluate the float.
    221    exponent     = static_cast<int>(exponentLong);
    222    double value = decimalMantissa;
    223 
    224    // Calculate the exponent offset to normalize the mantissa.
    225    int normalizationExponentOffset = 1 - mantissaDecimalDigits;
    226    // Apply the exponent.
    227    value *= std::pow(10.0, static_cast<double>(exponent + normalizationExponentOffset));
    228    if (value > static_cast<double>(std::numeric_limits<float>::max()))
    229    {
    230        return std::numeric_limits<float>::infinity();
    231    }
    232    if (value < static_cast<double>(std::numeric_limits<float>::min()))
    233    {
    234        return 0.0f;
    235    }
    236    return static_cast<float>(value);
    237 }
    238 
    239 bool strtof_clamp(const std::string &str, float *value)
    240 {
    241    // Custom float parsing that can handle the following corner cases:
    242    //   1. The decimal mantissa is very small but the exponent is very large, putting the resulting
    243    //   number inside the float range.
    244    //   2. The decimal mantissa is very large but the exponent is very small, putting the resulting
    245    //   number inside the float range.
    246    //   3. The value is out-of-range and should be evaluated as infinity.
    247    //   4. The value is too small and should be evaluated as zero.
    248    // See ESSL 3.00.6 section 4.1.4 for the relevant specification.
    249    *value = NumericLexFloat32OutOfRangeToInfinity(str);
    250    return !gl::isInf(*value);
    251 }
    252 
    253 GLenum GLVariableType(const TType &type)
    254 {
    255    switch (type.getBasicType())
    256    {
    257        case EbtFloat:
    258            ASSERT(type.getNominalSize() >= 1 && type.getNominalSize() <= 4);
    259            ASSERT(type.getSecondarySize() >= 1 && type.getSecondarySize() <= 4);
    260 
    261            return kFloatGLType[type.getNominalSize() - 1][type.getSecondarySize() - 1];
    262 
    263        case EbtInt:
    264            ASSERT(type.getNominalSize() >= 1 && type.getNominalSize() <= 4);
    265            ASSERT(type.getSecondarySize() == 1);
    266 
    267            return kIntGLType[type.getNominalSize() - 1];
    268 
    269        case EbtUInt:
    270            ASSERT(type.getNominalSize() >= 1 && type.getNominalSize() <= 4);
    271            ASSERT(type.getSecondarySize() == 1);
    272 
    273            return kUIntGLType[type.getNominalSize() - 1];
    274 
    275        case EbtBool:
    276            ASSERT(type.getNominalSize() >= 1 && type.getNominalSize() <= 4);
    277            ASSERT(type.getSecondarySize() == 1);
    278 
    279            return kBoolGLType[type.getNominalSize() - 1];
    280 
    281        case EbtSampler2D:
    282            return GL_SAMPLER_2D;
    283        case EbtSampler3D:
    284            return GL_SAMPLER_3D;
    285        case EbtSamplerCube:
    286            return GL_SAMPLER_CUBE;
    287        case EbtSamplerExternalOES:
    288            return GL_SAMPLER_EXTERNAL_OES;
    289        case EbtSamplerExternal2DY2YEXT:
    290            return GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT;
    291        case EbtSampler2DRect:
    292            return GL_SAMPLER_2D_RECT_ANGLE;
    293        case EbtSampler2DArray:
    294            return GL_SAMPLER_2D_ARRAY;
    295        case EbtSampler2DMS:
    296            return GL_SAMPLER_2D_MULTISAMPLE;
    297        case EbtSampler2DMSArray:
    298            return GL_SAMPLER_2D_MULTISAMPLE_ARRAY;
    299        case EbtSamplerCubeArray:
    300            return GL_SAMPLER_CUBE_MAP_ARRAY;
    301        case EbtSamplerBuffer:
    302            return GL_SAMPLER_BUFFER;
    303        case EbtISampler2D:
    304            return GL_INT_SAMPLER_2D;
    305        case EbtISampler3D:
    306            return GL_INT_SAMPLER_3D;
    307        case EbtISamplerCube:
    308            return GL_INT_SAMPLER_CUBE;
    309        case EbtISampler2DArray:
    310            return GL_INT_SAMPLER_2D_ARRAY;
    311        case EbtISampler2DMS:
    312            return GL_INT_SAMPLER_2D_MULTISAMPLE;
    313        case EbtISampler2DMSArray:
    314            return GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY;
    315        case EbtISamplerCubeArray:
    316            return GL_INT_SAMPLER_CUBE_MAP_ARRAY;
    317        case EbtISamplerBuffer:
    318            return GL_INT_SAMPLER_BUFFER;
    319        case EbtUSampler2D:
    320            return GL_UNSIGNED_INT_SAMPLER_2D;
    321        case EbtUSampler3D:
    322            return GL_UNSIGNED_INT_SAMPLER_3D;
    323        case EbtUSamplerCube:
    324            return GL_UNSIGNED_INT_SAMPLER_CUBE;
    325        case EbtUSampler2DArray:
    326            return GL_UNSIGNED_INT_SAMPLER_2D_ARRAY;
    327        case EbtUSampler2DMS:
    328            return GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE;
    329        case EbtUSampler2DMSArray:
    330            return GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY;
    331        case EbtUSamplerCubeArray:
    332            return GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY;
    333        case EbtUSamplerBuffer:
    334            return GL_UNSIGNED_INT_SAMPLER_BUFFER;
    335        case EbtSampler2DShadow:
    336            return GL_SAMPLER_2D_SHADOW;
    337        case EbtSamplerCubeShadow:
    338            return GL_SAMPLER_CUBE_SHADOW;
    339        case EbtSampler2DArrayShadow:
    340            return GL_SAMPLER_2D_ARRAY_SHADOW;
    341        case EbtSamplerCubeArrayShadow:
    342            return GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW;
    343        case EbtImage2D:
    344            return GL_IMAGE_2D;
    345        case EbtIImage2D:
    346            return GL_INT_IMAGE_2D;
    347        case EbtUImage2D:
    348            return GL_UNSIGNED_INT_IMAGE_2D;
    349        case EbtImage2DArray:
    350            return GL_IMAGE_2D_ARRAY;
    351        case EbtIImage2DArray:
    352            return GL_INT_IMAGE_2D_ARRAY;
    353        case EbtUImage2DArray:
    354            return GL_UNSIGNED_INT_IMAGE_2D_ARRAY;
    355        case EbtImage3D:
    356            return GL_IMAGE_3D;
    357        case EbtIImage3D:
    358            return GL_INT_IMAGE_3D;
    359        case EbtUImage3D:
    360            return GL_UNSIGNED_INT_IMAGE_3D;
    361        case EbtImageCube:
    362            return GL_IMAGE_CUBE;
    363        case EbtIImageCube:
    364            return GL_INT_IMAGE_CUBE;
    365        case EbtUImageCube:
    366            return GL_UNSIGNED_INT_IMAGE_CUBE;
    367        case EbtImageCubeArray:
    368            return GL_IMAGE_CUBE_MAP_ARRAY;
    369        case EbtIImageCubeArray:
    370            return GL_INT_IMAGE_CUBE_MAP_ARRAY;
    371        case EbtUImageCubeArray:
    372            return GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY;
    373        case EbtImageBuffer:
    374            return GL_IMAGE_BUFFER;
    375        case EbtIImageBuffer:
    376            return GL_INT_IMAGE_BUFFER;
    377        case EbtUImageBuffer:
    378            return GL_UNSIGNED_INT_IMAGE_BUFFER;
    379        case EbtAtomicCounter:
    380            return GL_UNSIGNED_INT_ATOMIC_COUNTER;
    381        case EbtSamplerVideoWEBGL:
    382            return GL_SAMPLER_VIDEO_IMAGE_WEBGL;
    383        case EbtPixelLocalANGLE:
    384        case EbtIPixelLocalANGLE:
    385        case EbtUPixelLocalANGLE:
    386            // TODO(anglebug.com/7279): For now, we can expect PLS handles to be rewritten to images
    387            // before anyone calls into here.
    388            [[fallthrough]];
    389        default:
    390            UNREACHABLE();
    391            return GL_NONE;
    392    }
    393 }
    394 
    395 GLenum GLVariablePrecision(const TType &type)
    396 {
    397    if (type.getBasicType() == EbtFloat)
    398    {
    399        switch (type.getPrecision())
    400        {
    401            case EbpHigh:
    402                return GL_HIGH_FLOAT;
    403            case EbpMedium:
    404                return GL_MEDIUM_FLOAT;
    405            case EbpLow:
    406                return GL_LOW_FLOAT;
    407            case EbpUndefined:
    408                // Desktop specs do not use precision
    409                return GL_NONE;
    410            default:
    411                UNREACHABLE();
    412        }
    413    }
    414    else if (type.getBasicType() == EbtInt || type.getBasicType() == EbtUInt)
    415    {
    416        switch (type.getPrecision())
    417        {
    418            case EbpHigh:
    419                return GL_HIGH_INT;
    420            case EbpMedium:
    421                return GL_MEDIUM_INT;
    422            case EbpLow:
    423                return GL_LOW_INT;
    424            case EbpUndefined:
    425                // Desktop specs do not use precision
    426                return GL_NONE;
    427            default:
    428                UNREACHABLE();
    429        }
    430    }
    431 
    432    // Other types (boolean, sampler) don't have a precision
    433    return GL_NONE;
    434 }
    435 
    436 ImmutableString ArrayString(const TType &type)
    437 {
    438    if (!type.isArray())
    439        return ImmutableString("");
    440 
    441    const TSpan<const unsigned int> &arraySizes     = type.getArraySizes();
    442    constexpr const size_t kMaxDecimalDigitsPerSize = 10u;
    443    ImmutableStringBuilder arrayString(arraySizes.size() * (kMaxDecimalDigitsPerSize + 2u));
    444    for (auto arraySizeIter = arraySizes.rbegin(); arraySizeIter != arraySizes.rend();
    445         ++arraySizeIter)
    446    {
    447        arrayString << "[";
    448        if (*arraySizeIter > 0)
    449        {
    450            arrayString.appendDecimal(*arraySizeIter);
    451        }
    452        arrayString << "]";
    453    }
    454    return arrayString;
    455 }
    456 
    457 ImmutableString GetTypeName(const TType &type, ShHashFunction64 hashFunction, NameMap *nameMap)
    458 {
    459    if (type.getBasicType() == EbtStruct)
    460        return HashName(type.getStruct(), hashFunction, nameMap);
    461    else
    462        return ImmutableString(type.getBuiltInTypeNameString());
    463 }
    464 
    465 bool IsVaryingOut(TQualifier qualifier)
    466 {
    467    switch (qualifier)
    468    {
    469        case EvqVaryingOut:
    470        case EvqSmoothOut:
    471        case EvqFlatOut:
    472        case EvqNoPerspectiveOut:
    473        case EvqCentroidOut:
    474        case EvqVertexOut:
    475        case EvqGeometryOut:
    476        case EvqTessControlOut:
    477        case EvqTessEvaluationOut:
    478        case EvqSampleOut:
    479        case EvqPatchOut:
    480            return true;
    481 
    482        default:
    483            break;
    484    }
    485 
    486    return false;
    487 }
    488 
    489 bool IsVaryingIn(TQualifier qualifier)
    490 {
    491    switch (qualifier)
    492    {
    493        case EvqVaryingIn:
    494        case EvqSmoothIn:
    495        case EvqFlatIn:
    496        case EvqNoPerspectiveIn:
    497        case EvqCentroidIn:
    498        case EvqFragmentIn:
    499        case EvqGeometryIn:
    500        case EvqTessControlIn:
    501        case EvqTessEvaluationIn:
    502        case EvqSampleIn:
    503        case EvqPatchIn:
    504            return true;
    505 
    506        default:
    507            break;
    508    }
    509 
    510    return false;
    511 }
    512 
    513 bool IsVarying(TQualifier qualifier)
    514 {
    515    return IsVaryingIn(qualifier) || IsVaryingOut(qualifier);
    516 }
    517 
    518 bool IsMatrixGLType(GLenum type)
    519 {
    520    switch (type)
    521    {
    522        case GL_FLOAT_MAT2:
    523        case GL_FLOAT_MAT3:
    524        case GL_FLOAT_MAT4:
    525        case GL_FLOAT_MAT2x3:
    526        case GL_FLOAT_MAT2x4:
    527        case GL_FLOAT_MAT3x2:
    528        case GL_FLOAT_MAT3x4:
    529        case GL_FLOAT_MAT4x2:
    530        case GL_FLOAT_MAT4x3:
    531            return true;
    532        default:
    533            return false;
    534    }
    535 }
    536 
    537 bool IsGeometryShaderInput(GLenum shaderType, TQualifier qualifier)
    538 {
    539    return (qualifier == EvqGeometryIn) ||
    540           ((shaderType == GL_GEOMETRY_SHADER_EXT) && IsInterpolationIn(qualifier));
    541 }
    542 
    543 bool IsTessellationControlShaderInput(GLenum shaderType, TQualifier qualifier)
    544 {
    545    return qualifier == EvqTessControlIn ||
    546           ((shaderType == GL_TESS_CONTROL_SHADER) && IsInterpolationIn(qualifier));
    547 }
    548 
    549 bool IsTessellationControlShaderOutput(GLenum shaderType, TQualifier qualifier)
    550 {
    551    return qualifier == EvqTessControlOut ||
    552           ((shaderType == GL_TESS_CONTROL_SHADER) && IsInterpolationOut(qualifier));
    553 }
    554 
    555 bool IsTessellationEvaluationShaderInput(GLenum shaderType, TQualifier qualifier)
    556 {
    557    return qualifier == EvqTessEvaluationIn ||
    558           ((shaderType == GL_TESS_EVALUATION_SHADER) && IsInterpolationIn(qualifier));
    559 }
    560 
    561 InterpolationType GetInterpolationType(TQualifier qualifier)
    562 {
    563    switch (qualifier)
    564    {
    565        case EvqFlatIn:
    566        case EvqFlatOut:
    567        // The auxiliary storage qualifier patch is not used for interpolation
    568        // it is a compile-time error to use interpolation qualifiers with patch
    569        case EvqPatchIn:
    570        case EvqPatchOut:
    571            return INTERPOLATION_FLAT;
    572 
    573        case EvqNoPerspectiveIn:
    574        case EvqNoPerspectiveOut:
    575            return INTERPOLATION_NOPERSPECTIVE;
    576 
    577        case EvqSmoothIn:
    578        case EvqSmoothOut:
    579        case EvqVertexOut:
    580        case EvqFragmentIn:
    581        case EvqVaryingIn:
    582        case EvqVaryingOut:
    583        case EvqGeometryIn:
    584        case EvqGeometryOut:
    585        case EvqTessControlIn:
    586        case EvqTessControlOut:
    587        case EvqTessEvaluationIn:
    588        case EvqTessEvaluationOut:
    589            return INTERPOLATION_SMOOTH;
    590 
    591        case EvqCentroidIn:
    592        case EvqCentroidOut:
    593            return INTERPOLATION_CENTROID;
    594 
    595        case EvqSampleIn:
    596        case EvqSampleOut:
    597            return INTERPOLATION_SAMPLE;
    598        default:
    599            UNREACHABLE();
    600            return INTERPOLATION_SMOOTH;
    601    }
    602 }
    603 
    604 // a field may not have qualifer without in or out.
    605 InterpolationType GetFieldInterpolationType(TQualifier qualifier)
    606 {
    607    switch (qualifier)
    608    {
    609        case EvqFlat:
    610            return INTERPOLATION_FLAT;
    611        case EvqNoPerspective:
    612            return INTERPOLATION_NOPERSPECTIVE;
    613        case EvqSmooth:
    614            return INTERPOLATION_SMOOTH;
    615        case EvqCentroid:
    616            return INTERPOLATION_CENTROID;
    617        default:
    618            return GetInterpolationType(qualifier);
    619    }
    620 }
    621 
    622 TType GetShaderVariableBasicType(const sh::ShaderVariable &var)
    623 {
    624    switch (var.type)
    625    {
    626        case GL_BOOL:
    627            return TType(EbtBool);
    628        case GL_BOOL_VEC2:
    629            return TType(EbtBool, 2);
    630        case GL_BOOL_VEC3:
    631            return TType(EbtBool, 3);
    632        case GL_BOOL_VEC4:
    633            return TType(EbtBool, 4);
    634        case GL_FLOAT:
    635            return TType(EbtFloat);
    636        case GL_FLOAT_VEC2:
    637            return TType(EbtFloat, 2);
    638        case GL_FLOAT_VEC3:
    639            return TType(EbtFloat, 3);
    640        case GL_FLOAT_VEC4:
    641            return TType(EbtFloat, 4);
    642        case GL_FLOAT_MAT2:
    643            return TType(EbtFloat, 2, 2);
    644        case GL_FLOAT_MAT3:
    645            return TType(EbtFloat, 3, 3);
    646        case GL_FLOAT_MAT4:
    647            return TType(EbtFloat, 4, 4);
    648        case GL_FLOAT_MAT2x3:
    649            return TType(EbtFloat, 2, 3);
    650        case GL_FLOAT_MAT2x4:
    651            return TType(EbtFloat, 2, 4);
    652        case GL_FLOAT_MAT3x2:
    653            return TType(EbtFloat, 3, 2);
    654        case GL_FLOAT_MAT3x4:
    655            return TType(EbtFloat, 3, 4);
    656        case GL_FLOAT_MAT4x2:
    657            return TType(EbtFloat, 4, 2);
    658        case GL_FLOAT_MAT4x3:
    659            return TType(EbtFloat, 4, 3);
    660        case GL_INT:
    661            return TType(EbtInt);
    662        case GL_INT_VEC2:
    663            return TType(EbtInt, 2);
    664        case GL_INT_VEC3:
    665            return TType(EbtInt, 3);
    666        case GL_INT_VEC4:
    667            return TType(EbtInt, 4);
    668        case GL_UNSIGNED_INT:
    669            return TType(EbtUInt);
    670        case GL_UNSIGNED_INT_VEC2:
    671            return TType(EbtUInt, 2);
    672        case GL_UNSIGNED_INT_VEC3:
    673            return TType(EbtUInt, 3);
    674        case GL_UNSIGNED_INT_VEC4:
    675            return TType(EbtUInt, 4);
    676        default:
    677            UNREACHABLE();
    678            return TType();
    679    }
    680 }
    681 
    682 void DeclareGlobalVariable(TIntermBlock *root, const TVariable *variable)
    683 {
    684    TIntermDeclaration *declaration = new TIntermDeclaration();
    685    declaration->appendDeclarator(new TIntermSymbol(variable));
    686 
    687    TIntermSequence *globalSequence = root->getSequence();
    688    globalSequence->insert(globalSequence->begin(), declaration);
    689 }
    690 
    691 // GLSL ES 1.0.17 4.6.1 The Invariant Qualifier
    692 bool CanBeInvariantESSL1(TQualifier qualifier)
    693 {
    694    return IsVaryingIn(qualifier) || IsVaryingOut(qualifier) ||
    695           IsBuiltinOutputVariable(qualifier) ||
    696           (IsBuiltinFragmentInputVariable(qualifier) && qualifier != EvqFrontFacing);
    697 }
    698 
    699 // GLSL ES 3.00 Revision 6, 4.6.1 The Invariant Qualifier
    700 // GLSL ES 3.10 Revision 4, 4.8.1 The Invariant Qualifier
    701 bool CanBeInvariantESSL3OrGreater(TQualifier qualifier)
    702 {
    703    return IsVaryingOut(qualifier) || qualifier == EvqFragmentOut ||
    704           IsBuiltinOutputVariable(qualifier) || qualifier == EvqFragmentInOut;
    705 }
    706 
    707 bool IsBuiltinOutputVariable(TQualifier qualifier)
    708 {
    709    switch (qualifier)
    710    {
    711        case EvqPosition:
    712        case EvqPointSize:
    713        case EvqFragDepth:
    714        case EvqFragColor:
    715        case EvqSecondaryFragColorEXT:
    716        case EvqFragData:
    717        case EvqSecondaryFragDataEXT:
    718        case EvqClipDistance:
    719        case EvqCullDistance:
    720        case EvqLastFragData:
    721        case EvqSampleMask:
    722            return true;
    723        default:
    724            break;
    725    }
    726    return false;
    727 }
    728 
    729 bool IsBuiltinFragmentInputVariable(TQualifier qualifier)
    730 {
    731    switch (qualifier)
    732    {
    733        case EvqFragCoord:
    734        case EvqPointCoord:
    735        case EvqFrontFacing:
    736        case EvqHelperInvocation:
    737        case EvqLastFragData:
    738            return true;
    739        default:
    740            break;
    741    }
    742    return false;
    743 }
    744 
    745 bool IsShaderOutput(TQualifier qualifier)
    746 {
    747    return IsVaryingOut(qualifier) || IsBuiltinOutputVariable(qualifier);
    748 }
    749 
    750 bool IsFragmentOutput(TQualifier qualifier)
    751 {
    752    switch (qualifier)
    753    {
    754        case EvqFragmentOut:
    755        case EvqFragmentInOut:
    756            return true;
    757        default:
    758            return false;
    759    }
    760 }
    761 
    762 bool IsOutputESSL(ShShaderOutput output)
    763 {
    764    return output == SH_ESSL_OUTPUT;
    765 }
    766 
    767 bool IsOutputGLSL(ShShaderOutput output)
    768 {
    769    switch (output)
    770    {
    771        case SH_GLSL_130_OUTPUT:
    772        case SH_GLSL_140_OUTPUT:
    773        case SH_GLSL_150_CORE_OUTPUT:
    774        case SH_GLSL_330_CORE_OUTPUT:
    775        case SH_GLSL_400_CORE_OUTPUT:
    776        case SH_GLSL_410_CORE_OUTPUT:
    777        case SH_GLSL_420_CORE_OUTPUT:
    778        case SH_GLSL_430_CORE_OUTPUT:
    779        case SH_GLSL_440_CORE_OUTPUT:
    780        case SH_GLSL_450_CORE_OUTPUT:
    781        case SH_GLSL_COMPATIBILITY_OUTPUT:
    782            return true;
    783        default:
    784            break;
    785    }
    786    return false;
    787 }
    788 bool IsOutputHLSL(ShShaderOutput output)
    789 {
    790    switch (output)
    791    {
    792        case SH_HLSL_3_0_OUTPUT:
    793        case SH_HLSL_4_1_OUTPUT:
    794        case SH_HLSL_4_0_FL9_3_OUTPUT:
    795            return true;
    796        default:
    797            break;
    798    }
    799    return false;
    800 }
    801 bool IsOutputVulkan(ShShaderOutput output)
    802 {
    803    return output == SH_SPIRV_VULKAN_OUTPUT;
    804 }
    805 bool IsOutputMetal(ShShaderOutput output)
    806 {
    807    return output == SH_SPIRV_METAL_OUTPUT;
    808 }
    809 bool IsOutputMetalDirect(ShShaderOutput output)
    810 {
    811    return output == SH_MSL_METAL_OUTPUT;
    812 }
    813 
    814 bool IsInShaderStorageBlock(TIntermTyped *node)
    815 {
    816    TIntermSwizzle *swizzleNode = node->getAsSwizzleNode();
    817    if (swizzleNode)
    818    {
    819        return IsInShaderStorageBlock(swizzleNode->getOperand());
    820    }
    821 
    822    TIntermBinary *binaryNode = node->getAsBinaryNode();
    823    if (binaryNode)
    824    {
    825        switch (binaryNode->getOp())
    826        {
    827            case EOpIndexDirectInterfaceBlock:
    828            case EOpIndexIndirect:
    829            case EOpIndexDirect:
    830            case EOpIndexDirectStruct:
    831                return IsInShaderStorageBlock(binaryNode->getLeft());
    832            default:
    833                return false;
    834        }
    835    }
    836 
    837    const TType &type = node->getType();
    838    return type.getQualifier() == EvqBuffer;
    839 }
    840 
    841 GLenum GetImageInternalFormatType(TLayoutImageInternalFormat iifq)
    842 {
    843    switch (iifq)
    844    {
    845        case EiifRGBA32F:
    846            return GL_RGBA32F;
    847        case EiifRGBA16F:
    848            return GL_RGBA16F;
    849        case EiifR32F:
    850            return GL_R32F;
    851        case EiifRGBA32UI:
    852            return GL_RGBA32UI;
    853        case EiifRGBA16UI:
    854            return GL_RGBA16UI;
    855        case EiifRGBA8UI:
    856            return GL_RGBA8UI;
    857        case EiifR32UI:
    858            return GL_R32UI;
    859        case EiifRGBA32I:
    860            return GL_RGBA32I;
    861        case EiifRGBA16I:
    862            return GL_RGBA16I;
    863        case EiifRGBA8I:
    864            return GL_RGBA8I;
    865        case EiifR32I:
    866            return GL_R32I;
    867        case EiifRGBA8:
    868            return GL_RGBA8;
    869        case EiifRGBA8_SNORM:
    870            return GL_RGBA8_SNORM;
    871        default:
    872            return GL_NONE;
    873    }
    874 }
    875 
    876 bool IsSpecWithFunctionBodyNewScope(ShShaderSpec shaderSpec, int shaderVersion)
    877 {
    878    return (shaderVersion == 100 && !sh::IsWebGLBasedSpec(shaderSpec));
    879 }
    880 
    881 ImplicitTypeConversion GetConversion(TBasicType t1, TBasicType t2)
    882 {
    883    if (t1 == t2)
    884        return ImplicitTypeConversion::Same;
    885 
    886    switch (t1)
    887    {
    888        case EbtInt:
    889            switch (t2)
    890            {
    891                case EbtInt:
    892                    UNREACHABLE();
    893                    break;
    894                case EbtUInt:
    895                    return ImplicitTypeConversion::Invalid;
    896                case EbtFloat:
    897                    return ImplicitTypeConversion::Left;
    898                default:
    899                    return ImplicitTypeConversion::Invalid;
    900            }
    901            break;
    902        case EbtUInt:
    903            switch (t2)
    904            {
    905                case EbtInt:
    906                    return ImplicitTypeConversion::Invalid;
    907                case EbtUInt:
    908                    UNREACHABLE();
    909                    break;
    910                case EbtFloat:
    911                    return ImplicitTypeConversion::Left;
    912                default:
    913                    return ImplicitTypeConversion::Invalid;
    914            }
    915            break;
    916        case EbtFloat:
    917            switch (t2)
    918            {
    919                case EbtInt:
    920                case EbtUInt:
    921                    return ImplicitTypeConversion::Right;
    922                case EbtFloat:
    923                    UNREACHABLE();
    924                    break;
    925                default:
    926                    return ImplicitTypeConversion::Invalid;
    927            }
    928            break;
    929        default:
    930            return ImplicitTypeConversion::Invalid;
    931    }
    932    return ImplicitTypeConversion::Invalid;
    933 }
    934 
    935 bool IsValidImplicitConversion(sh::ImplicitTypeConversion conversion, TOperator op)
    936 {
    937    switch (conversion)
    938    {
    939        case sh::ImplicitTypeConversion::Same:
    940            return true;
    941        case sh::ImplicitTypeConversion::Left:
    942            switch (op)
    943            {
    944                case EOpEqual:
    945                case EOpNotEqual:
    946                case EOpLessThan:
    947                case EOpGreaterThan:
    948                case EOpLessThanEqual:
    949                case EOpGreaterThanEqual:
    950                case EOpAdd:
    951                case EOpSub:
    952                case EOpMul:
    953                case EOpDiv:
    954                    return true;
    955                default:
    956                    break;
    957            }
    958            break;
    959        case sh::ImplicitTypeConversion::Right:
    960            switch (op)
    961            {
    962                case EOpAssign:
    963                case EOpInitialize:
    964                case EOpEqual:
    965                case EOpNotEqual:
    966                case EOpLessThan:
    967                case EOpGreaterThan:
    968                case EOpLessThanEqual:
    969                case EOpGreaterThanEqual:
    970                case EOpAdd:
    971                case EOpSub:
    972                case EOpMul:
    973                case EOpDiv:
    974                case EOpAddAssign:
    975                case EOpSubAssign:
    976                case EOpMulAssign:
    977                case EOpDivAssign:
    978                    return true;
    979                default:
    980                    break;
    981            }
    982            break;
    983        case sh::ImplicitTypeConversion::Invalid:
    984            break;
    985    }
    986    return false;
    987 }
    988 
    989 bool IsPrecisionApplicableToType(TBasicType type)
    990 {
    991    switch (type)
    992    {
    993        case EbtInt:
    994        case EbtUInt:
    995        case EbtFloat:
    996            // TODO: find all types where precision is applicable; for example samplers.
    997            // http://anglebug.com/6132
    998            return true;
    999        default:
   1000            return false;
   1001    }
   1002 }
   1003 
   1004 bool IsRedeclarableBuiltIn(const ImmutableString &name)
   1005 {
   1006    return name == "gl_ClipDistance" || name == "gl_CullDistance" || name == "gl_LastFragData" ||
   1007           name == "gl_PerVertex" || name == "gl_Position" || name == "gl_PointSize";
   1008 }
   1009 
   1010 size_t FindFieldIndex(const TFieldList &fieldList, const char *fieldName)
   1011 {
   1012    for (size_t fieldIndex = 0; fieldIndex < fieldList.size(); ++fieldIndex)
   1013    {
   1014        if (strcmp(fieldList[fieldIndex]->name().data(), fieldName) == 0)
   1015        {
   1016            return fieldIndex;
   1017        }
   1018    }
   1019    UNREACHABLE();
   1020    return 0;
   1021 }
   1022 
   1023 }  // namespace sh