tor-browser

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

ProgramLinkedResources.cpp (89034B)


      1 //
      2 // Copyright 2017 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 // ProgramLinkedResources.cpp: implements link-time checks for default block uniforms, and generates
      8 // uniform locations. Populates data structures related to uniforms so that they can be stored in
      9 // program state.
     10 
     11 #include "libANGLE/ProgramLinkedResources.h"
     12 
     13 #include "common/string_utils.h"
     14 #include "common/utilities.h"
     15 #include "libANGLE/Caps.h"
     16 #include "libANGLE/Context.h"
     17 #include "libANGLE/Shader.h"
     18 #include "libANGLE/features.h"
     19 
     20 namespace gl
     21 {
     22 namespace
     23 {
     24 LinkedUniform *FindUniform(std::vector<LinkedUniform> &list, const std::string &name)
     25 {
     26    for (LinkedUniform &uniform : list)
     27    {
     28        if (uniform.name == name)
     29            return &uniform;
     30    }
     31 
     32    return nullptr;
     33 }
     34 
     35 template <typename VarT>
     36 void SetActive(std::vector<VarT> *list, const std::string &name, ShaderType shaderType, bool active)
     37 {
     38    for (auto &variable : *list)
     39    {
     40        if (variable.name == name)
     41        {
     42            variable.setActive(shaderType, active);
     43            return;
     44        }
     45    }
     46 }
     47 
     48 // GLSL ES Spec 3.00.3, section 4.3.5.
     49 LinkMismatchError LinkValidateUniforms(const sh::ShaderVariable &uniform1,
     50                                       const sh::ShaderVariable &uniform2,
     51                                       std::string *mismatchedStructFieldName)
     52 {
     53 #if ANGLE_PROGRAM_LINK_VALIDATE_UNIFORM_PRECISION == ANGLE_ENABLED
     54    const bool validatePrecisionFeature = true;
     55 #else
     56    const bool validatePrecisionFeature = false;
     57 #endif
     58 
     59    // Validate precision match of uniforms iff they are statically used
     60    bool validatePrecision = uniform1.staticUse && uniform2.staticUse && validatePrecisionFeature;
     61    LinkMismatchError linkError = LinkValidateProgramVariables(
     62        uniform1, uniform2, validatePrecision, false, false, mismatchedStructFieldName);
     63    if (linkError != LinkMismatchError::NO_MISMATCH)
     64    {
     65        return linkError;
     66    }
     67 
     68    // GLSL ES Spec 3.10.4, section 4.4.5.
     69    if (uniform1.binding != -1 && uniform2.binding != -1 && uniform1.binding != uniform2.binding)
     70    {
     71        return LinkMismatchError::BINDING_MISMATCH;
     72    }
     73 
     74    // GLSL ES Spec 3.10.4, section 9.2.1.
     75    if (uniform1.location != -1 && uniform2.location != -1 &&
     76        uniform1.location != uniform2.location)
     77    {
     78        return LinkMismatchError::LOCATION_MISMATCH;
     79    }
     80    if (uniform1.offset != uniform2.offset)
     81    {
     82        return LinkMismatchError::OFFSET_MISMATCH;
     83    }
     84 
     85    return LinkMismatchError::NO_MISMATCH;
     86 }
     87 
     88 GLuint GetMaximumShaderUniformVectors(ShaderType shaderType, const Caps &caps)
     89 {
     90    switch (shaderType)
     91    {
     92        case ShaderType::Vertex:
     93            return static_cast<GLuint>(caps.maxVertexUniformVectors);
     94        case ShaderType::Fragment:
     95            return static_cast<GLuint>(caps.maxFragmentUniformVectors);
     96 
     97        case ShaderType::Compute:
     98        case ShaderType::Geometry:
     99        case ShaderType::TessControl:
    100        case ShaderType::TessEvaluation:
    101            return static_cast<GLuint>(caps.maxShaderUniformComponents[shaderType]) / 4;
    102 
    103        default:
    104            UNREACHABLE();
    105            return 0u;
    106    }
    107 }
    108 
    109 enum class UniformType : uint8_t
    110 {
    111    Variable      = 0,
    112    Sampler       = 1,
    113    Image         = 2,
    114    AtomicCounter = 3,
    115 
    116    InvalidEnum = 4,
    117    EnumCount   = 4,
    118 };
    119 
    120 const char *GetUniformResourceNameString(UniformType uniformType)
    121 {
    122    switch (uniformType)
    123    {
    124        case UniformType::Variable:
    125            return "uniform";
    126        case UniformType::Sampler:
    127            return "texture image unit";
    128        case UniformType::Image:
    129            return "image uniform";
    130        case UniformType::AtomicCounter:
    131            return "atomic counter";
    132        default:
    133            UNREACHABLE();
    134            return "";
    135    }
    136 }
    137 
    138 std::string GetUniformResourceLimitName(ShaderType shaderType, UniformType uniformType)
    139 {
    140    // Special case: MAX_TEXTURE_IMAGE_UNITS (no "MAX_FRAGMENT_TEXTURE_IMAGE_UNITS")
    141    if (shaderType == ShaderType::Fragment && uniformType == UniformType::Sampler)
    142    {
    143        return "MAX_TEXTURE_IMAGE_UNITS";
    144    }
    145 
    146    std::ostringstream ostream;
    147    ostream << "MAX_" << GetShaderTypeString(shaderType) << "_";
    148 
    149    switch (uniformType)
    150    {
    151        case UniformType::Variable:
    152            // For vertex and fragment shaders, ES 2.0 only defines MAX_VERTEX_UNIFORM_VECTORS and
    153            // MAX_FRAGMENT_UNIFORM_VECTORS ([OpenGL ES 2.0] Table 6.20).
    154            if (shaderType == ShaderType::Vertex || shaderType == ShaderType::Fragment)
    155            {
    156                ostream << "UNIFORM_VECTORS";
    157                break;
    158            }
    159            // For compute and geometry shaders, there are no definitions on
    160            // "MAX_COMPUTE_UNIFORM_VECTORS" or "MAX_GEOMETRY_UNIFORM_VECTORS_EXT"
    161            // ([OpenGL ES 3.1] Table 20.45, [EXT_geometry_shader] Table 20.43gs).
    162            else
    163            {
    164                ostream << "UNIFORM_COMPONENTS";
    165            }
    166            break;
    167        case UniformType::Sampler:
    168            ostream << "TEXTURE_IMAGE_UNITS";
    169            break;
    170        case UniformType::Image:
    171            ostream << "IMAGE_UNIFORMS";
    172            break;
    173        case UniformType::AtomicCounter:
    174            ostream << "ATOMIC_COUNTERS";
    175            break;
    176        default:
    177            UNREACHABLE();
    178            return "";
    179    }
    180 
    181    if (shaderType == ShaderType::Geometry)
    182    {
    183        ostream << "_EXT";
    184    }
    185 
    186    return ostream.str();
    187 }
    188 
    189 void LogUniformsExceedLimit(ShaderType shaderType,
    190                            UniformType uniformType,
    191                            GLuint limit,
    192                            InfoLog &infoLog)
    193 {
    194    infoLog << GetShaderTypeString(shaderType) << " shader "
    195            << GetUniformResourceNameString(uniformType) << "s count exceeds "
    196            << GetUniformResourceLimitName(shaderType, uniformType) << "(" << limit << ")";
    197 }
    198 
    199 // The purpose of this visitor is to capture the uniforms in a uniform block. Each new uniform is
    200 // added to "uniformsOut".
    201 class UniformBlockEncodingVisitor : public sh::VariableNameVisitor
    202 {
    203  public:
    204    UniformBlockEncodingVisitor(const GetBlockMemberInfoFunc &getMemberInfo,
    205                                const std::string &namePrefix,
    206                                const std::string &mappedNamePrefix,
    207                                std::vector<LinkedUniform> *uniformsOut,
    208                                ShaderType shaderType,
    209                                int blockIndex)
    210        : sh::VariableNameVisitor(namePrefix, mappedNamePrefix),
    211          mGetMemberInfo(getMemberInfo),
    212          mUniformsOut(uniformsOut),
    213          mShaderType(shaderType),
    214          mBlockIndex(blockIndex)
    215    {}
    216 
    217    void visitNamedVariable(const sh::ShaderVariable &variable,
    218                            bool isRowMajor,
    219                            const std::string &name,
    220                            const std::string &mappedName,
    221                            const std::vector<unsigned int> &arraySizes) override
    222    {
    223        // If getBlockMemberInfo returns false, the variable is optimized out.
    224        sh::BlockMemberInfo variableInfo;
    225        if (!mGetMemberInfo(name, mappedName, &variableInfo))
    226            return;
    227 
    228        std::string nameWithArrayIndex       = name;
    229        std::string mappedNameWithArrayIndex = mappedName;
    230 
    231        if (variable.isArray())
    232        {
    233            nameWithArrayIndex += "[0]";
    234            mappedNameWithArrayIndex += "[0]";
    235        }
    236 
    237        if (mBlockIndex == -1)
    238        {
    239            SetActive(mUniformsOut, nameWithArrayIndex, mShaderType, variable.active);
    240            return;
    241        }
    242 
    243        LinkedUniform newUniform(variable.type, variable.precision, nameWithArrayIndex,
    244                                 variable.arraySizes, -1, -1, -1, mBlockIndex, variableInfo);
    245        newUniform.mappedName = mappedNameWithArrayIndex;
    246        newUniform.setActive(mShaderType, variable.active);
    247 
    248        // Since block uniforms have no location, we don't need to store them in the uniform
    249        // locations list.
    250        mUniformsOut->push_back(newUniform);
    251    }
    252 
    253  private:
    254    const GetBlockMemberInfoFunc &mGetMemberInfo;
    255    std::vector<LinkedUniform> *mUniformsOut;
    256    const ShaderType mShaderType;
    257    const int mBlockIndex;
    258 };
    259 
    260 // The purpose of this visitor is to capture the buffer variables in a shader storage block. Each
    261 // new buffer variable is stored in "bufferVariablesOut".
    262 class ShaderStorageBlockVisitor : public sh::BlockEncoderVisitor
    263 {
    264  public:
    265    ShaderStorageBlockVisitor(const GetBlockMemberInfoFunc &getMemberInfo,
    266                              const std::string &namePrefix,
    267                              const std::string &mappedNamePrefix,
    268                              std::vector<BufferVariable> *bufferVariablesOut,
    269                              ShaderType shaderType,
    270                              int blockIndex)
    271        : sh::BlockEncoderVisitor(namePrefix, mappedNamePrefix, &mStubEncoder),
    272          mGetMemberInfo(getMemberInfo),
    273          mBufferVariablesOut(bufferVariablesOut),
    274          mShaderType(shaderType),
    275          mBlockIndex(blockIndex)
    276    {}
    277 
    278    void visitNamedVariable(const sh::ShaderVariable &variable,
    279                            bool isRowMajor,
    280                            const std::string &name,
    281                            const std::string &mappedName,
    282                            const std::vector<unsigned int> &arraySizes) override
    283    {
    284        if (mSkipEnabled)
    285            return;
    286 
    287        // If getBlockMemberInfo returns false, the variable is optimized out.
    288        sh::BlockMemberInfo variableInfo;
    289        if (!mGetMemberInfo(name, mappedName, &variableInfo))
    290            return;
    291 
    292        std::string nameWithArrayIndex       = name;
    293        std::string mappedNameWithArrayIndex = mappedName;
    294 
    295        if (variable.isArray())
    296        {
    297            nameWithArrayIndex += "[0]";
    298            mappedNameWithArrayIndex += "[0]";
    299        }
    300 
    301        if (mBlockIndex == -1)
    302        {
    303            SetActive(mBufferVariablesOut, nameWithArrayIndex, mShaderType, variable.active);
    304            return;
    305        }
    306 
    307        BufferVariable newBufferVariable(variable.type, variable.precision, nameWithArrayIndex,
    308                                         variable.arraySizes, mBlockIndex, variableInfo);
    309        newBufferVariable.mappedName = mappedNameWithArrayIndex;
    310        newBufferVariable.setActive(mShaderType, variable.active);
    311 
    312        newBufferVariable.topLevelArraySize = mTopLevelArraySize;
    313 
    314        mBufferVariablesOut->push_back(newBufferVariable);
    315    }
    316 
    317  private:
    318    const GetBlockMemberInfoFunc &mGetMemberInfo;
    319    std::vector<BufferVariable> *mBufferVariablesOut;
    320    const ShaderType mShaderType;
    321    const int mBlockIndex;
    322    sh::StubBlockEncoder mStubEncoder;
    323 };
    324 
    325 struct ShaderUniformCount
    326 {
    327    unsigned int vectorCount        = 0;
    328    unsigned int samplerCount       = 0;
    329    unsigned int imageCount         = 0;
    330    unsigned int atomicCounterCount = 0;
    331    unsigned int fragmentInOutCount = 0;
    332 };
    333 
    334 ShaderUniformCount &operator+=(ShaderUniformCount &lhs, const ShaderUniformCount &rhs)
    335 {
    336    lhs.vectorCount += rhs.vectorCount;
    337    lhs.samplerCount += rhs.samplerCount;
    338    lhs.imageCount += rhs.imageCount;
    339    lhs.atomicCounterCount += rhs.atomicCounterCount;
    340    lhs.fragmentInOutCount += rhs.fragmentInOutCount;
    341    return lhs;
    342 }
    343 
    344 // The purpose of this visitor is to flatten struct and array uniforms into a list of singleton
    345 // uniforms. They are stored in separate lists by uniform type so they can be sorted in order.
    346 // Counts for each uniform category are stored and can be queried with "getCounts".
    347 class FlattenUniformVisitor : public sh::VariableNameVisitor
    348 {
    349  public:
    350    FlattenUniformVisitor(ShaderType shaderType,
    351                          const sh::ShaderVariable &uniform,
    352                          std::vector<LinkedUniform> *uniforms,
    353                          std::vector<LinkedUniform> *samplerUniforms,
    354                          std::vector<LinkedUniform> *imageUniforms,
    355                          std::vector<LinkedUniform> *atomicCounterUniforms,
    356                          std::vector<LinkedUniform> *inputAttachmentUniforms,
    357                          std::vector<UnusedUniform> *unusedUniforms)
    358        : sh::VariableNameVisitor("", ""),
    359          mShaderType(shaderType),
    360          mMarkActive(uniform.active),
    361          mMarkStaticUse(uniform.staticUse),
    362          mBinding(uniform.binding),
    363          mOffset(uniform.offset),
    364          mLocation(uniform.location),
    365          mUniforms(uniforms),
    366          mSamplerUniforms(samplerUniforms),
    367          mImageUniforms(imageUniforms),
    368          mAtomicCounterUniforms(atomicCounterUniforms),
    369          mInputAttachmentUniforms(inputAttachmentUniforms),
    370          mUnusedUniforms(unusedUniforms)
    371    {}
    372 
    373    void visitNamedOpaqueObject(const sh::ShaderVariable &variable,
    374                                const std::string &name,
    375                                const std::string &mappedName,
    376                                const std::vector<unsigned int> &arraySizes) override
    377    {
    378        visitNamedVariable(variable, false, name, mappedName, arraySizes);
    379    }
    380 
    381    void visitNamedVariable(const sh::ShaderVariable &variable,
    382                            bool isRowMajor,
    383                            const std::string &name,
    384                            const std::string &mappedName,
    385                            const std::vector<unsigned int> &arraySizes) override
    386    {
    387        bool isSampler                          = IsSamplerType(variable.type);
    388        bool isImage                            = IsImageType(variable.type);
    389        bool isAtomicCounter                    = IsAtomicCounterType(variable.type);
    390        bool isFragmentInOut                    = variable.isFragmentInOut;
    391        std::vector<LinkedUniform> *uniformList = mUniforms;
    392        if (isSampler)
    393        {
    394            uniformList = mSamplerUniforms;
    395        }
    396        else if (isImage)
    397        {
    398            uniformList = mImageUniforms;
    399        }
    400        else if (isAtomicCounter)
    401        {
    402            uniformList = mAtomicCounterUniforms;
    403        }
    404        else if (isFragmentInOut)
    405        {
    406            uniformList = mInputAttachmentUniforms;
    407        }
    408 
    409        std::string fullNameWithArrayIndex(name);
    410        std::string fullMappedNameWithArrayIndex(mappedName);
    411 
    412        if (variable.isArray())
    413        {
    414            // We're following the GLES 3.1 November 2016 spec section 7.3.1.1 Naming Active
    415            // Resources and including [0] at the end of array variable names.
    416            fullNameWithArrayIndex += "[0]";
    417            fullMappedNameWithArrayIndex += "[0]";
    418        }
    419 
    420        LinkedUniform *existingUniform = FindUniform(*uniformList, fullNameWithArrayIndex);
    421        if (existingUniform)
    422        {
    423            if (getBinding() != -1)
    424            {
    425                existingUniform->binding = getBinding();
    426            }
    427            if (getOffset() != -1)
    428            {
    429                existingUniform->offset = getOffset();
    430            }
    431            if (mLocation != -1)
    432            {
    433                existingUniform->location = mLocation;
    434            }
    435            if (mMarkActive)
    436            {
    437                existingUniform->active = true;
    438                existingUniform->setActive(mShaderType, true);
    439            }
    440            if (mMarkStaticUse)
    441            {
    442                existingUniform->staticUse = true;
    443            }
    444        }
    445        else
    446        {
    447            LinkedUniform linkedUniform(variable.type, variable.precision, fullNameWithArrayIndex,
    448                                        variable.arraySizes, getBinding(), getOffset(), mLocation,
    449                                        -1, sh::kDefaultBlockMemberInfo);
    450            linkedUniform.mappedName          = fullMappedNameWithArrayIndex;
    451            linkedUniform.active              = mMarkActive;
    452            linkedUniform.staticUse           = mMarkStaticUse;
    453            linkedUniform.outerArraySizes     = arraySizes;
    454            linkedUniform.texelFetchStaticUse = variable.texelFetchStaticUse;
    455            linkedUniform.imageUnitFormat     = variable.imageUnitFormat;
    456            linkedUniform.isFragmentInOut     = variable.isFragmentInOut;
    457            if (variable.hasParentArrayIndex())
    458            {
    459                linkedUniform.setParentArrayIndex(variable.parentArrayIndex());
    460            }
    461 
    462            std::vector<unsigned int> arrayDims = arraySizes;
    463            ASSERT(variable.arraySizes.size() == 1 || variable.arraySizes.size() == 0);
    464            arrayDims.push_back(variable.arraySizes.empty() ? 1 : variable.arraySizes[0]);
    465 
    466            size_t numDimensions = arraySizes.size();
    467            uint32_t arrayStride = 1;
    468            for (size_t dimension = numDimensions; dimension > 0;)
    469            {
    470                --dimension;
    471                arrayStride *= arrayDims[dimension + 1];
    472                linkedUniform.outerArrayOffset += arrayStride * mArrayElementStack[dimension];
    473            }
    474 
    475            if (mMarkActive)
    476            {
    477                linkedUniform.setActive(mShaderType, true);
    478            }
    479            else
    480            {
    481                mUnusedUniforms->emplace_back(
    482                    linkedUniform.name, linkedUniform.isSampler(), linkedUniform.isImage(),
    483                    linkedUniform.isAtomicCounter(), linkedUniform.isFragmentInOut);
    484            }
    485 
    486            uniformList->push_back(linkedUniform);
    487        }
    488 
    489        unsigned int elementCount = variable.getBasicTypeElementCount();
    490 
    491        // Samplers and images aren't "real" uniforms, so they don't count towards register usage.
    492        // Likewise, don't count "real" uniforms towards opaque count.
    493 
    494        if (!IsOpaqueType(variable.type) && !isFragmentInOut)
    495        {
    496            mUniformCount.vectorCount += VariableRegisterCount(variable.type) * elementCount;
    497        }
    498 
    499        mUniformCount.samplerCount += (isSampler ? elementCount : 0);
    500        mUniformCount.imageCount += (isImage ? elementCount : 0);
    501        mUniformCount.atomicCounterCount += (isAtomicCounter ? elementCount : 0);
    502        mUniformCount.fragmentInOutCount += (isFragmentInOut ? elementCount : 0);
    503 
    504        if (mLocation != -1)
    505        {
    506            mLocation += elementCount;
    507        }
    508    }
    509 
    510    void enterStructAccess(const sh::ShaderVariable &structVar, bool isRowMajor) override
    511    {
    512        mStructStackSize++;
    513        sh::VariableNameVisitor::enterStructAccess(structVar, isRowMajor);
    514    }
    515 
    516    void exitStructAccess(const sh::ShaderVariable &structVar, bool isRowMajor) override
    517    {
    518        mStructStackSize--;
    519        sh::VariableNameVisitor::exitStructAccess(structVar, isRowMajor);
    520    }
    521 
    522    void enterArrayElement(const sh::ShaderVariable &arrayVar, unsigned int arrayElement) override
    523    {
    524        mArrayElementStack.push_back(arrayElement);
    525        sh::VariableNameVisitor::enterArrayElement(arrayVar, arrayElement);
    526    }
    527 
    528    void exitArrayElement(const sh::ShaderVariable &arrayVar, unsigned int arrayElement) override
    529    {
    530        mArrayElementStack.pop_back();
    531        sh::VariableNameVisitor::exitArrayElement(arrayVar, arrayElement);
    532    }
    533 
    534    ShaderUniformCount getCounts() const { return mUniformCount; }
    535 
    536  private:
    537    int getBinding() const { return mStructStackSize == 0 ? mBinding : -1; }
    538    int getOffset() const { return mStructStackSize == 0 ? mOffset : -1; }
    539 
    540    ShaderType mShaderType;
    541 
    542    // Active and StaticUse are given separately because they are tracked at struct granularity.
    543    bool mMarkActive;
    544    bool mMarkStaticUse;
    545    int mBinding;
    546    int mOffset;
    547    int mLocation;
    548    std::vector<LinkedUniform> *mUniforms;
    549    std::vector<LinkedUniform> *mSamplerUniforms;
    550    std::vector<LinkedUniform> *mImageUniforms;
    551    std::vector<LinkedUniform> *mAtomicCounterUniforms;
    552    std::vector<LinkedUniform> *mInputAttachmentUniforms;
    553    std::vector<UnusedUniform> *mUnusedUniforms;
    554    std::vector<unsigned int> mArrayElementStack;
    555    ShaderUniformCount mUniformCount;
    556    unsigned int mStructStackSize = 0;
    557 };
    558 
    559 class InterfaceBlockInfo final : angle::NonCopyable
    560 {
    561  public:
    562    InterfaceBlockInfo(CustomBlockLayoutEncoderFactory *customEncoderFactory)
    563        : mCustomEncoderFactory(customEncoderFactory)
    564    {}
    565 
    566    void getShaderBlockInfo(const std::vector<sh::InterfaceBlock> &interfaceBlocks);
    567 
    568    bool getBlockSize(const std::string &name, const std::string &mappedName, size_t *sizeOut);
    569    bool getBlockMemberInfo(const std::string &name,
    570                            const std::string &mappedName,
    571                            sh::BlockMemberInfo *infoOut);
    572 
    573  private:
    574    size_t getBlockInfo(const sh::InterfaceBlock &interfaceBlock);
    575 
    576    std::map<std::string, size_t> mBlockSizes;
    577    sh::BlockLayoutMap mBlockLayout;
    578    // Based on the interface block layout, the std140 or std430 encoders are used.  On some
    579    // platforms (currently only D3D), there could be another non-standard encoder used.
    580    CustomBlockLayoutEncoderFactory *mCustomEncoderFactory;
    581 };
    582 
    583 void InterfaceBlockInfo::getShaderBlockInfo(const std::vector<sh::InterfaceBlock> &interfaceBlocks)
    584 {
    585    for (const sh::InterfaceBlock &interfaceBlock : interfaceBlocks)
    586    {
    587        if (!IsActiveInterfaceBlock(interfaceBlock))
    588            continue;
    589 
    590        if (mBlockSizes.count(interfaceBlock.name) > 0)
    591            continue;
    592 
    593        size_t dataSize                  = getBlockInfo(interfaceBlock);
    594        mBlockSizes[interfaceBlock.name] = dataSize;
    595    }
    596 }
    597 
    598 size_t InterfaceBlockInfo::getBlockInfo(const sh::InterfaceBlock &interfaceBlock)
    599 {
    600    ASSERT(IsActiveInterfaceBlock(interfaceBlock));
    601 
    602    // define member uniforms
    603    sh::Std140BlockEncoder std140Encoder;
    604    sh::Std430BlockEncoder std430Encoder;
    605    sh::BlockLayoutEncoder *customEncoder = nullptr;
    606    sh::BlockLayoutEncoder *encoder       = nullptr;
    607 
    608    if (interfaceBlock.layout == sh::BLOCKLAYOUT_STD140)
    609    {
    610        encoder = &std140Encoder;
    611    }
    612    else if (interfaceBlock.layout == sh::BLOCKLAYOUT_STD430)
    613    {
    614        encoder = &std430Encoder;
    615    }
    616    else if (mCustomEncoderFactory)
    617    {
    618        encoder = customEncoder = mCustomEncoderFactory->makeEncoder();
    619    }
    620    else
    621    {
    622        UNREACHABLE();
    623        return 0;
    624    }
    625 
    626    sh::GetInterfaceBlockInfo(interfaceBlock.fields, interfaceBlock.fieldPrefix(), encoder,
    627                              &mBlockLayout);
    628 
    629    size_t offset = encoder->getCurrentOffset();
    630 
    631    SafeDelete(customEncoder);
    632 
    633    return offset;
    634 }
    635 
    636 bool InterfaceBlockInfo::getBlockSize(const std::string &name,
    637                                      const std::string &mappedName,
    638                                      size_t *sizeOut)
    639 {
    640    size_t nameLengthWithoutArrayIndex;
    641    ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
    642    std::string baseName = name.substr(0u, nameLengthWithoutArrayIndex);
    643    auto sizeIter        = mBlockSizes.find(baseName);
    644    if (sizeIter == mBlockSizes.end())
    645    {
    646        *sizeOut = 0;
    647        return false;
    648    }
    649 
    650    *sizeOut = sizeIter->second;
    651    return true;
    652 }
    653 
    654 bool InterfaceBlockInfo::getBlockMemberInfo(const std::string &name,
    655                                            const std::string &mappedName,
    656                                            sh::BlockMemberInfo *infoOut)
    657 {
    658    auto infoIter = mBlockLayout.find(name);
    659    if (infoIter == mBlockLayout.end())
    660    {
    661        *infoOut = sh::kDefaultBlockMemberInfo;
    662        return false;
    663    }
    664 
    665    *infoOut = infoIter->second;
    666    return true;
    667 }
    668 
    669 void GetFilteredVaryings(const std::vector<sh::ShaderVariable> &varyings,
    670                         std::vector<const sh::ShaderVariable *> *filteredVaryingsOut)
    671 {
    672    for (const sh::ShaderVariable &varying : varyings)
    673    {
    674        // Built-in varyings obey special rules
    675        if (varying.isBuiltIn())
    676        {
    677            continue;
    678        }
    679 
    680        filteredVaryingsOut->push_back(&varying);
    681    }
    682 }
    683 
    684 LinkMismatchError LinkValidateVaryings(const sh::ShaderVariable &outputVarying,
    685                                       const sh::ShaderVariable &inputVarying,
    686                                       int shaderVersion,
    687                                       ShaderType frontShaderType,
    688                                       ShaderType backShaderType,
    689                                       bool isSeparable,
    690                                       std::string *mismatchedStructFieldName)
    691 {
    692    // [ES 3.2 spec] 7.4.1 Shader Interface Matching:
    693    // Tessellation control shader per-vertex output variables and blocks and tessellation control,
    694    // tessellation evaluation, and geometry shader per-vertex input variables and blocks are
    695    // required to be declared as arrays, with each element representing input or output values for
    696    // a single vertex of a multi-vertex primitive. For the purposes of interface matching, such
    697    // variables and blocks are treated as though they were not declared as arrays.
    698    bool treatOutputAsNonArray =
    699        (frontShaderType == ShaderType::TessControl && !outputVarying.isPatch);
    700    bool treatInputAsNonArray =
    701        ((backShaderType == ShaderType::TessControl ||
    702          backShaderType == ShaderType::TessEvaluation || backShaderType == ShaderType::Geometry) &&
    703         !inputVarying.isPatch);
    704 
    705    // Skip the validation on the array sizes between a vertex output varying and a geometry input
    706    // varying as it has been done before.
    707    bool validatePrecision      = isSeparable && (shaderVersion > 100);
    708    LinkMismatchError linkError = LinkValidateProgramVariables(
    709        outputVarying, inputVarying, validatePrecision, treatOutputAsNonArray, treatInputAsNonArray,
    710        mismatchedStructFieldName);
    711    if (linkError != LinkMismatchError::NO_MISMATCH)
    712    {
    713        return linkError;
    714    }
    715 
    716    // Explicit locations must match if the names match.
    717    if (outputVarying.isSameNameAtLinkTime(inputVarying) &&
    718        outputVarying.location != inputVarying.location)
    719    {
    720        return LinkMismatchError::LOCATION_MISMATCH;
    721    }
    722 
    723    if (!sh::InterpolationTypesMatch(outputVarying.interpolation, inputVarying.interpolation))
    724    {
    725        return LinkMismatchError::INTERPOLATION_TYPE_MISMATCH;
    726    }
    727 
    728    if (shaderVersion == 100 && outputVarying.isInvariant != inputVarying.isInvariant)
    729    {
    730        return LinkMismatchError::INVARIANCE_MISMATCH;
    731    }
    732 
    733    return LinkMismatchError::NO_MISMATCH;
    734 }
    735 
    736 bool DoShaderVariablesMatch(int frontShaderVersion,
    737                            ShaderType frontShaderType,
    738                            ShaderType backShaderType,
    739                            const sh::ShaderVariable &input,
    740                            const sh::ShaderVariable &output,
    741                            bool isSeparable,
    742                            gl::InfoLog &infoLog)
    743 {
    744    bool namesMatch     = input.isSameNameAtLinkTime(output);
    745    bool locationsMatch = input.location != -1 && input.location == output.location;
    746 
    747    // An output block is considered to match an input block in the subsequent
    748    // shader if the two blocks have the same block name, and the members of the
    749    // block match exactly in name, type, qualification, and declaration order.
    750    //
    751    // - For the purposes of shader interface matching, the gl_PointSize
    752    //   member of the intrinsically declared gl_PerVertex shader interface
    753    //   block is ignored.
    754    // - Output blocks that do not match in name, but have a location and match
    755    //   in every other way listed above may be considered to match by some
    756    //   implementations, but not all - so this behaviour should not be relied
    757    //   upon.
    758 
    759    // An output variable is considered to match an input variable in the subsequent
    760    // shader if:
    761    //
    762    // - the two variables match in name, type, and qualification; or
    763    // - the two variables are declared with the same location qualifier and
    764    //   match in type and qualification.
    765 
    766    if (namesMatch || locationsMatch)
    767    {
    768        std::string mismatchedStructFieldName;
    769        LinkMismatchError linkError =
    770            LinkValidateVaryings(output, input, frontShaderVersion, frontShaderType, backShaderType,
    771                                 isSeparable, &mismatchedStructFieldName);
    772        if (linkError != LinkMismatchError::NO_MISMATCH)
    773        {
    774            LogLinkMismatch(infoLog, input.name, "varying", linkError, mismatchedStructFieldName,
    775                            frontShaderType, backShaderType);
    776            return false;
    777        }
    778 
    779        return true;
    780    }
    781 
    782    return false;
    783 }
    784 
    785 const char *GetInterfaceBlockTypeString(sh::BlockType blockType)
    786 {
    787    switch (blockType)
    788    {
    789        case sh::BlockType::BLOCK_UNIFORM:
    790            return "uniform block";
    791        case sh::BlockType::BLOCK_BUFFER:
    792            return "shader storage block";
    793        default:
    794            UNREACHABLE();
    795            return "";
    796    }
    797 }
    798 
    799 std::string GetInterfaceBlockLimitName(ShaderType shaderType, sh::BlockType blockType)
    800 {
    801    std::ostringstream stream;
    802    stream << "GL_MAX_" << GetShaderTypeString(shaderType) << "_";
    803 
    804    switch (blockType)
    805    {
    806        case sh::BlockType::BLOCK_UNIFORM:
    807            stream << "UNIFORM_BUFFERS";
    808            break;
    809        case sh::BlockType::BLOCK_BUFFER:
    810            stream << "SHADER_STORAGE_BLOCKS";
    811            break;
    812        default:
    813            UNREACHABLE();
    814            return "";
    815    }
    816 
    817    if (shaderType == ShaderType::Geometry)
    818    {
    819        stream << "_EXT";
    820    }
    821 
    822    return stream.str();
    823 }
    824 
    825 void LogInterfaceBlocksExceedLimit(InfoLog &infoLog,
    826                                   ShaderType shaderType,
    827                                   sh::BlockType blockType,
    828                                   GLuint limit)
    829 {
    830    infoLog << GetShaderTypeString(shaderType) << " shader "
    831            << GetInterfaceBlockTypeString(blockType) << " count exceeds "
    832            << GetInterfaceBlockLimitName(shaderType, blockType) << " (" << limit << ")";
    833 }
    834 
    835 bool ValidateInterfaceBlocksCount(GLuint maxInterfaceBlocks,
    836                                  const std::vector<sh::InterfaceBlock> &interfaceBlocks,
    837                                  ShaderType shaderType,
    838                                  sh::BlockType blockType,
    839                                  GLuint *combinedInterfaceBlocksCount,
    840                                  InfoLog &infoLog)
    841 {
    842    GLuint blockCount = 0;
    843    for (const sh::InterfaceBlock &block : interfaceBlocks)
    844    {
    845        if (IsActiveInterfaceBlock(block))
    846        {
    847            blockCount += std::max(block.arraySize, 1u);
    848            if (blockCount > maxInterfaceBlocks)
    849            {
    850                LogInterfaceBlocksExceedLimit(infoLog, shaderType, blockType, maxInterfaceBlocks);
    851                return false;
    852            }
    853        }
    854    }
    855 
    856    // [OpenGL ES 3.1] Chapter 7.6.2 Page 105:
    857    // If a uniform block is used by multiple shader stages, each such use counts separately
    858    // against this combined limit.
    859    // [OpenGL ES 3.1] Chapter 7.8 Page 111:
    860    // If a shader storage block in a program is referenced by multiple shaders, each such
    861    // reference counts separately against this combined limit.
    862    if (combinedInterfaceBlocksCount)
    863    {
    864        *combinedInterfaceBlocksCount += blockCount;
    865    }
    866 
    867    return true;
    868 }
    869 }  // anonymous namespace
    870 
    871 UniformLinker::UniformLinker(const ShaderBitSet &activeShaderStages,
    872                             const ShaderMap<std::vector<sh::ShaderVariable>> &shaderUniforms)
    873    : mActiveShaderStages(activeShaderStages), mShaderUniforms(shaderUniforms)
    874 {}
    875 
    876 UniformLinker::~UniformLinker() = default;
    877 
    878 void UniformLinker::getResults(std::vector<LinkedUniform> *uniforms,
    879                               std::vector<UnusedUniform> *unusedUniformsOutOrNull,
    880                               std::vector<VariableLocation> *uniformLocationsOutOrNull)
    881 {
    882    uniforms->swap(mUniforms);
    883 
    884    if (unusedUniformsOutOrNull)
    885    {
    886        unusedUniformsOutOrNull->swap(mUnusedUniforms);
    887    }
    888 
    889    if (uniformLocationsOutOrNull)
    890    {
    891        uniformLocationsOutOrNull->swap(mUniformLocations);
    892    }
    893 }
    894 
    895 bool UniformLinker::link(const Caps &caps,
    896                         InfoLog &infoLog,
    897                         const ProgramAliasedBindings &uniformLocationBindings)
    898 {
    899    if (mActiveShaderStages[ShaderType::Vertex] && mActiveShaderStages[ShaderType::Fragment])
    900    {
    901        if (!validateGraphicsUniforms(infoLog))
    902        {
    903            return false;
    904        }
    905    }
    906 
    907    // Flatten the uniforms list (nested fields) into a simple list (no nesting).
    908    // Also check the maximum uniform vector and sampler counts.
    909    if (!flattenUniformsAndCheckCaps(caps, infoLog))
    910    {
    911        return false;
    912    }
    913 
    914    if (!checkMaxCombinedAtomicCounters(caps, infoLog))
    915    {
    916        return false;
    917    }
    918 
    919    if (!indexUniforms(infoLog, uniformLocationBindings))
    920    {
    921        return false;
    922    }
    923 
    924    return true;
    925 }
    926 
    927 bool UniformLinker::validateGraphicsUniforms(InfoLog &infoLog) const
    928 {
    929    // Check that uniforms defined in the graphics shaders are identical
    930    std::map<std::string, ShaderUniform> linkedUniforms;
    931 
    932    for (const ShaderType shaderType : mActiveShaderStages)
    933    {
    934        if (shaderType == ShaderType::Vertex)
    935        {
    936            for (const sh::ShaderVariable &vertexUniform : mShaderUniforms[ShaderType::Vertex])
    937            {
    938                linkedUniforms[vertexUniform.name] =
    939                    std::make_pair(ShaderType::Vertex, &vertexUniform);
    940            }
    941        }
    942        else
    943        {
    944            bool isLastShader = (shaderType == ShaderType::Fragment);
    945            if (!validateGraphicsUniformsPerShader(shaderType, !isLastShader, &linkedUniforms,
    946                                                   infoLog))
    947            {
    948                return false;
    949            }
    950        }
    951    }
    952 
    953    return true;
    954 }
    955 
    956 bool UniformLinker::validateGraphicsUniformsPerShader(
    957    ShaderType shaderToLink,
    958    bool extendLinkedUniforms,
    959    std::map<std::string, ShaderUniform> *linkedUniforms,
    960    InfoLog &infoLog) const
    961 {
    962    ASSERT(mActiveShaderStages[shaderToLink] && linkedUniforms);
    963 
    964    for (const sh::ShaderVariable &uniform : mShaderUniforms[shaderToLink])
    965    {
    966        const auto &entry = linkedUniforms->find(uniform.name);
    967        if (entry != linkedUniforms->end())
    968        {
    969            const sh::ShaderVariable &linkedUniform = *(entry->second.second);
    970            std::string mismatchedStructFieldName;
    971            LinkMismatchError linkError =
    972                LinkValidateUniforms(uniform, linkedUniform, &mismatchedStructFieldName);
    973            if (linkError != LinkMismatchError::NO_MISMATCH)
    974            {
    975                LogLinkMismatch(infoLog, uniform.name, "uniform", linkError,
    976                                mismatchedStructFieldName, entry->second.first, shaderToLink);
    977                return false;
    978            }
    979        }
    980        else if (extendLinkedUniforms)
    981        {
    982            (*linkedUniforms)[uniform.name] = std::make_pair(shaderToLink, &uniform);
    983        }
    984    }
    985 
    986    return true;
    987 }
    988 
    989 bool UniformLinker::indexUniforms(InfoLog &infoLog,
    990                                  const ProgramAliasedBindings &uniformLocationBindings)
    991 {
    992    // Locations which have been allocated for an unused uniform.
    993    std::set<GLuint> ignoredLocations;
    994 
    995    int maxUniformLocation = -1;
    996 
    997    // Gather uniform locations that have been set either using the bindUniformLocationCHROMIUM API
    998    // or by using a location layout qualifier and check conflicts between them.
    999    if (!gatherUniformLocationsAndCheckConflicts(infoLog, uniformLocationBindings,
   1000                                                 &ignoredLocations, &maxUniformLocation))
   1001    {
   1002        return false;
   1003    }
   1004 
   1005    // Conflicts have been checked, now we can prune non-statically used uniforms. Code further down
   1006    // the line relies on only having statically used uniforms in mUniforms.
   1007    pruneUnusedUniforms();
   1008 
   1009    // Gather uniforms that have their location pre-set and uniforms that don't yet have a location.
   1010    std::vector<VariableLocation> unlocatedUniforms;
   1011    std::map<GLuint, VariableLocation> preLocatedUniforms;
   1012 
   1013    for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
   1014    {
   1015        const LinkedUniform &uniform = mUniforms[uniformIndex];
   1016 
   1017        if ((uniform.isBuiltIn() && !uniform.isEmulatedBuiltIn()) ||
   1018            IsAtomicCounterType(uniform.type) || uniform.isFragmentInOut)
   1019        {
   1020            continue;
   1021        }
   1022 
   1023        int preSetLocation = uniformLocationBindings.getBinding(uniform);
   1024        int shaderLocation = uniform.location;
   1025 
   1026        if (shaderLocation != -1)
   1027        {
   1028            preSetLocation = shaderLocation;
   1029        }
   1030 
   1031        unsigned int elementCount = uniform.getBasicTypeElementCount();
   1032        for (unsigned int arrayIndex = 0; arrayIndex < elementCount; arrayIndex++)
   1033        {
   1034            VariableLocation location(arrayIndex, static_cast<unsigned int>(uniformIndex));
   1035 
   1036            if ((arrayIndex == 0 && preSetLocation != -1) || shaderLocation != -1)
   1037            {
   1038                int elementLocation                 = preSetLocation + arrayIndex;
   1039                preLocatedUniforms[elementLocation] = location;
   1040            }
   1041            else
   1042            {
   1043                unlocatedUniforms.push_back(location);
   1044            }
   1045        }
   1046    }
   1047 
   1048    // Make enough space for all uniforms, with pre-set locations or not.
   1049    mUniformLocations.resize(
   1050        std::max(unlocatedUniforms.size() + preLocatedUniforms.size() + ignoredLocations.size(),
   1051                 static_cast<size_t>(maxUniformLocation + 1)));
   1052 
   1053    // Assign uniforms with pre-set locations
   1054    for (const auto &uniform : preLocatedUniforms)
   1055    {
   1056        mUniformLocations[uniform.first] = uniform.second;
   1057    }
   1058 
   1059    // Assign ignored uniforms
   1060    for (const auto &ignoredLocation : ignoredLocations)
   1061    {
   1062        mUniformLocations[ignoredLocation].markIgnored();
   1063    }
   1064 
   1065    // Automatically assign locations for the rest of the uniforms
   1066    size_t nextUniformLocation = 0;
   1067    for (const auto &unlocatedUniform : unlocatedUniforms)
   1068    {
   1069        while (mUniformLocations[nextUniformLocation].used() ||
   1070               mUniformLocations[nextUniformLocation].ignored)
   1071        {
   1072            nextUniformLocation++;
   1073        }
   1074 
   1075        ASSERT(nextUniformLocation < mUniformLocations.size());
   1076        mUniformLocations[nextUniformLocation] = unlocatedUniform;
   1077        nextUniformLocation++;
   1078    }
   1079 
   1080    return true;
   1081 }
   1082 
   1083 bool UniformLinker::gatherUniformLocationsAndCheckConflicts(
   1084    InfoLog &infoLog,
   1085    const ProgramAliasedBindings &uniformLocationBindings,
   1086    std::set<GLuint> *ignoredLocations,
   1087    int *maxUniformLocation)
   1088 {
   1089    // All the locations where another uniform can't be located.
   1090    std::set<GLuint> reservedLocations;
   1091 
   1092    for (const LinkedUniform &uniform : mUniforms)
   1093    {
   1094        if ((uniform.isBuiltIn() && !uniform.isEmulatedBuiltIn()) || uniform.isFragmentInOut)
   1095        {
   1096            // The uniform of the fragment inout is not a normal uniform type. So, in the case of
   1097            // the fragment inout, this routine should be skipped.
   1098            continue;
   1099        }
   1100 
   1101        int apiBoundLocation = uniformLocationBindings.getBinding(uniform);
   1102        int shaderLocation   = uniform.location;
   1103 
   1104        if (shaderLocation != -1)
   1105        {
   1106            unsigned int elementCount = uniform.getBasicTypeElementCount();
   1107 
   1108            for (unsigned int arrayIndex = 0; arrayIndex < elementCount; arrayIndex++)
   1109            {
   1110                // GLSL ES 3.10 section 4.4.3
   1111                int elementLocation = shaderLocation + arrayIndex;
   1112                *maxUniformLocation = std::max(*maxUniformLocation, elementLocation);
   1113                if (reservedLocations.find(elementLocation) != reservedLocations.end())
   1114                {
   1115                    infoLog << "Multiple uniforms bound to location " << elementLocation << ".";
   1116                    return false;
   1117                }
   1118                reservedLocations.insert(elementLocation);
   1119                if (!uniform.active)
   1120                {
   1121                    ignoredLocations->insert(elementLocation);
   1122                }
   1123            }
   1124        }
   1125        else if (apiBoundLocation != -1 && uniform.staticUse)
   1126        {
   1127            // Only the first location is reserved even if the uniform is an array.
   1128            *maxUniformLocation = std::max(*maxUniformLocation, apiBoundLocation);
   1129            if (reservedLocations.find(apiBoundLocation) != reservedLocations.end())
   1130            {
   1131                infoLog << "Multiple uniforms bound to location " << apiBoundLocation << ".";
   1132                return false;
   1133            }
   1134            reservedLocations.insert(apiBoundLocation);
   1135            if (!uniform.active)
   1136            {
   1137                ignoredLocations->insert(apiBoundLocation);
   1138            }
   1139        }
   1140    }
   1141 
   1142    // Record the uniform locations that were bound using the API for uniforms that were not found
   1143    // from the shader. Other uniforms should not be assigned to those locations.
   1144    for (const auto &locationBinding : uniformLocationBindings)
   1145    {
   1146        GLuint location = locationBinding.second.location;
   1147        if (reservedLocations.find(location) == reservedLocations.end())
   1148        {
   1149            ignoredLocations->insert(location);
   1150            *maxUniformLocation = std::max(*maxUniformLocation, static_cast<int>(location));
   1151        }
   1152    }
   1153 
   1154    return true;
   1155 }
   1156 
   1157 void UniformLinker::pruneUnusedUniforms()
   1158 {
   1159    auto uniformIter = mUniforms.begin();
   1160    while (uniformIter != mUniforms.end())
   1161    {
   1162        if (uniformIter->active)
   1163        {
   1164            ++uniformIter;
   1165        }
   1166        else
   1167        {
   1168            mUnusedUniforms.emplace_back(uniformIter->name, uniformIter->isSampler(),
   1169                                         uniformIter->isImage(), uniformIter->isAtomicCounter(),
   1170                                         uniformIter->isFragmentInOut);
   1171            uniformIter = mUniforms.erase(uniformIter);
   1172        }
   1173    }
   1174 }
   1175 
   1176 bool UniformLinker::flattenUniformsAndCheckCapsForShader(
   1177    ShaderType shaderType,
   1178    const Caps &caps,
   1179    std::vector<LinkedUniform> &samplerUniforms,
   1180    std::vector<LinkedUniform> &imageUniforms,
   1181    std::vector<LinkedUniform> &atomicCounterUniforms,
   1182    std::vector<LinkedUniform> &inputAttachmentUniforms,
   1183    std::vector<UnusedUniform> &unusedUniforms,
   1184    InfoLog &infoLog)
   1185 {
   1186    ShaderUniformCount shaderUniformCount;
   1187    for (const sh::ShaderVariable &uniform : mShaderUniforms[shaderType])
   1188    {
   1189        FlattenUniformVisitor flattener(shaderType, uniform, &mUniforms, &samplerUniforms,
   1190                                        &imageUniforms, &atomicCounterUniforms,
   1191                                        &inputAttachmentUniforms, &unusedUniforms);
   1192        sh::TraverseShaderVariable(uniform, false, &flattener);
   1193 
   1194        if (uniform.active)
   1195        {
   1196            shaderUniformCount += flattener.getCounts();
   1197        }
   1198        else
   1199        {
   1200            unusedUniforms.emplace_back(uniform.name, IsSamplerType(uniform.type),
   1201                                        IsImageType(uniform.type),
   1202                                        IsAtomicCounterType(uniform.type), uniform.isFragmentInOut);
   1203        }
   1204    }
   1205 
   1206    // This code does not do fine-grained component counting.
   1207    GLuint maxUniformVectorsCount = GetMaximumShaderUniformVectors(shaderType, caps);
   1208    if (shaderUniformCount.vectorCount > maxUniformVectorsCount)
   1209    {
   1210        GLuint maxUniforms = 0u;
   1211 
   1212        // See comments in GetUniformResourceLimitName()
   1213        if (shaderType == ShaderType::Vertex || shaderType == ShaderType::Fragment)
   1214        {
   1215            maxUniforms = maxUniformVectorsCount;
   1216        }
   1217        else
   1218        {
   1219            maxUniforms = maxUniformVectorsCount * 4;
   1220        }
   1221 
   1222        LogUniformsExceedLimit(shaderType, UniformType::Variable, maxUniforms, infoLog);
   1223        return false;
   1224    }
   1225 
   1226    if (shaderUniformCount.samplerCount >
   1227        static_cast<GLuint>(caps.maxShaderTextureImageUnits[shaderType]))
   1228    {
   1229        LogUniformsExceedLimit(shaderType, UniformType::Sampler,
   1230                               caps.maxShaderTextureImageUnits[shaderType], infoLog);
   1231        return false;
   1232    }
   1233 
   1234    if (shaderUniformCount.imageCount >
   1235        static_cast<GLuint>(caps.maxShaderImageUniforms[shaderType]))
   1236    {
   1237        LogUniformsExceedLimit(shaderType, UniformType::Image,
   1238                               caps.maxShaderImageUniforms[shaderType], infoLog);
   1239        return false;
   1240    }
   1241 
   1242    if (shaderUniformCount.atomicCounterCount >
   1243        static_cast<GLuint>(caps.maxShaderAtomicCounters[shaderType]))
   1244    {
   1245        LogUniformsExceedLimit(shaderType, UniformType::AtomicCounter,
   1246                               caps.maxShaderAtomicCounters[shaderType], infoLog);
   1247        return false;
   1248    }
   1249 
   1250    return true;
   1251 }
   1252 
   1253 bool UniformLinker::flattenUniformsAndCheckCaps(const Caps &caps, InfoLog &infoLog)
   1254 {
   1255    std::vector<LinkedUniform> samplerUniforms;
   1256    std::vector<LinkedUniform> imageUniforms;
   1257    std::vector<LinkedUniform> atomicCounterUniforms;
   1258    std::vector<LinkedUniform> inputAttachmentUniforms;
   1259    std::vector<UnusedUniform> unusedUniforms;
   1260 
   1261    for (const ShaderType shaderType : mActiveShaderStages)
   1262    {
   1263        if (!flattenUniformsAndCheckCapsForShader(shaderType, caps, samplerUniforms, imageUniforms,
   1264                                                  atomicCounterUniforms, inputAttachmentUniforms,
   1265                                                  unusedUniforms, infoLog))
   1266        {
   1267            return false;
   1268        }
   1269    }
   1270 
   1271    mUniforms.insert(mUniforms.end(), samplerUniforms.begin(), samplerUniforms.end());
   1272    mUniforms.insert(mUniforms.end(), imageUniforms.begin(), imageUniforms.end());
   1273    mUniforms.insert(mUniforms.end(), atomicCounterUniforms.begin(), atomicCounterUniforms.end());
   1274    mUniforms.insert(mUniforms.end(), inputAttachmentUniforms.begin(),
   1275                     inputAttachmentUniforms.end());
   1276    mUnusedUniforms.insert(mUnusedUniforms.end(), unusedUniforms.begin(), unusedUniforms.end());
   1277    return true;
   1278 }
   1279 
   1280 bool UniformLinker::checkMaxCombinedAtomicCounters(const Caps &caps, InfoLog &infoLog)
   1281 {
   1282    unsigned int atomicCounterCount = 0;
   1283    for (const auto &uniform : mUniforms)
   1284    {
   1285        if (IsAtomicCounterType(uniform.type) && uniform.active)
   1286        {
   1287            atomicCounterCount += uniform.getBasicTypeElementCount();
   1288            if (atomicCounterCount > static_cast<GLuint>(caps.maxCombinedAtomicCounters))
   1289            {
   1290                infoLog << "atomic counter count exceeds MAX_COMBINED_ATOMIC_COUNTERS"
   1291                        << caps.maxCombinedAtomicCounters << ").";
   1292                return false;
   1293            }
   1294        }
   1295    }
   1296    return true;
   1297 }
   1298 
   1299 // InterfaceBlockLinker implementation.
   1300 InterfaceBlockLinker::InterfaceBlockLinker() = default;
   1301 
   1302 InterfaceBlockLinker::~InterfaceBlockLinker() = default;
   1303 
   1304 void InterfaceBlockLinker::init(std::vector<InterfaceBlock> *blocksOut,
   1305                                std::vector<std::string> *unusedInterfaceBlocksOut)
   1306 {
   1307    mBlocksOut                = blocksOut;
   1308    mUnusedInterfaceBlocksOut = unusedInterfaceBlocksOut;
   1309 }
   1310 
   1311 void InterfaceBlockLinker::addShaderBlocks(ShaderType shaderType,
   1312                                           const std::vector<sh::InterfaceBlock> *blocks)
   1313 {
   1314    mShaderBlocks[shaderType] = blocks;
   1315 }
   1316 
   1317 void InterfaceBlockLinker::linkBlocks(const GetBlockSizeFunc &getBlockSize,
   1318                                      const GetBlockMemberInfoFunc &getMemberInfo) const
   1319 {
   1320    ASSERT(mBlocksOut->empty());
   1321 
   1322    std::set<std::string> visitedList;
   1323 
   1324    for (const ShaderType shaderType : AllShaderTypes())
   1325    {
   1326        if (!mShaderBlocks[shaderType])
   1327        {
   1328            continue;
   1329        }
   1330 
   1331        for (const sh::InterfaceBlock &block : *mShaderBlocks[shaderType])
   1332        {
   1333            if (!IsActiveInterfaceBlock(block))
   1334            {
   1335                mUnusedInterfaceBlocksOut->push_back(block.name);
   1336                continue;
   1337            }
   1338 
   1339            if (visitedList.count(block.name) == 0)
   1340            {
   1341                defineInterfaceBlock(getBlockSize, getMemberInfo, block, shaderType);
   1342                visitedList.insert(block.name);
   1343                continue;
   1344            }
   1345 
   1346            if (!block.active)
   1347            {
   1348                mUnusedInterfaceBlocksOut->push_back(block.name);
   1349                continue;
   1350            }
   1351 
   1352            for (InterfaceBlock &priorBlock : *mBlocksOut)
   1353            {
   1354                if (block.name == priorBlock.name)
   1355                {
   1356                    priorBlock.setActive(shaderType, true);
   1357 
   1358                    std::unique_ptr<sh::ShaderVariableVisitor> visitor(
   1359                        getVisitor(getMemberInfo, block.fieldPrefix(), block.fieldMappedPrefix(),
   1360                                   shaderType, -1));
   1361 
   1362                    sh::TraverseShaderVariables(block.fields, false, visitor.get());
   1363                }
   1364            }
   1365        }
   1366    }
   1367 }
   1368 
   1369 void InterfaceBlockLinker::defineInterfaceBlock(const GetBlockSizeFunc &getBlockSize,
   1370                                                const GetBlockMemberInfoFunc &getMemberInfo,
   1371                                                const sh::InterfaceBlock &interfaceBlock,
   1372                                                ShaderType shaderType) const
   1373 {
   1374    size_t blockSize = 0;
   1375    std::vector<unsigned int> blockIndexes;
   1376 
   1377    int blockIndex = static_cast<int>(mBlocksOut->size());
   1378    // Track the first and last block member index to determine the range of active block members in
   1379    // the block.
   1380    size_t firstBlockMemberIndex = getCurrentBlockMemberIndex();
   1381 
   1382    std::unique_ptr<sh::ShaderVariableVisitor> visitor(
   1383        getVisitor(getMemberInfo, interfaceBlock.fieldPrefix(), interfaceBlock.fieldMappedPrefix(),
   1384                   shaderType, blockIndex));
   1385    sh::TraverseShaderVariables(interfaceBlock.fields, false, visitor.get());
   1386 
   1387    size_t lastBlockMemberIndex = getCurrentBlockMemberIndex();
   1388 
   1389    for (size_t blockMemberIndex = firstBlockMemberIndex; blockMemberIndex < lastBlockMemberIndex;
   1390         ++blockMemberIndex)
   1391    {
   1392        blockIndexes.push_back(static_cast<unsigned int>(blockMemberIndex));
   1393    }
   1394 
   1395    unsigned int firstFieldArraySize = interfaceBlock.fields[0].getArraySizeProduct();
   1396 
   1397    for (unsigned int arrayElement = 0; arrayElement < interfaceBlock.elementCount();
   1398         ++arrayElement)
   1399    {
   1400        std::string blockArrayName       = interfaceBlock.name;
   1401        std::string blockMappedArrayName = interfaceBlock.mappedName;
   1402        if (interfaceBlock.isArray())
   1403        {
   1404            blockArrayName += ArrayString(arrayElement);
   1405            blockMappedArrayName += ArrayString(arrayElement);
   1406        }
   1407 
   1408        // Don't define this block at all if it's not active in the implementation.
   1409        if (!getBlockSize(blockArrayName, blockMappedArrayName, &blockSize))
   1410        {
   1411            continue;
   1412        }
   1413 
   1414        // ESSL 3.10 section 4.4.4 page 58:
   1415        // Any uniform or shader storage block declared without a binding qualifier is initially
   1416        // assigned to block binding point zero.
   1417        int blockBinding =
   1418            (interfaceBlock.binding == -1 ? 0 : interfaceBlock.binding + arrayElement);
   1419        InterfaceBlock block(interfaceBlock.name, interfaceBlock.mappedName,
   1420                             interfaceBlock.isArray(), arrayElement, firstFieldArraySize,
   1421                             blockBinding);
   1422        block.memberIndexes = blockIndexes;
   1423        block.setActive(shaderType, interfaceBlock.active);
   1424 
   1425        // Since all block elements in an array share the same active interface blocks, they
   1426        // will all be active once any block member is used. So, since interfaceBlock.name[0]
   1427        // was active, here we will add every block element in the array.
   1428        block.dataSize = static_cast<unsigned int>(blockSize);
   1429        mBlocksOut->push_back(block);
   1430    }
   1431 }
   1432 
   1433 // UniformBlockLinker implementation.
   1434 UniformBlockLinker::UniformBlockLinker() = default;
   1435 
   1436 UniformBlockLinker::~UniformBlockLinker() {}
   1437 
   1438 void UniformBlockLinker::init(std::vector<InterfaceBlock> *blocksOut,
   1439                              std::vector<LinkedUniform> *uniformsOut,
   1440                              std::vector<std::string> *unusedInterfaceBlocksOut)
   1441 {
   1442    InterfaceBlockLinker::init(blocksOut, unusedInterfaceBlocksOut);
   1443    mUniformsOut = uniformsOut;
   1444 }
   1445 
   1446 size_t UniformBlockLinker::getCurrentBlockMemberIndex() const
   1447 {
   1448    return mUniformsOut->size();
   1449 }
   1450 
   1451 sh::ShaderVariableVisitor *UniformBlockLinker::getVisitor(
   1452    const GetBlockMemberInfoFunc &getMemberInfo,
   1453    const std::string &namePrefix,
   1454    const std::string &mappedNamePrefix,
   1455    ShaderType shaderType,
   1456    int blockIndex) const
   1457 {
   1458    return new UniformBlockEncodingVisitor(getMemberInfo, namePrefix, mappedNamePrefix,
   1459                                           mUniformsOut, shaderType, blockIndex);
   1460 }
   1461 
   1462 // ShaderStorageBlockLinker implementation.
   1463 ShaderStorageBlockLinker::ShaderStorageBlockLinker() = default;
   1464 
   1465 ShaderStorageBlockLinker::~ShaderStorageBlockLinker() = default;
   1466 
   1467 void ShaderStorageBlockLinker::init(std::vector<InterfaceBlock> *blocksOut,
   1468                                    std::vector<BufferVariable> *bufferVariablesOut,
   1469                                    std::vector<std::string> *unusedInterfaceBlocksOut)
   1470 {
   1471    InterfaceBlockLinker::init(blocksOut, unusedInterfaceBlocksOut);
   1472    mBufferVariablesOut = bufferVariablesOut;
   1473 }
   1474 
   1475 size_t ShaderStorageBlockLinker::getCurrentBlockMemberIndex() const
   1476 {
   1477    return mBufferVariablesOut->size();
   1478 }
   1479 
   1480 sh::ShaderVariableVisitor *ShaderStorageBlockLinker::getVisitor(
   1481    const GetBlockMemberInfoFunc &getMemberInfo,
   1482    const std::string &namePrefix,
   1483    const std::string &mappedNamePrefix,
   1484    ShaderType shaderType,
   1485    int blockIndex) const
   1486 {
   1487    return new ShaderStorageBlockVisitor(getMemberInfo, namePrefix, mappedNamePrefix,
   1488                                         mBufferVariablesOut, shaderType, blockIndex);
   1489 }
   1490 
   1491 // AtomicCounterBufferLinker implementation.
   1492 AtomicCounterBufferLinker::AtomicCounterBufferLinker() = default;
   1493 
   1494 AtomicCounterBufferLinker::~AtomicCounterBufferLinker() = default;
   1495 
   1496 void AtomicCounterBufferLinker::init(std::vector<AtomicCounterBuffer> *atomicCounterBuffersOut)
   1497 {
   1498    mAtomicCounterBuffersOut = atomicCounterBuffersOut;
   1499 }
   1500 
   1501 void AtomicCounterBufferLinker::link(const std::map<int, unsigned int> &sizeMap) const
   1502 {
   1503    for (auto &atomicCounterBuffer : *mAtomicCounterBuffersOut)
   1504    {
   1505        auto bufferSize = sizeMap.find(atomicCounterBuffer.binding);
   1506        ASSERT(bufferSize != sizeMap.end());
   1507        atomicCounterBuffer.dataSize = bufferSize->second;
   1508    }
   1509 }
   1510 
   1511 ProgramLinkedResources::ProgramLinkedResources() = default;
   1512 
   1513 ProgramLinkedResources::~ProgramLinkedResources() = default;
   1514 
   1515 LinkingVariables::LinkingVariables(const Context *context, const ProgramState &state)
   1516 {
   1517    for (ShaderType shaderType : kAllGraphicsShaderTypes)
   1518    {
   1519        Shader *shader = state.getAttachedShader(shaderType);
   1520        if (shader)
   1521        {
   1522            outputVaryings[shaderType] = shader->getOutputVaryings(context);
   1523            inputVaryings[shaderType]  = shader->getInputVaryings(context);
   1524            uniforms[shaderType]       = shader->getUniforms(context);
   1525            uniformBlocks[shaderType]  = shader->getUniformBlocks(context);
   1526            isShaderStageUsedBitset.set(shaderType);
   1527        }
   1528    }
   1529 }
   1530 
   1531 LinkingVariables::LinkingVariables(const ProgramPipelineState &state)
   1532 {
   1533    for (ShaderType shaderType : state.getExecutable().getLinkedShaderStages())
   1534    {
   1535        const Program *program = state.getShaderProgram(shaderType);
   1536        ASSERT(program);
   1537        outputVaryings[shaderType] = program->getExecutable().getLinkedOutputVaryings(shaderType);
   1538        inputVaryings[shaderType]  = program->getExecutable().getLinkedInputVaryings(shaderType);
   1539        uniforms[shaderType] = program->getState().getExecutable().getLinkedUniforms(shaderType);
   1540        uniformBlocks[shaderType] =
   1541            program->getState().getExecutable().getLinkedUniformBlocks(shaderType);
   1542        isShaderStageUsedBitset.set(shaderType);
   1543    }
   1544 }
   1545 
   1546 LinkingVariables::~LinkingVariables() = default;
   1547 
   1548 void ProgramLinkedResources::init(std::vector<InterfaceBlock> *uniformBlocksOut,
   1549                                  std::vector<LinkedUniform> *uniformsOut,
   1550                                  std::vector<InterfaceBlock> *shaderStorageBlocksOut,
   1551                                  std::vector<BufferVariable> *bufferVariablesOut,
   1552                                  std::vector<AtomicCounterBuffer> *atomicCounterBuffersOut)
   1553 {
   1554    uniformBlockLinker.init(uniformBlocksOut, uniformsOut, &unusedInterfaceBlocks);
   1555    shaderStorageBlockLinker.init(shaderStorageBlocksOut, bufferVariablesOut,
   1556                                  &unusedInterfaceBlocks);
   1557    atomicCounterBufferLinker.init(atomicCounterBuffersOut);
   1558 }
   1559 
   1560 void ProgramLinkedResourcesLinker::linkResources(const Context *context,
   1561                                                 const ProgramState &programState,
   1562                                                 const ProgramLinkedResources &resources) const
   1563 {
   1564    // Gather uniform interface block info.
   1565    InterfaceBlockInfo uniformBlockInfo(mCustomEncoderFactory);
   1566    for (const ShaderType shaderType : AllShaderTypes())
   1567    {
   1568        Shader *shader = programState.getAttachedShader(shaderType);
   1569        if (shader)
   1570        {
   1571            uniformBlockInfo.getShaderBlockInfo(shader->getUniformBlocks(context));
   1572        }
   1573    }
   1574 
   1575    auto getUniformBlockSize = [&uniformBlockInfo](const std::string &name,
   1576                                                   const std::string &mappedName, size_t *sizeOut) {
   1577        return uniformBlockInfo.getBlockSize(name, mappedName, sizeOut);
   1578    };
   1579 
   1580    auto getUniformBlockMemberInfo = [&uniformBlockInfo](const std::string &name,
   1581                                                         const std::string &mappedName,
   1582                                                         sh::BlockMemberInfo *infoOut) {
   1583        return uniformBlockInfo.getBlockMemberInfo(name, mappedName, infoOut);
   1584    };
   1585 
   1586    // Link uniform interface blocks.
   1587    resources.uniformBlockLinker.linkBlocks(getUniformBlockSize, getUniformBlockMemberInfo);
   1588 
   1589    // Gather storage buffer interface block info.
   1590    InterfaceBlockInfo shaderStorageBlockInfo(mCustomEncoderFactory);
   1591    for (const ShaderType shaderType : AllShaderTypes())
   1592    {
   1593        Shader *shader = programState.getAttachedShader(shaderType);
   1594        if (shader)
   1595        {
   1596            shaderStorageBlockInfo.getShaderBlockInfo(shader->getShaderStorageBlocks(context));
   1597        }
   1598    }
   1599    auto getShaderStorageBlockSize = [&shaderStorageBlockInfo](const std::string &name,
   1600                                                               const std::string &mappedName,
   1601                                                               size_t *sizeOut) {
   1602        return shaderStorageBlockInfo.getBlockSize(name, mappedName, sizeOut);
   1603    };
   1604 
   1605    auto getShaderStorageBlockMemberInfo = [&shaderStorageBlockInfo](const std::string &name,
   1606                                                                     const std::string &mappedName,
   1607                                                                     sh::BlockMemberInfo *infoOut) {
   1608        return shaderStorageBlockInfo.getBlockMemberInfo(name, mappedName, infoOut);
   1609    };
   1610 
   1611    // Link storage buffer interface blocks.
   1612    resources.shaderStorageBlockLinker.linkBlocks(getShaderStorageBlockSize,
   1613                                                  getShaderStorageBlockMemberInfo);
   1614 
   1615    // Gather and link atomic counter buffer interface blocks.
   1616    std::map<int, unsigned int> sizeMap;
   1617    getAtomicCounterBufferSizeMap(programState, sizeMap);
   1618    resources.atomicCounterBufferLinker.link(sizeMap);
   1619 }
   1620 
   1621 void ProgramLinkedResourcesLinker::getAtomicCounterBufferSizeMap(
   1622    const ProgramState &programState,
   1623    std::map<int, unsigned int> &sizeMapOut) const
   1624 {
   1625    for (unsigned int index : programState.getAtomicCounterUniformRange())
   1626    {
   1627        const LinkedUniform &glUniform = programState.getUniforms()[index];
   1628 
   1629        auto &bufferDataSize = sizeMapOut[glUniform.binding];
   1630 
   1631        // Calculate the size of the buffer by finding the end of the last uniform with the same
   1632        // binding. The end of the uniform is calculated by finding the initial offset of the
   1633        // uniform and adding size of the uniform. For arrays, the size is the number of elements
   1634        // times the element size (should always by 4 for atomic_units).
   1635        unsigned dataOffset =
   1636            glUniform.offset + static_cast<unsigned int>(glUniform.getBasicTypeElementCount() *
   1637                                                         glUniform.getElementSize());
   1638        if (dataOffset > bufferDataSize)
   1639        {
   1640            bufferDataSize = dataOffset;
   1641        }
   1642    }
   1643 }
   1644 
   1645 bool LinkValidateProgramGlobalNames(InfoLog &infoLog,
   1646                                    const ProgramExecutable &executable,
   1647                                    const LinkingVariables &linkingVariables)
   1648 {
   1649    angle::HashMap<std::string, const sh::ShaderVariable *> uniformMap;
   1650    using BlockAndFieldPair = std::pair<const sh::InterfaceBlock *, const sh::ShaderVariable *>;
   1651    angle::HashMap<std::string, std::vector<BlockAndFieldPair>> uniformBlockFieldMap;
   1652 
   1653    for (ShaderType shaderType : kAllGraphicsShaderTypes)
   1654    {
   1655        if (!linkingVariables.isShaderStageUsedBitset[shaderType])
   1656        {
   1657            continue;
   1658        }
   1659 
   1660        // Build a map of Uniforms
   1661        const std::vector<sh::ShaderVariable> &uniforms = linkingVariables.uniforms[shaderType];
   1662        for (const auto &uniform : uniforms)
   1663        {
   1664            uniformMap[uniform.name] = &uniform;
   1665        }
   1666 
   1667        // Build a map of Uniform Blocks
   1668        // This will also detect any field name conflicts between Uniform Blocks without instance
   1669        // names
   1670        const std::vector<sh::InterfaceBlock> &uniformBlocks =
   1671            linkingVariables.uniformBlocks[shaderType];
   1672 
   1673        for (const auto &uniformBlock : uniformBlocks)
   1674        {
   1675            // Only uniform blocks without an instance name can create a conflict with their field
   1676            // names
   1677            if (!uniformBlock.instanceName.empty())
   1678            {
   1679                continue;
   1680            }
   1681 
   1682            for (const auto &field : uniformBlock.fields)
   1683            {
   1684                if (!uniformBlockFieldMap.count(field.name))
   1685                {
   1686                    // First time we've seen this uniform block field name, so add the
   1687                    // (Uniform Block, Field) pair immediately since there can't be a conflict yet
   1688                    BlockAndFieldPair blockAndFieldPair(&uniformBlock, &field);
   1689                    std::vector<BlockAndFieldPair> newUniformBlockList;
   1690                    newUniformBlockList.push_back(blockAndFieldPair);
   1691                    uniformBlockFieldMap[field.name] = newUniformBlockList;
   1692                    continue;
   1693                }
   1694 
   1695                // We've seen this name before.
   1696                // We need to check each of the uniform blocks that contain a field with this name
   1697                // to see if there's a conflict or not.
   1698                std::vector<BlockAndFieldPair> prevBlockFieldPairs =
   1699                    uniformBlockFieldMap[field.name];
   1700                for (const auto &prevBlockFieldPair : prevBlockFieldPairs)
   1701                {
   1702                    const sh::InterfaceBlock *prevUniformBlock      = prevBlockFieldPair.first;
   1703                    const sh::ShaderVariable *prevUniformBlockField = prevBlockFieldPair.second;
   1704 
   1705                    if (uniformBlock.isSameInterfaceBlockAtLinkTime(*prevUniformBlock))
   1706                    {
   1707                        // The same uniform block should, by definition, contain the same field name
   1708                        continue;
   1709                    }
   1710 
   1711                    // The uniform blocks don't match, so check if the necessary field properties
   1712                    // also match
   1713                    if ((field.name == prevUniformBlockField->name) &&
   1714                        (field.type == prevUniformBlockField->type) &&
   1715                        (field.precision == prevUniformBlockField->precision))
   1716                    {
   1717                        infoLog << "Name conflicts between uniform block field names: "
   1718                                << field.name;
   1719                        return false;
   1720                    }
   1721                }
   1722 
   1723                // No conflict, so record this pair
   1724                BlockAndFieldPair blockAndFieldPair(&uniformBlock, &field);
   1725                uniformBlockFieldMap[field.name].push_back(blockAndFieldPair);
   1726            }
   1727        }
   1728    }
   1729 
   1730    // Validate no uniform names conflict with attribute names
   1731    if (linkingVariables.isShaderStageUsedBitset[ShaderType::Vertex])
   1732    {
   1733        // ESSL 3.00.6 section 4.3.5:
   1734        // If a uniform variable name is declared in one stage (e.g., a vertex shader)
   1735        // but not in another (e.g., a fragment shader), then that name is still
   1736        // available in the other stage for a different use.
   1737        std::unordered_set<std::string> uniforms;
   1738        for (const sh::ShaderVariable &uniform : linkingVariables.uniforms[ShaderType::Vertex])
   1739        {
   1740            uniforms.insert(uniform.name);
   1741        }
   1742        for (const auto &attrib : executable.getProgramInputs())
   1743        {
   1744            if (uniforms.count(attrib.name))
   1745            {
   1746                infoLog << "Name conflicts between a uniform and an attribute: " << attrib.name;
   1747                return false;
   1748            }
   1749        }
   1750    }
   1751 
   1752    // Validate no Uniform Block fields conflict with other Uniforms
   1753    for (const auto &uniformBlockField : uniformBlockFieldMap)
   1754    {
   1755        const std::string &fieldName = uniformBlockField.first;
   1756        if (uniformMap.count(fieldName))
   1757        {
   1758            infoLog << "Name conflicts between a uniform and a uniform block field: " << fieldName;
   1759            return false;
   1760        }
   1761    }
   1762 
   1763    return true;
   1764 }
   1765 
   1766 // [OpenGL ES 3.2] Chapter 7.4.1 "Shader Interface Matching"
   1767 bool LinkValidateShaderInterfaceMatching(const std::vector<sh::ShaderVariable> &outputVaryings,
   1768                                         const std::vector<sh::ShaderVariable> &inputVaryings,
   1769                                         ShaderType frontShaderType,
   1770                                         ShaderType backShaderType,
   1771                                         int frontShaderVersion,
   1772                                         int backShaderVersion,
   1773                                         bool isSeparable,
   1774                                         gl::InfoLog &infoLog)
   1775 {
   1776    ASSERT(frontShaderVersion == backShaderVersion);
   1777 
   1778    std::vector<const sh::ShaderVariable *> filteredInputVaryings;
   1779    std::vector<const sh::ShaderVariable *> filteredOutputVaryings;
   1780 
   1781    GetFilteredVaryings(inputVaryings, &filteredInputVaryings);
   1782    GetFilteredVaryings(outputVaryings, &filteredOutputVaryings);
   1783 
   1784    // Separable programs require the number of inputs and outputs match
   1785    if (isSeparable && filteredInputVaryings.size() < filteredOutputVaryings.size())
   1786    {
   1787        infoLog << GetShaderTypeString(backShaderType)
   1788                << " does not consume all varyings generated by "
   1789                << GetShaderTypeString(frontShaderType);
   1790        return false;
   1791    }
   1792    if (isSeparable && filteredInputVaryings.size() > filteredOutputVaryings.size())
   1793    {
   1794        infoLog << GetShaderTypeString(frontShaderType)
   1795                << " does not generate all varyings consumed by "
   1796                << GetShaderTypeString(backShaderType);
   1797        return false;
   1798    }
   1799 
   1800    // All inputs must match all outputs
   1801    for (const sh::ShaderVariable *input : filteredInputVaryings)
   1802    {
   1803        bool match = false;
   1804        for (const sh::ShaderVariable *output : filteredOutputVaryings)
   1805        {
   1806            if (DoShaderVariablesMatch(frontShaderVersion, frontShaderType, backShaderType, *input,
   1807                                       *output, isSeparable, infoLog))
   1808            {
   1809                match = true;
   1810                break;
   1811            }
   1812        }
   1813 
   1814        // We permit unmatched, unreferenced varyings. Note that this specifically depends on
   1815        // whether the input is statically used - a statically used input should fail this test even
   1816        // if it is not active. GLSL ES 3.00.6 section 4.3.10.
   1817        if (!match && input->staticUse)
   1818        {
   1819            const std::string &name =
   1820                input->isShaderIOBlock ? input->structOrBlockName : input->name;
   1821            infoLog << GetShaderTypeString(backShaderType) << " varying " << name
   1822                    << " does not match any " << GetShaderTypeString(frontShaderType) << " varying";
   1823            return false;
   1824        }
   1825    }
   1826 
   1827    return true;
   1828 }
   1829 
   1830 LinkMismatchError LinkValidateProgramVariables(const sh::ShaderVariable &variable1,
   1831                                               const sh::ShaderVariable &variable2,
   1832                                               bool validatePrecision,
   1833                                               bool treatVariable1AsNonArray,
   1834                                               bool treatVariable2AsNonArray,
   1835                                               std::string *mismatchedStructOrBlockMemberName)
   1836 {
   1837    if (variable1.type != variable2.type)
   1838    {
   1839        return LinkMismatchError::TYPE_MISMATCH;
   1840    }
   1841 
   1842    bool variable1IsArray = variable1.isArray();
   1843    bool variable2IsArray = variable2.isArray();
   1844    if (treatVariable1AsNonArray)
   1845    {
   1846        ASSERT(variable1IsArray);
   1847        variable1IsArray = false;
   1848    }
   1849    if (treatVariable2AsNonArray)
   1850    {
   1851        ASSERT(variable2IsArray);
   1852        variable2IsArray = false;
   1853    }
   1854    // TODO(anglebug.com/5557): Investigate interactions with arrays-of-arrays.
   1855    if (variable1IsArray != variable2IsArray)
   1856    {
   1857        return LinkMismatchError::ARRAYNESS_MISMATCH;
   1858    }
   1859    if (!treatVariable1AsNonArray && !treatVariable2AsNonArray &&
   1860        variable1.arraySizes != variable2.arraySizes)
   1861    {
   1862        return LinkMismatchError::ARRAY_SIZE_MISMATCH;
   1863    }
   1864    if (validatePrecision && variable1.precision != variable2.precision)
   1865    {
   1866        return LinkMismatchError::PRECISION_MISMATCH;
   1867    }
   1868    if (!variable1.isShaderIOBlock && !variable2.isShaderIOBlock &&
   1869        variable1.structOrBlockName != variable2.structOrBlockName)
   1870    {
   1871        return LinkMismatchError::STRUCT_NAME_MISMATCH;
   1872    }
   1873    if (variable1.imageUnitFormat != variable2.imageUnitFormat)
   1874    {
   1875        return LinkMismatchError::FORMAT_MISMATCH;
   1876    }
   1877 
   1878    if (variable1.fields.size() != variable2.fields.size())
   1879    {
   1880        return LinkMismatchError::FIELD_NUMBER_MISMATCH;
   1881    }
   1882    const unsigned int numMembers = static_cast<unsigned int>(variable1.fields.size());
   1883    for (unsigned int memberIndex = 0; memberIndex < numMembers; memberIndex++)
   1884    {
   1885        const sh::ShaderVariable &member1 = variable1.fields[memberIndex];
   1886        const sh::ShaderVariable &member2 = variable2.fields[memberIndex];
   1887 
   1888        if (member1.name != member2.name)
   1889        {
   1890            return LinkMismatchError::FIELD_NAME_MISMATCH;
   1891        }
   1892 
   1893        if (member1.interpolation != member2.interpolation)
   1894        {
   1895            return LinkMismatchError::INTERPOLATION_TYPE_MISMATCH;
   1896        }
   1897 
   1898        if (variable1.isShaderIOBlock && variable2.isShaderIOBlock)
   1899        {
   1900            if (member1.location != member2.location)
   1901            {
   1902                return LinkMismatchError::FIELD_LOCATION_MISMATCH;
   1903            }
   1904 
   1905            if (member1.structOrBlockName != member2.structOrBlockName)
   1906            {
   1907                return LinkMismatchError::FIELD_STRUCT_NAME_MISMATCH;
   1908            }
   1909        }
   1910 
   1911        LinkMismatchError linkErrorOnField = LinkValidateProgramVariables(
   1912            member1, member2, validatePrecision, false, false, mismatchedStructOrBlockMemberName);
   1913        if (linkErrorOnField != LinkMismatchError::NO_MISMATCH)
   1914        {
   1915            AddProgramVariableParentPrefix(member1.name, mismatchedStructOrBlockMemberName);
   1916            return linkErrorOnField;
   1917        }
   1918    }
   1919 
   1920    return LinkMismatchError::NO_MISMATCH;
   1921 }
   1922 
   1923 void AddProgramVariableParentPrefix(const std::string &parentName, std::string *mismatchedFieldName)
   1924 {
   1925    ASSERT(mismatchedFieldName);
   1926    if (mismatchedFieldName->empty())
   1927    {
   1928        *mismatchedFieldName = parentName;
   1929    }
   1930    else
   1931    {
   1932        std::ostringstream stream;
   1933        stream << parentName << "." << *mismatchedFieldName;
   1934        *mismatchedFieldName = stream.str();
   1935    }
   1936 }
   1937 
   1938 bool LinkValidateBuiltInVaryingsInvariant(const std::vector<sh::ShaderVariable> &vertexVaryings,
   1939                                          const std::vector<sh::ShaderVariable> &fragmentVaryings,
   1940                                          int vertexShaderVersion,
   1941                                          InfoLog &infoLog)
   1942 {
   1943    bool glPositionIsInvariant   = false;
   1944    bool glPointSizeIsInvariant  = false;
   1945    bool glFragCoordIsInvariant  = false;
   1946    bool glPointCoordIsInvariant = false;
   1947 
   1948    for (const sh::ShaderVariable &varying : vertexVaryings)
   1949    {
   1950        if (!varying.isBuiltIn())
   1951        {
   1952            continue;
   1953        }
   1954        if (varying.name.compare("gl_Position") == 0)
   1955        {
   1956            glPositionIsInvariant = varying.isInvariant;
   1957        }
   1958        else if (varying.name.compare("gl_PointSize") == 0)
   1959        {
   1960            glPointSizeIsInvariant = varying.isInvariant;
   1961        }
   1962    }
   1963 
   1964    for (const sh::ShaderVariable &varying : fragmentVaryings)
   1965    {
   1966        if (!varying.isBuiltIn())
   1967        {
   1968            continue;
   1969        }
   1970        if (varying.name.compare("gl_FragCoord") == 0)
   1971        {
   1972            glFragCoordIsInvariant = varying.isInvariant;
   1973        }
   1974        else if (varying.name.compare("gl_PointCoord") == 0)
   1975        {
   1976            glPointCoordIsInvariant = varying.isInvariant;
   1977        }
   1978    }
   1979 
   1980    // There is some ambiguity in ESSL 1.00.17 paragraph 4.6.4 interpretation,
   1981    // for example, https://cvs.khronos.org/bugzilla/show_bug.cgi?id=13842.
   1982    // Not requiring invariance to match is supported by:
   1983    // dEQP, WebGL CTS, Nexus 5X GLES
   1984    if (glFragCoordIsInvariant && !glPositionIsInvariant)
   1985    {
   1986        infoLog << "gl_FragCoord can only be declared invariant if and only if gl_Position is "
   1987                   "declared invariant.";
   1988        return false;
   1989    }
   1990    if (glPointCoordIsInvariant && !glPointSizeIsInvariant)
   1991    {
   1992        infoLog << "gl_PointCoord can only be declared invariant if and only if gl_PointSize is "
   1993                   "declared invariant.";
   1994        return false;
   1995    }
   1996 
   1997    return true;
   1998 }
   1999 
   2000 bool LinkValidateBuiltInVaryings(const std::vector<sh::ShaderVariable> &outputVaryings,
   2001                                 const std::vector<sh::ShaderVariable> &inputVaryings,
   2002                                 ShaderType outputShaderType,
   2003                                 ShaderType inputShaderType,
   2004                                 int outputShaderVersion,
   2005                                 int inputShaderVersion,
   2006                                 InfoLog &infoLog)
   2007 {
   2008    ASSERT(outputShaderVersion == inputShaderVersion);
   2009 
   2010    // Only ESSL 1.0 has restrictions on matching input and output invariance
   2011    if (inputShaderVersion == 100 && outputShaderType == ShaderType::Vertex &&
   2012        inputShaderType == ShaderType::Fragment)
   2013    {
   2014        return LinkValidateBuiltInVaryingsInvariant(outputVaryings, inputVaryings,
   2015                                                    outputShaderVersion, infoLog);
   2016    }
   2017 
   2018    uint32_t sizeClipDistance = 0;
   2019    uint32_t sizeCullDistance = 0;
   2020 
   2021    for (const sh::ShaderVariable &varying : outputVaryings)
   2022    {
   2023        if (!varying.isBuiltIn())
   2024        {
   2025            continue;
   2026        }
   2027        if (varying.name.compare("gl_ClipDistance") == 0)
   2028        {
   2029            sizeClipDistance = varying.getOutermostArraySize();
   2030        }
   2031        else if (varying.name.compare("gl_CullDistance") == 0)
   2032        {
   2033            sizeCullDistance = varying.getOutermostArraySize();
   2034        }
   2035    }
   2036 
   2037    for (const sh::ShaderVariable &varying : inputVaryings)
   2038    {
   2039        if (!varying.isBuiltIn())
   2040        {
   2041            continue;
   2042        }
   2043        if (varying.name.compare("gl_ClipDistance") == 0)
   2044        {
   2045            if (sizeClipDistance != varying.getOutermostArraySize())
   2046            {
   2047                infoLog << "If either shader redeclares the built-in arrays gl_ClipDistance[] the "
   2048                           "array must have the same size in both shaders.";
   2049                return false;
   2050            }
   2051        }
   2052        else if (varying.name.compare("gl_CullDistance") == 0)
   2053        {
   2054            if (sizeCullDistance != varying.getOutermostArraySize())
   2055            {
   2056                infoLog << "If either shader redeclares the built-in arrays gl_CullDistance[] the "
   2057                           "array must have the same size in both shaders.";
   2058                return false;
   2059            }
   2060        }
   2061    }
   2062    return true;
   2063 }
   2064 
   2065 void LogAmbiguousFieldLinkMismatch(InfoLog &infoLog,
   2066                                   const std::string &blockName1,
   2067                                   const std::string &blockName2,
   2068                                   const std::string &fieldName,
   2069                                   ShaderType shaderType1,
   2070                                   ShaderType shaderType2)
   2071 {
   2072    infoLog << "Ambiguous field '" << fieldName << "' in blocks '" << blockName1 << "' ("
   2073            << GetShaderTypeString(shaderType1) << " shader) and '" << blockName2 << "' ("
   2074            << GetShaderTypeString(shaderType2) << " shader) which don't have instance names.";
   2075 }
   2076 
   2077 bool ValidateInstancelessGraphicsInterfaceBlocksPerShader(
   2078    const std::vector<sh::InterfaceBlock> &interfaceBlocks,
   2079    ShaderType shaderType,
   2080    InterfaceBlockMap *instancelessBlocksFields,
   2081    InfoLog &infoLog)
   2082 {
   2083    ASSERT(instancelessBlocksFields);
   2084 
   2085    for (const sh::InterfaceBlock &block : interfaceBlocks)
   2086    {
   2087        if (!block.instanceName.empty())
   2088        {
   2089            continue;
   2090        }
   2091 
   2092        for (const sh::ShaderVariable &field : block.fields)
   2093        {
   2094            const auto &entry = instancelessBlocksFields->find(field.name);
   2095            if (entry != instancelessBlocksFields->end())
   2096            {
   2097                const sh::InterfaceBlock &linkedBlock = *(entry->second.second);
   2098                if (block.name != linkedBlock.name)
   2099                {
   2100                    LogAmbiguousFieldLinkMismatch(infoLog, block.name, linkedBlock.name, field.name,
   2101                                                  entry->second.first, shaderType);
   2102                    return false;
   2103                }
   2104            }
   2105            else
   2106            {
   2107                (*instancelessBlocksFields)[field.name] = std::make_pair(shaderType, &block);
   2108            }
   2109        }
   2110    }
   2111 
   2112    return true;
   2113 }
   2114 
   2115 LinkMismatchError LinkValidateInterfaceBlockFields(const sh::ShaderVariable &blockField1,
   2116                                                   const sh::ShaderVariable &blockField2,
   2117                                                   bool webglCompatibility,
   2118                                                   std::string *mismatchedBlockFieldName)
   2119 {
   2120    if (blockField1.name != blockField2.name)
   2121    {
   2122        return LinkMismatchError::FIELD_NAME_MISMATCH;
   2123    }
   2124 
   2125    // If webgl, validate precision of UBO fields, otherwise don't.  See Khronos bug 10287.
   2126    LinkMismatchError linkError = LinkValidateProgramVariables(
   2127        blockField1, blockField2, webglCompatibility, false, false, mismatchedBlockFieldName);
   2128    if (linkError != LinkMismatchError::NO_MISMATCH)
   2129    {
   2130        AddProgramVariableParentPrefix(blockField1.name, mismatchedBlockFieldName);
   2131        return linkError;
   2132    }
   2133 
   2134    if (blockField1.isRowMajorLayout != blockField2.isRowMajorLayout)
   2135    {
   2136        AddProgramVariableParentPrefix(blockField1.name, mismatchedBlockFieldName);
   2137        return LinkMismatchError::MATRIX_PACKING_MISMATCH;
   2138    }
   2139 
   2140    return LinkMismatchError::NO_MISMATCH;
   2141 }
   2142 
   2143 LinkMismatchError AreMatchingInterfaceBlocks(const sh::InterfaceBlock &interfaceBlock1,
   2144                                             const sh::InterfaceBlock &interfaceBlock2,
   2145                                             bool webglCompatibility,
   2146                                             std::string *mismatchedBlockFieldName)
   2147 {
   2148    // validate blocks for the same member types
   2149    if (interfaceBlock1.fields.size() != interfaceBlock2.fields.size())
   2150    {
   2151        return LinkMismatchError::FIELD_NUMBER_MISMATCH;
   2152    }
   2153    if (interfaceBlock1.arraySize != interfaceBlock2.arraySize)
   2154    {
   2155        return LinkMismatchError::ARRAY_SIZE_MISMATCH;
   2156    }
   2157    if (interfaceBlock1.layout != interfaceBlock2.layout ||
   2158        interfaceBlock1.binding != interfaceBlock2.binding)
   2159    {
   2160        return LinkMismatchError::LAYOUT_QUALIFIER_MISMATCH;
   2161    }
   2162    if (interfaceBlock1.instanceName.empty() != interfaceBlock2.instanceName.empty())
   2163    {
   2164        return LinkMismatchError::INSTANCE_NAME_MISMATCH;
   2165    }
   2166    const unsigned int numBlockMembers = static_cast<unsigned int>(interfaceBlock1.fields.size());
   2167    for (unsigned int blockMemberIndex = 0; blockMemberIndex < numBlockMembers; blockMemberIndex++)
   2168    {
   2169        const sh::ShaderVariable &member1 = interfaceBlock1.fields[blockMemberIndex];
   2170        const sh::ShaderVariable &member2 = interfaceBlock2.fields[blockMemberIndex];
   2171 
   2172        LinkMismatchError linkError = LinkValidateInterfaceBlockFields(
   2173            member1, member2, webglCompatibility, mismatchedBlockFieldName);
   2174        if (linkError != LinkMismatchError::NO_MISMATCH)
   2175        {
   2176            return linkError;
   2177        }
   2178    }
   2179    return LinkMismatchError::NO_MISMATCH;
   2180 }
   2181 
   2182 void InitializeInterfaceBlockMap(const std::vector<sh::InterfaceBlock> &interfaceBlocks,
   2183                                 ShaderType shaderType,
   2184                                 InterfaceBlockMap *linkedInterfaceBlocks)
   2185 {
   2186    ASSERT(linkedInterfaceBlocks);
   2187 
   2188    for (const sh::InterfaceBlock &interfaceBlock : interfaceBlocks)
   2189    {
   2190        (*linkedInterfaceBlocks)[interfaceBlock.name] = std::make_pair(shaderType, &interfaceBlock);
   2191    }
   2192 }
   2193 
   2194 bool ValidateGraphicsInterfaceBlocksPerShader(
   2195    const std::vector<sh::InterfaceBlock> &interfaceBlocksToLink,
   2196    ShaderType shaderType,
   2197    bool webglCompatibility,
   2198    InterfaceBlockMap *linkedBlocks,
   2199    InfoLog &infoLog)
   2200 {
   2201    ASSERT(linkedBlocks);
   2202 
   2203    for (const sh::InterfaceBlock &block : interfaceBlocksToLink)
   2204    {
   2205        const auto &entry = linkedBlocks->find(block.name);
   2206        if (entry != linkedBlocks->end())
   2207        {
   2208            const sh::InterfaceBlock &linkedBlock = *(entry->second.second);
   2209            std::string mismatchedStructFieldName;
   2210            LinkMismatchError linkError = AreMatchingInterfaceBlocks(
   2211                block, linkedBlock, webglCompatibility, &mismatchedStructFieldName);
   2212            if (linkError != LinkMismatchError::NO_MISMATCH)
   2213            {
   2214                LogLinkMismatch(infoLog, block.name, GetInterfaceBlockTypeString(block.blockType),
   2215                                linkError, mismatchedStructFieldName, entry->second.first,
   2216                                shaderType);
   2217                return false;
   2218            }
   2219        }
   2220        else
   2221        {
   2222            (*linkedBlocks)[block.name] = std::make_pair(shaderType, &block);
   2223        }
   2224    }
   2225 
   2226    return true;
   2227 }
   2228 
   2229 bool ValidateInterfaceBlocksMatch(
   2230    GLuint numShadersHasInterfaceBlocks,
   2231    const ShaderMap<const std::vector<sh::InterfaceBlock> *> &shaderInterfaceBlocks,
   2232    InfoLog &infoLog,
   2233    bool webglCompatibility,
   2234    InterfaceBlockMap *instancelessInterfaceBlocksFields)
   2235 {
   2236    for (ShaderType shaderType : kAllGraphicsShaderTypes)
   2237    {
   2238        // Validate that instanceless blocks of different names don't have fields of the same name.
   2239        if (shaderInterfaceBlocks[shaderType] &&
   2240            !ValidateInstancelessGraphicsInterfaceBlocksPerShader(
   2241                *shaderInterfaceBlocks[shaderType], shaderType, instancelessInterfaceBlocksFields,
   2242                infoLog))
   2243        {
   2244            return false;
   2245        }
   2246    }
   2247 
   2248    if (numShadersHasInterfaceBlocks < 2u)
   2249    {
   2250        return true;
   2251    }
   2252 
   2253    ASSERT(!shaderInterfaceBlocks[ShaderType::Compute]);
   2254 
   2255    // Check that interface blocks defined in the graphics shaders are identical
   2256 
   2257    InterfaceBlockMap linkedInterfaceBlocks;
   2258 
   2259    bool interfaceBlockMapInitialized = false;
   2260    for (ShaderType shaderType : kAllGraphicsShaderTypes)
   2261    {
   2262        if (!shaderInterfaceBlocks[shaderType])
   2263        {
   2264            continue;
   2265        }
   2266 
   2267        if (!interfaceBlockMapInitialized)
   2268        {
   2269            InitializeInterfaceBlockMap(*shaderInterfaceBlocks[shaderType], shaderType,
   2270                                        &linkedInterfaceBlocks);
   2271            interfaceBlockMapInitialized = true;
   2272        }
   2273        else if (!ValidateGraphicsInterfaceBlocksPerShader(*shaderInterfaceBlocks[shaderType],
   2274                                                           shaderType, webglCompatibility,
   2275                                                           &linkedInterfaceBlocks, infoLog))
   2276        {
   2277            return false;
   2278        }
   2279    }
   2280 
   2281    return true;
   2282 }
   2283 
   2284 bool LinkValidateProgramInterfaceBlocks(const Context *context,
   2285                                        ShaderBitSet activeProgramStages,
   2286                                        const ProgramLinkedResources &resources,
   2287                                        InfoLog &infoLog,
   2288                                        GLuint *combinedShaderStorageBlocksCountOut)
   2289 {
   2290    ASSERT(combinedShaderStorageBlocksCountOut);
   2291 
   2292    const Caps &caps              = context->getCaps();
   2293    const bool webglCompatibility = context->isWebGL();
   2294    const Version &version        = context->getClientVersion();
   2295 
   2296    GLuint combinedUniformBlocksCount                                         = 0u;
   2297    GLuint numShadersHasUniformBlocks                                         = 0u;
   2298    ShaderMap<const std::vector<sh::InterfaceBlock> *> allShaderUniformBlocks = {};
   2299    InterfaceBlockMap instancelessInterfaceBlocksFields;
   2300 
   2301    for (ShaderType shaderType : activeProgramStages)
   2302    {
   2303        const std::vector<sh::InterfaceBlock> &uniformBlocks =
   2304            resources.uniformBlockLinker.getShaderBlocks(shaderType);
   2305        if (!uniformBlocks.empty())
   2306        {
   2307            if (!ValidateInterfaceBlocksCount(
   2308                    static_cast<GLuint>(caps.maxShaderUniformBlocks[shaderType]), uniformBlocks,
   2309                    shaderType, sh::BlockType::BLOCK_UNIFORM, &combinedUniformBlocksCount, infoLog))
   2310            {
   2311                return false;
   2312            }
   2313 
   2314            allShaderUniformBlocks[shaderType] = &uniformBlocks;
   2315            ++numShadersHasUniformBlocks;
   2316        }
   2317    }
   2318 
   2319    if (combinedUniformBlocksCount > static_cast<GLuint>(caps.maxCombinedUniformBlocks))
   2320    {
   2321        infoLog << "The sum of the number of active uniform blocks exceeds "
   2322                   "MAX_COMBINED_UNIFORM_BLOCKS ("
   2323                << caps.maxCombinedUniformBlocks << ").";
   2324        return false;
   2325    }
   2326 
   2327    if (!ValidateInterfaceBlocksMatch(numShadersHasUniformBlocks, allShaderUniformBlocks, infoLog,
   2328                                      webglCompatibility, &instancelessInterfaceBlocksFields))
   2329    {
   2330        return false;
   2331    }
   2332 
   2333    if (version >= Version(3, 1))
   2334    {
   2335        *combinedShaderStorageBlocksCountOut                                      = 0u;
   2336        GLuint numShadersHasShaderStorageBlocks                                   = 0u;
   2337        ShaderMap<const std::vector<sh::InterfaceBlock> *> allShaderStorageBlocks = {};
   2338        for (ShaderType shaderType : activeProgramStages)
   2339        {
   2340            const std::vector<sh::InterfaceBlock> &shaderStorageBlocks =
   2341                resources.shaderStorageBlockLinker.getShaderBlocks(shaderType);
   2342            if (!shaderStorageBlocks.empty())
   2343            {
   2344                if (!ValidateInterfaceBlocksCount(
   2345                        static_cast<GLuint>(caps.maxShaderStorageBlocks[shaderType]),
   2346                        shaderStorageBlocks, shaderType, sh::BlockType::BLOCK_BUFFER,
   2347                        combinedShaderStorageBlocksCountOut, infoLog))
   2348                {
   2349                    return false;
   2350                }
   2351 
   2352                allShaderStorageBlocks[shaderType] = &shaderStorageBlocks;
   2353                ++numShadersHasShaderStorageBlocks;
   2354            }
   2355        }
   2356 
   2357        if (*combinedShaderStorageBlocksCountOut >
   2358            static_cast<GLuint>(caps.maxCombinedShaderStorageBlocks))
   2359        {
   2360            infoLog << "The sum of the number of active shader storage blocks exceeds "
   2361                       "MAX_COMBINED_SHADER_STORAGE_BLOCKS ("
   2362                    << caps.maxCombinedShaderStorageBlocks << ").";
   2363            return false;
   2364        }
   2365 
   2366        if (!ValidateInterfaceBlocksMatch(numShadersHasShaderStorageBlocks, allShaderStorageBlocks,
   2367                                          infoLog, webglCompatibility,
   2368                                          &instancelessInterfaceBlocksFields))
   2369        {
   2370            return false;
   2371        }
   2372    }
   2373 
   2374    return true;
   2375 }
   2376 
   2377 }  // namespace gl