tor-browser

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

ProgramExecutable.cpp (69227B)


      1 //
      2 // Copyright 2020 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 // ProgramExecutable.cpp: Collects the interfaces common to both Programs and
      7 // ProgramPipelines in order to execute/draw with either.
      8 
      9 #include "libANGLE/ProgramExecutable.h"
     10 
     11 #include "common/string_utils.h"
     12 #include "libANGLE/Context.h"
     13 #include "libANGLE/Program.h"
     14 #include "libANGLE/Shader.h"
     15 
     16 namespace gl
     17 {
     18 namespace
     19 {
     20 bool IncludeSameArrayElement(const std::set<std::string> &nameSet, const std::string &name)
     21 {
     22    std::vector<unsigned int> subscripts;
     23    std::string baseName = ParseResourceName(name, &subscripts);
     24    for (const std::string &nameInSet : nameSet)
     25    {
     26        std::vector<unsigned int> arrayIndices;
     27        std::string arrayName = ParseResourceName(nameInSet, &arrayIndices);
     28        if (baseName == arrayName &&
     29            (subscripts.empty() || arrayIndices.empty() || subscripts == arrayIndices))
     30        {
     31            return true;
     32        }
     33    }
     34    return false;
     35 }
     36 
     37 // Find the matching varying or field by name.
     38 const sh::ShaderVariable *FindOutputVaryingOrField(const ProgramMergedVaryings &varyings,
     39                                                   ShaderType stage,
     40                                                   const std::string &name)
     41 {
     42    const sh::ShaderVariable *var = nullptr;
     43    for (const ProgramVaryingRef &ref : varyings)
     44    {
     45        if (ref.frontShaderStage != stage)
     46        {
     47            continue;
     48        }
     49 
     50        const sh::ShaderVariable *varying = ref.get(stage);
     51        if (varying->name == name)
     52        {
     53            var = varying;
     54            break;
     55        }
     56        GLuint fieldIndex = 0;
     57        var               = varying->findField(name, &fieldIndex);
     58        if (var != nullptr)
     59        {
     60            break;
     61        }
     62    }
     63    return var;
     64 }
     65 
     66 bool FindUsedOutputLocation(std::vector<VariableLocation> &outputLocations,
     67                            unsigned int baseLocation,
     68                            unsigned int elementCount,
     69                            const std::vector<VariableLocation> &reservedLocations,
     70                            unsigned int variableIndex)
     71 {
     72    if (baseLocation + elementCount > outputLocations.size())
     73    {
     74        elementCount = baseLocation < outputLocations.size()
     75                           ? static_cast<unsigned int>(outputLocations.size() - baseLocation)
     76                           : 0;
     77    }
     78    for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
     79    {
     80        const unsigned int location = baseLocation + elementIndex;
     81        if (outputLocations[location].used())
     82        {
     83            VariableLocation locationInfo(elementIndex, variableIndex);
     84            if (std::find(reservedLocations.begin(), reservedLocations.end(), locationInfo) ==
     85                reservedLocations.end())
     86            {
     87                return true;
     88            }
     89        }
     90    }
     91    return false;
     92 }
     93 
     94 void AssignOutputLocations(std::vector<VariableLocation> &outputLocations,
     95                           unsigned int baseLocation,
     96                           unsigned int elementCount,
     97                           const std::vector<VariableLocation> &reservedLocations,
     98                           unsigned int variableIndex,
     99                           sh::ShaderVariable &outputVariable)
    100 {
    101    if (baseLocation + elementCount > outputLocations.size())
    102    {
    103        outputLocations.resize(baseLocation + elementCount);
    104    }
    105    for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
    106    {
    107        VariableLocation locationInfo(elementIndex, variableIndex);
    108        if (std::find(reservedLocations.begin(), reservedLocations.end(), locationInfo) ==
    109            reservedLocations.end())
    110        {
    111            outputVariable.location     = baseLocation;
    112            const unsigned int location = baseLocation + elementIndex;
    113            outputLocations[location]   = locationInfo;
    114        }
    115    }
    116 }
    117 
    118 int GetOutputLocationForLink(const ProgramAliasedBindings &fragmentOutputLocations,
    119                             const sh::ShaderVariable &outputVariable)
    120 {
    121    if (outputVariable.location != -1)
    122    {
    123        return outputVariable.location;
    124    }
    125    int apiLocation = fragmentOutputLocations.getBinding(outputVariable);
    126    if (apiLocation != -1)
    127    {
    128        return apiLocation;
    129    }
    130    return -1;
    131 }
    132 
    133 bool IsOutputSecondaryForLink(const ProgramAliasedBindings &fragmentOutputIndexes,
    134                              const sh::ShaderVariable &outputVariable)
    135 {
    136    if (outputVariable.index != -1)
    137    {
    138        ASSERT(outputVariable.index == 0 || outputVariable.index == 1);
    139        return (outputVariable.index == 1);
    140    }
    141    int apiIndex = fragmentOutputIndexes.getBinding(outputVariable);
    142    if (apiIndex != -1)
    143    {
    144        // Index layout qualifier from the shader takes precedence, so the index from the API is
    145        // checked only if the index was not set in the shader. This is not specified in the EXT
    146        // spec, but is specified in desktop OpenGL specs.
    147        return (apiIndex == 1);
    148    }
    149    // EXT_blend_func_extended: Outputs get index 0 by default.
    150    return false;
    151 }
    152 
    153 RangeUI AddUniforms(const ShaderMap<Program *> &programs,
    154                    ShaderBitSet activeShaders,
    155                    std::vector<LinkedUniform> &outputUniforms,
    156                    const std::function<RangeUI(const ProgramState &)> &getRange)
    157 {
    158    unsigned int startRange = static_cast<unsigned int>(outputUniforms.size());
    159    for (ShaderType shaderType : activeShaders)
    160    {
    161        const ProgramState &programState                  = programs[shaderType]->getState();
    162        const std::vector<LinkedUniform> &programUniforms = programState.getUniforms();
    163        const RangeUI uniformRange                        = getRange(programState);
    164 
    165        outputUniforms.insert(outputUniforms.end(), programUniforms.begin() + uniformRange.low(),
    166                              programUniforms.begin() + uniformRange.high());
    167    }
    168    return RangeUI(startRange, static_cast<unsigned int>(outputUniforms.size()));
    169 }
    170 
    171 template <typename BlockT>
    172 void AppendActiveBlocks(ShaderType shaderType,
    173                        const std::vector<BlockT> &blocksIn,
    174                        std::vector<BlockT> &blocksOut)
    175 {
    176    for (const BlockT &block : blocksIn)
    177    {
    178        if (block.isActive(shaderType))
    179        {
    180            blocksOut.push_back(block);
    181        }
    182    }
    183 }
    184 }  // anonymous namespace
    185 
    186 ProgramExecutable::ProgramExecutable()
    187    : mMaxActiveAttribLocation(0),
    188      mAttributesTypeMask(0),
    189      mAttributesMask(0),
    190      mActiveSamplerRefCounts{},
    191      mCanDrawWith(false),
    192      mYUVOutput(false),
    193      mTransformFeedbackBufferMode(GL_INTERLEAVED_ATTRIBS),
    194      mDefaultUniformRange(0, 0),
    195      mSamplerUniformRange(0, 0),
    196      mImageUniformRange(0, 0),
    197      mAtomicCounterUniformRange(0, 0),
    198      mFragmentInoutRange(0, 0),
    199      mHasDiscard(false),
    200      mEnablesPerSampleShading(false),
    201      // [GL_EXT_geometry_shader] Table 20.22
    202      mGeometryShaderInputPrimitiveType(PrimitiveMode::Triangles),
    203      mGeometryShaderOutputPrimitiveType(PrimitiveMode::TriangleStrip),
    204      mGeometryShaderInvocations(1),
    205      mGeometryShaderMaxVertices(0),
    206      mTessControlShaderVertices(0),
    207      mTessGenMode(GL_NONE),
    208      mTessGenSpacing(GL_NONE),
    209      mTessGenVertexOrder(GL_NONE),
    210      mTessGenPointMode(GL_NONE)
    211 {
    212    reset(true);
    213 }
    214 
    215 ProgramExecutable::ProgramExecutable(const ProgramExecutable &other)
    216    : mLinkedShaderStages(other.mLinkedShaderStages),
    217      mActiveAttribLocationsMask(other.mActiveAttribLocationsMask),
    218      mMaxActiveAttribLocation(other.mMaxActiveAttribLocation),
    219      mAttributesTypeMask(other.mAttributesTypeMask),
    220      mAttributesMask(other.mAttributesMask),
    221      mActiveSamplersMask(other.mActiveSamplersMask),
    222      mActiveSamplerRefCounts(other.mActiveSamplerRefCounts),
    223      mActiveSamplerTypes(other.mActiveSamplerTypes),
    224      mActiveSamplerYUV(other.mActiveSamplerYUV),
    225      mActiveSamplerFormats(other.mActiveSamplerFormats),
    226      mActiveSamplerShaderBits(other.mActiveSamplerShaderBits),
    227      mActiveImagesMask(other.mActiveImagesMask),
    228      mActiveImageShaderBits(other.mActiveImageShaderBits),
    229      mCanDrawWith(other.mCanDrawWith),
    230      mOutputVariables(other.mOutputVariables),
    231      mOutputLocations(other.mOutputLocations),
    232      mSecondaryOutputLocations(other.mSecondaryOutputLocations),
    233      mYUVOutput(other.mYUVOutput),
    234      mProgramInputs(other.mProgramInputs),
    235      mLinkedTransformFeedbackVaryings(other.mLinkedTransformFeedbackVaryings),
    236      mTransformFeedbackStrides(other.mTransformFeedbackStrides),
    237      mTransformFeedbackBufferMode(other.mTransformFeedbackBufferMode),
    238      mUniforms(other.mUniforms),
    239      mDefaultUniformRange(other.mDefaultUniformRange),
    240      mSamplerUniformRange(other.mSamplerUniformRange),
    241      mImageUniformRange(other.mImageUniformRange),
    242      mAtomicCounterUniformRange(other.mAtomicCounterUniformRange),
    243      mUniformBlocks(other.mUniformBlocks),
    244      mActiveUniformBlockBindings(other.mActiveUniformBlockBindings),
    245      mAtomicCounterBuffers(other.mAtomicCounterBuffers),
    246      mShaderStorageBlocks(other.mShaderStorageBlocks),
    247      mFragmentInoutRange(other.mFragmentInoutRange),
    248      mHasDiscard(other.mHasDiscard),
    249      mEnablesPerSampleShading(other.mEnablesPerSampleShading),
    250      mAdvancedBlendEquations(other.mAdvancedBlendEquations)
    251 {
    252    reset(true);
    253 }
    254 
    255 ProgramExecutable::~ProgramExecutable() = default;
    256 
    257 void ProgramExecutable::reset(bool clearInfoLog)
    258 {
    259    if (clearInfoLog)
    260    {
    261        resetInfoLog();
    262    }
    263    mActiveAttribLocationsMask.reset();
    264    mAttributesTypeMask.reset();
    265    mAttributesMask.reset();
    266    mMaxActiveAttribLocation = 0;
    267 
    268    mActiveSamplersMask.reset();
    269    mActiveSamplerRefCounts = {};
    270    mActiveSamplerTypes.fill(TextureType::InvalidEnum);
    271    mActiveSamplerYUV.reset();
    272    mActiveSamplerFormats.fill(SamplerFormat::InvalidEnum);
    273 
    274    mActiveImagesMask.reset();
    275 
    276    mProgramInputs.clear();
    277    mLinkedTransformFeedbackVaryings.clear();
    278    mTransformFeedbackStrides.clear();
    279    mUniforms.clear();
    280    mUniformBlocks.clear();
    281    mActiveUniformBlockBindings.reset();
    282    mShaderStorageBlocks.clear();
    283    mAtomicCounterBuffers.clear();
    284    mOutputVariables.clear();
    285    mOutputLocations.clear();
    286    mActiveOutputVariablesMask.reset();
    287    mSecondaryOutputLocations.clear();
    288    mYUVOutput = false;
    289    mSamplerBindings.clear();
    290    mImageBindings.clear();
    291 
    292    mDefaultUniformRange       = RangeUI(0, 0);
    293    mSamplerUniformRange       = RangeUI(0, 0);
    294    mImageUniformRange         = RangeUI(0, 0);
    295    mAtomicCounterUniformRange = RangeUI(0, 0);
    296 
    297    mFragmentInoutRange      = RangeUI(0, 0);
    298    mHasDiscard              = false;
    299    mEnablesPerSampleShading = false;
    300    mAdvancedBlendEquations.reset();
    301 
    302    mGeometryShaderInputPrimitiveType  = PrimitiveMode::Triangles;
    303    mGeometryShaderOutputPrimitiveType = PrimitiveMode::TriangleStrip;
    304    mGeometryShaderInvocations         = 1;
    305    mGeometryShaderMaxVertices         = 0;
    306 
    307    mTessControlShaderVertices = 0;
    308    mTessGenMode               = GL_NONE;
    309    mTessGenSpacing            = GL_NONE;
    310    mTessGenVertexOrder        = GL_NONE;
    311    mTessGenPointMode          = GL_NONE;
    312 
    313    mOutputVariableTypes.clear();
    314    mDrawBufferTypeMask.reset();
    315 }
    316 
    317 void ProgramExecutable::load(bool isSeparable, gl::BinaryInputStream *stream)
    318 {
    319    static_assert(MAX_VERTEX_ATTRIBS * 2 <= sizeof(uint32_t) * 8,
    320                  "Too many vertex attribs for mask: All bits of mAttributesTypeMask types and "
    321                  "mask fit into 32 bits each");
    322    mAttributesTypeMask        = gl::ComponentTypeMask(stream->readInt<uint32_t>());
    323    mAttributesMask            = gl::AttributesMask(stream->readInt<uint32_t>());
    324    mActiveAttribLocationsMask = gl::AttributesMask(stream->readInt<uint32_t>());
    325    mMaxActiveAttribLocation   = stream->readInt<unsigned int>();
    326 
    327    unsigned int fragmentInoutRangeLow  = stream->readInt<uint32_t>();
    328    unsigned int fragmentInoutRangeHigh = stream->readInt<uint32_t>();
    329    mFragmentInoutRange                 = RangeUI(fragmentInoutRangeLow, fragmentInoutRangeHigh);
    330 
    331    mHasDiscard              = stream->readBool();
    332    mEnablesPerSampleShading = stream->readBool();
    333 
    334    static_assert(sizeof(mAdvancedBlendEquations.bits()) == sizeof(uint32_t));
    335    mAdvancedBlendEquations = BlendEquationBitSet(stream->readInt<uint32_t>());
    336 
    337    mLinkedShaderStages = ShaderBitSet(stream->readInt<uint8_t>());
    338 
    339    mGeometryShaderInputPrimitiveType  = stream->readEnum<PrimitiveMode>();
    340    mGeometryShaderOutputPrimitiveType = stream->readEnum<PrimitiveMode>();
    341    mGeometryShaderInvocations         = stream->readInt<int>();
    342    mGeometryShaderMaxVertices         = stream->readInt<int>();
    343 
    344    mTessControlShaderVertices = stream->readInt<int>();
    345    mTessGenMode               = stream->readInt<GLenum>();
    346    mTessGenSpacing            = stream->readInt<GLenum>();
    347    mTessGenVertexOrder        = stream->readInt<GLenum>();
    348    mTessGenPointMode          = stream->readInt<GLenum>();
    349 
    350    size_t attribCount = stream->readInt<size_t>();
    351    ASSERT(getProgramInputs().empty());
    352    for (size_t attribIndex = 0; attribIndex < attribCount; ++attribIndex)
    353    {
    354        sh::ShaderVariable attrib;
    355        LoadShaderVar(stream, &attrib);
    356        attrib.location = stream->readInt<int>();
    357        mProgramInputs.push_back(attrib);
    358    }
    359 
    360    size_t uniformCount = stream->readInt<size_t>();
    361    ASSERT(getUniforms().empty());
    362    for (size_t uniformIndex = 0; uniformIndex < uniformCount; ++uniformIndex)
    363    {
    364        LinkedUniform uniform;
    365        LoadShaderVar(stream, &uniform);
    366 
    367        uniform.bufferIndex = stream->readInt<int>();
    368        LoadBlockMemberInfo(stream, &uniform.blockInfo);
    369 
    370        stream->readIntVector<unsigned int>(&uniform.outerArraySizes);
    371        uniform.outerArrayOffset = stream->readInt<unsigned int>();
    372 
    373        uniform.typeInfo = &GetUniformTypeInfo(uniform.type);
    374 
    375        // Active shader info
    376        for (ShaderType shaderType : gl::AllShaderTypes())
    377        {
    378            uniform.setActive(shaderType, stream->readBool());
    379        }
    380 
    381        mUniforms.push_back(uniform);
    382    }
    383 
    384    size_t uniformBlockCount = stream->readInt<size_t>();
    385    ASSERT(getUniformBlocks().empty());
    386    for (size_t uniformBlockIndex = 0; uniformBlockIndex < uniformBlockCount; ++uniformBlockIndex)
    387    {
    388        InterfaceBlock uniformBlock;
    389        LoadInterfaceBlock(stream, &uniformBlock);
    390        mUniformBlocks.push_back(uniformBlock);
    391 
    392        mActiveUniformBlockBindings.set(uniformBlockIndex, uniformBlock.binding != 0);
    393    }
    394 
    395    size_t shaderStorageBlockCount = stream->readInt<size_t>();
    396    ASSERT(getShaderStorageBlocks().empty());
    397    for (size_t shaderStorageBlockIndex = 0; shaderStorageBlockIndex < shaderStorageBlockCount;
    398         ++shaderStorageBlockIndex)
    399    {
    400        InterfaceBlock shaderStorageBlock;
    401        LoadInterfaceBlock(stream, &shaderStorageBlock);
    402        mShaderStorageBlocks.push_back(shaderStorageBlock);
    403    }
    404 
    405    size_t atomicCounterBufferCount = stream->readInt<size_t>();
    406    ASSERT(getAtomicCounterBuffers().empty());
    407    for (size_t bufferIndex = 0; bufferIndex < atomicCounterBufferCount; ++bufferIndex)
    408    {
    409        AtomicCounterBuffer atomicCounterBuffer;
    410        LoadShaderVariableBuffer(stream, &atomicCounterBuffer);
    411 
    412        mAtomicCounterBuffers.push_back(atomicCounterBuffer);
    413    }
    414 
    415    size_t transformFeedbackVaryingCount = stream->readInt<size_t>();
    416    ASSERT(mLinkedTransformFeedbackVaryings.empty());
    417    for (size_t transformFeedbackVaryingIndex = 0;
    418         transformFeedbackVaryingIndex < transformFeedbackVaryingCount;
    419         ++transformFeedbackVaryingIndex)
    420    {
    421        sh::ShaderVariable varying;
    422        stream->readIntVector<unsigned int>(&varying.arraySizes);
    423        stream->readInt(&varying.type);
    424        stream->readString(&varying.name);
    425 
    426        GLuint arrayIndex = stream->readInt<GLuint>();
    427 
    428        mLinkedTransformFeedbackVaryings.emplace_back(varying, arrayIndex);
    429    }
    430 
    431    mTransformFeedbackBufferMode = stream->readInt<GLint>();
    432 
    433    size_t outputCount = stream->readInt<size_t>();
    434    ASSERT(getOutputVariables().empty());
    435    for (size_t outputIndex = 0; outputIndex < outputCount; ++outputIndex)
    436    {
    437        sh::ShaderVariable output;
    438        LoadShaderVar(stream, &output);
    439        output.location = stream->readInt<int>();
    440        output.index    = stream->readInt<int>();
    441        mOutputVariables.push_back(output);
    442    }
    443 
    444    size_t outputVarCount = stream->readInt<size_t>();
    445    ASSERT(getOutputLocations().empty());
    446    for (size_t outputIndex = 0; outputIndex < outputVarCount; ++outputIndex)
    447    {
    448        VariableLocation locationData;
    449        stream->readInt(&locationData.arrayIndex);
    450        stream->readInt(&locationData.index);
    451        stream->readBool(&locationData.ignored);
    452        mOutputLocations.push_back(locationData);
    453    }
    454 
    455    mActiveOutputVariablesMask =
    456        gl::DrawBufferMask(stream->readInt<gl::DrawBufferMask::value_type>());
    457 
    458    size_t outputTypeCount = stream->readInt<size_t>();
    459    for (size_t outputIndex = 0; outputIndex < outputTypeCount; ++outputIndex)
    460    {
    461        mOutputVariableTypes.push_back(stream->readInt<GLenum>());
    462    }
    463 
    464    static_assert(IMPLEMENTATION_MAX_DRAW_BUFFERS * 2 <= 8 * sizeof(uint32_t),
    465                  "All bits of mDrawBufferTypeMask and mActiveOutputVariables types and mask fit "
    466                  "into 32 bits each");
    467    mDrawBufferTypeMask = gl::ComponentTypeMask(stream->readInt<uint32_t>());
    468 
    469    stream->readBool(&mYUVOutput);
    470 
    471    size_t secondaryOutputVarCount = stream->readInt<size_t>();
    472    ASSERT(getSecondaryOutputLocations().empty());
    473    for (size_t outputIndex = 0; outputIndex < secondaryOutputVarCount; ++outputIndex)
    474    {
    475        VariableLocation locationData;
    476        stream->readInt(&locationData.arrayIndex);
    477        stream->readInt(&locationData.index);
    478        stream->readBool(&locationData.ignored);
    479        mSecondaryOutputLocations.push_back(locationData);
    480    }
    481 
    482    unsigned int defaultUniformRangeLow  = stream->readInt<unsigned int>();
    483    unsigned int defaultUniformRangeHigh = stream->readInt<unsigned int>();
    484    mDefaultUniformRange                 = RangeUI(defaultUniformRangeLow, defaultUniformRangeHigh);
    485 
    486    unsigned int samplerRangeLow  = stream->readInt<unsigned int>();
    487    unsigned int samplerRangeHigh = stream->readInt<unsigned int>();
    488    mSamplerUniformRange          = RangeUI(samplerRangeLow, samplerRangeHigh);
    489 
    490    size_t samplerCount = stream->readInt<size_t>();
    491    for (size_t samplerIndex = 0; samplerIndex < samplerCount; ++samplerIndex)
    492    {
    493        TextureType textureType = stream->readEnum<TextureType>();
    494        GLenum samplerType      = stream->readInt<GLenum>();
    495        SamplerFormat format    = stream->readEnum<SamplerFormat>();
    496        size_t bindingCount     = stream->readInt<size_t>();
    497        mSamplerBindings.emplace_back(textureType, samplerType, format, bindingCount);
    498    }
    499 
    500    unsigned int imageRangeLow  = stream->readInt<unsigned int>();
    501    unsigned int imageRangeHigh = stream->readInt<unsigned int>();
    502    mImageUniformRange          = RangeUI(imageRangeLow, imageRangeHigh);
    503 
    504    size_t imageBindingCount = stream->readInt<size_t>();
    505    for (size_t imageIndex = 0; imageIndex < imageBindingCount; ++imageIndex)
    506    {
    507        size_t elementCount     = stream->readInt<size_t>();
    508        TextureType textureType = static_cast<TextureType>(stream->readInt<unsigned int>());
    509        ImageBinding imageBinding(elementCount, textureType);
    510        for (size_t elementIndex = 0; elementIndex < elementCount; ++elementIndex)
    511        {
    512            imageBinding.boundImageUnits[elementIndex] = stream->readInt<unsigned int>();
    513        }
    514        mImageBindings.emplace_back(imageBinding);
    515    }
    516 
    517    unsigned int atomicCounterRangeLow  = stream->readInt<unsigned int>();
    518    unsigned int atomicCounterRangeHigh = stream->readInt<unsigned int>();
    519    mAtomicCounterUniformRange          = RangeUI(atomicCounterRangeLow, atomicCounterRangeHigh);
    520 
    521    // These values are currently only used by PPOs, so only load them when the program is marked
    522    // separable to save memory.
    523    if (isSeparable)
    524    {
    525        for (ShaderType shaderType : mLinkedShaderStages)
    526        {
    527            mLinkedOutputVaryings[shaderType].resize(stream->readInt<size_t>());
    528            for (sh::ShaderVariable &variable : mLinkedOutputVaryings[shaderType])
    529            {
    530                LoadShaderVar(stream, &variable);
    531            }
    532            mLinkedInputVaryings[shaderType].resize(stream->readInt<size_t>());
    533            for (sh::ShaderVariable &variable : mLinkedInputVaryings[shaderType])
    534            {
    535                LoadShaderVar(stream, &variable);
    536            }
    537            mLinkedUniforms[shaderType].resize(stream->readInt<size_t>());
    538            for (sh::ShaderVariable &variable : mLinkedUniforms[shaderType])
    539            {
    540                LoadShaderVar(stream, &variable);
    541            }
    542            mLinkedUniformBlocks[shaderType].resize(stream->readInt<size_t>());
    543            for (sh::InterfaceBlock &shaderStorageBlock : mLinkedUniformBlocks[shaderType])
    544            {
    545                LoadShInterfaceBlock(stream, &shaderStorageBlock);
    546            }
    547            mLinkedShaderVersions[shaderType] = stream->readInt<int>();
    548        }
    549    }
    550 }
    551 
    552 void ProgramExecutable::save(bool isSeparable, gl::BinaryOutputStream *stream) const
    553 {
    554    static_assert(MAX_VERTEX_ATTRIBS * 2 <= sizeof(uint32_t) * 8,
    555                  "All bits of mAttributesTypeMask types and mask fit into 32 bits each");
    556    stream->writeInt(static_cast<uint32_t>(mAttributesTypeMask.to_ulong()));
    557    stream->writeInt(static_cast<uint32_t>(mAttributesMask.to_ulong()));
    558    stream->writeInt(static_cast<uint32_t>(mActiveAttribLocationsMask.to_ulong()));
    559    stream->writeInt(mMaxActiveAttribLocation);
    560 
    561    stream->writeInt(mFragmentInoutRange.low());
    562    stream->writeInt(mFragmentInoutRange.high());
    563 
    564    stream->writeBool(mHasDiscard);
    565    stream->writeBool(mEnablesPerSampleShading);
    566    stream->writeInt(mAdvancedBlendEquations.bits());
    567 
    568    stream->writeInt(mLinkedShaderStages.bits());
    569 
    570    ASSERT(mGeometryShaderInvocations >= 1 && mGeometryShaderMaxVertices >= 0);
    571    stream->writeEnum(mGeometryShaderInputPrimitiveType);
    572    stream->writeEnum(mGeometryShaderOutputPrimitiveType);
    573    stream->writeInt(mGeometryShaderInvocations);
    574    stream->writeInt(mGeometryShaderMaxVertices);
    575 
    576    stream->writeInt(mTessControlShaderVertices);
    577    stream->writeInt(mTessGenMode);
    578    stream->writeInt(mTessGenSpacing);
    579    stream->writeInt(mTessGenVertexOrder);
    580    stream->writeInt(mTessGenPointMode);
    581 
    582    stream->writeInt(getProgramInputs().size());
    583    for (const sh::ShaderVariable &attrib : getProgramInputs())
    584    {
    585        WriteShaderVar(stream, attrib);
    586        stream->writeInt(attrib.location);
    587    }
    588 
    589    stream->writeInt(getUniforms().size());
    590    for (const LinkedUniform &uniform : getUniforms())
    591    {
    592        WriteShaderVar(stream, uniform);
    593 
    594        stream->writeInt(uniform.bufferIndex);
    595        WriteBlockMemberInfo(stream, uniform.blockInfo);
    596 
    597        stream->writeIntVector(uniform.outerArraySizes);
    598        stream->writeInt(uniform.outerArrayOffset);
    599 
    600        // Active shader info
    601        for (ShaderType shaderType : gl::AllShaderTypes())
    602        {
    603            stream->writeBool(uniform.isActive(shaderType));
    604        }
    605    }
    606 
    607    stream->writeInt(getUniformBlocks().size());
    608    for (const InterfaceBlock &uniformBlock : getUniformBlocks())
    609    {
    610        WriteInterfaceBlock(stream, uniformBlock);
    611    }
    612 
    613    stream->writeInt(getShaderStorageBlocks().size());
    614    for (const InterfaceBlock &shaderStorageBlock : getShaderStorageBlocks())
    615    {
    616        WriteInterfaceBlock(stream, shaderStorageBlock);
    617    }
    618 
    619    stream->writeInt(mAtomicCounterBuffers.size());
    620    for (const AtomicCounterBuffer &atomicCounterBuffer : getAtomicCounterBuffers())
    621    {
    622        WriteShaderVariableBuffer(stream, atomicCounterBuffer);
    623    }
    624 
    625    stream->writeInt(getLinkedTransformFeedbackVaryings().size());
    626    for (const auto &var : getLinkedTransformFeedbackVaryings())
    627    {
    628        stream->writeIntVector(var.arraySizes);
    629        stream->writeInt(var.type);
    630        stream->writeString(var.name);
    631 
    632        stream->writeIntOrNegOne(var.arrayIndex);
    633    }
    634 
    635    stream->writeInt(getTransformFeedbackBufferMode());
    636 
    637    stream->writeInt(getOutputVariables().size());
    638    for (const sh::ShaderVariable &output : getOutputVariables())
    639    {
    640        WriteShaderVar(stream, output);
    641        stream->writeInt(output.location);
    642        stream->writeInt(output.index);
    643    }
    644 
    645    stream->writeInt(getOutputLocations().size());
    646    for (const auto &outputVar : getOutputLocations())
    647    {
    648        stream->writeInt(outputVar.arrayIndex);
    649        stream->writeIntOrNegOne(outputVar.index);
    650        stream->writeBool(outputVar.ignored);
    651    }
    652 
    653    stream->writeInt(static_cast<int>(mActiveOutputVariablesMask.to_ulong()));
    654 
    655    stream->writeInt(mOutputVariableTypes.size());
    656    for (const auto &outputVariableType : mOutputVariableTypes)
    657    {
    658        stream->writeInt(outputVariableType);
    659    }
    660 
    661    static_assert(
    662        IMPLEMENTATION_MAX_DRAW_BUFFERS * 2 <= 8 * sizeof(uint32_t),
    663        "All bits of mDrawBufferTypeMask and mActiveOutputVariables can be contained in 32 bits");
    664    stream->writeInt(static_cast<int>(mDrawBufferTypeMask.to_ulong()));
    665 
    666    stream->writeBool(mYUVOutput);
    667 
    668    stream->writeInt(getSecondaryOutputLocations().size());
    669    for (const auto &outputVar : getSecondaryOutputLocations())
    670    {
    671        stream->writeInt(outputVar.arrayIndex);
    672        stream->writeIntOrNegOne(outputVar.index);
    673        stream->writeBool(outputVar.ignored);
    674    }
    675 
    676    stream->writeInt(getDefaultUniformRange().low());
    677    stream->writeInt(getDefaultUniformRange().high());
    678 
    679    stream->writeInt(getSamplerUniformRange().low());
    680    stream->writeInt(getSamplerUniformRange().high());
    681 
    682    stream->writeInt(getSamplerBindings().size());
    683    for (const auto &samplerBinding : getSamplerBindings())
    684    {
    685        stream->writeEnum(samplerBinding.textureType);
    686        stream->writeInt(samplerBinding.samplerType);
    687        stream->writeEnum(samplerBinding.format);
    688        stream->writeInt(samplerBinding.boundTextureUnits.size());
    689    }
    690 
    691    stream->writeInt(getImageUniformRange().low());
    692    stream->writeInt(getImageUniformRange().high());
    693 
    694    stream->writeInt(getImageBindings().size());
    695    for (const auto &imageBinding : getImageBindings())
    696    {
    697        stream->writeInt(imageBinding.boundImageUnits.size());
    698        stream->writeInt(static_cast<unsigned int>(imageBinding.textureType));
    699        for (size_t i = 0; i < imageBinding.boundImageUnits.size(); ++i)
    700        {
    701            stream->writeInt(imageBinding.boundImageUnits[i]);
    702        }
    703    }
    704 
    705    stream->writeInt(getAtomicCounterUniformRange().low());
    706    stream->writeInt(getAtomicCounterUniformRange().high());
    707 
    708    // These values are currently only used by PPOs, so only save them when the program is marked
    709    // separable to save memory.
    710    if (isSeparable)
    711    {
    712        for (ShaderType shaderType : mLinkedShaderStages)
    713        {
    714            stream->writeInt(mLinkedOutputVaryings[shaderType].size());
    715            for (const sh::ShaderVariable &shaderVariable : mLinkedOutputVaryings[shaderType])
    716            {
    717                WriteShaderVar(stream, shaderVariable);
    718            }
    719            stream->writeInt(mLinkedInputVaryings[shaderType].size());
    720            for (const sh::ShaderVariable &shaderVariable : mLinkedInputVaryings[shaderType])
    721            {
    722                WriteShaderVar(stream, shaderVariable);
    723            }
    724            stream->writeInt(mLinkedUniforms[shaderType].size());
    725            for (const sh::ShaderVariable &shaderVariable : mLinkedUniforms[shaderType])
    726            {
    727                WriteShaderVar(stream, shaderVariable);
    728            }
    729            stream->writeInt(mLinkedUniformBlocks[shaderType].size());
    730            for (const sh::InterfaceBlock &shaderStorageBlock : mLinkedUniformBlocks[shaderType])
    731            {
    732                WriteShInterfaceBlock(stream, shaderStorageBlock);
    733            }
    734            stream->writeInt(mLinkedShaderVersions[shaderType]);
    735        }
    736    }
    737 }
    738 
    739 int ProgramExecutable::getInfoLogLength() const
    740 {
    741    return static_cast<int>(mInfoLog.getLength());
    742 }
    743 
    744 void ProgramExecutable::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const
    745 {
    746    return mInfoLog.getLog(bufSize, length, infoLog);
    747 }
    748 
    749 std::string ProgramExecutable::getInfoLogString() const
    750 {
    751    return mInfoLog.str();
    752 }
    753 
    754 bool ProgramExecutable::isAttribLocationActive(size_t attribLocation) const
    755 {
    756    ASSERT(attribLocation < mActiveAttribLocationsMask.size());
    757    return mActiveAttribLocationsMask[attribLocation];
    758 }
    759 
    760 AttributesMask ProgramExecutable::getAttributesMask() const
    761 {
    762    return mAttributesMask;
    763 }
    764 
    765 bool ProgramExecutable::hasDefaultUniforms() const
    766 {
    767    return !getDefaultUniformRange().empty();
    768 }
    769 
    770 bool ProgramExecutable::hasTextures() const
    771 {
    772    return !getSamplerBindings().empty();
    773 }
    774 
    775 bool ProgramExecutable::hasUniformBuffers() const
    776 {
    777    return !mUniformBlocks.empty();
    778 }
    779 
    780 bool ProgramExecutable::hasStorageBuffers() const
    781 {
    782    return !mShaderStorageBlocks.empty();
    783 }
    784 
    785 bool ProgramExecutable::hasAtomicCounterBuffers() const
    786 {
    787    return !mAtomicCounterBuffers.empty();
    788 }
    789 
    790 bool ProgramExecutable::hasImages() const
    791 {
    792    return !mImageBindings.empty();
    793 }
    794 
    795 bool ProgramExecutable::usesFramebufferFetch() const
    796 {
    797    return (mFragmentInoutRange.length() > 0);
    798 }
    799 
    800 GLuint ProgramExecutable::getUniformIndexFromImageIndex(GLuint imageIndex) const
    801 {
    802    ASSERT(imageIndex < mImageUniformRange.length());
    803    return imageIndex + mImageUniformRange.low();
    804 }
    805 
    806 GLuint ProgramExecutable::getUniformIndexFromSamplerIndex(GLuint samplerIndex) const
    807 {
    808    ASSERT(samplerIndex < mSamplerUniformRange.length());
    809    return samplerIndex + mSamplerUniformRange.low();
    810 }
    811 
    812 void ProgramExecutable::setActive(size_t textureUnit,
    813                                  const SamplerBinding &samplerBinding,
    814                                  const gl::LinkedUniform &samplerUniform)
    815 {
    816    mActiveSamplersMask.set(textureUnit);
    817    mActiveSamplerTypes[textureUnit]      = samplerBinding.textureType;
    818    mActiveSamplerYUV[textureUnit]        = IsSamplerYUVType(samplerBinding.samplerType);
    819    mActiveSamplerFormats[textureUnit]    = samplerBinding.format;
    820    mActiveSamplerShaderBits[textureUnit] = samplerUniform.activeShaders();
    821 }
    822 
    823 void ProgramExecutable::setInactive(size_t textureUnit)
    824 {
    825    mActiveSamplersMask.reset(textureUnit);
    826    mActiveSamplerTypes[textureUnit] = TextureType::InvalidEnum;
    827    mActiveSamplerYUV.reset(textureUnit);
    828    mActiveSamplerFormats[textureUnit] = SamplerFormat::InvalidEnum;
    829    mActiveSamplerShaderBits[textureUnit].reset();
    830 }
    831 
    832 void ProgramExecutable::hasSamplerTypeConflict(size_t textureUnit)
    833 {
    834    // Conflicts are marked with InvalidEnum
    835    mActiveSamplerYUV.reset(textureUnit);
    836    mActiveSamplerTypes[textureUnit] = TextureType::InvalidEnum;
    837 }
    838 
    839 void ProgramExecutable::hasSamplerFormatConflict(size_t textureUnit)
    840 {
    841    // Conflicts are marked with InvalidEnum
    842    mActiveSamplerFormats[textureUnit] = SamplerFormat::InvalidEnum;
    843 }
    844 
    845 void ProgramExecutable::updateActiveSamplers(const ProgramState &programState)
    846 {
    847    const std::vector<SamplerBinding> &samplerBindings = programState.getSamplerBindings();
    848 
    849    for (uint32_t samplerIndex = 0; samplerIndex < samplerBindings.size(); ++samplerIndex)
    850    {
    851        const SamplerBinding &samplerBinding = samplerBindings[samplerIndex];
    852 
    853        for (GLint textureUnit : samplerBinding.boundTextureUnits)
    854        {
    855            if (++mActiveSamplerRefCounts[textureUnit] == 1)
    856            {
    857                uint32_t uniformIndex = programState.getUniformIndexFromSamplerIndex(samplerIndex);
    858                setActive(textureUnit, samplerBinding, programState.getUniforms()[uniformIndex]);
    859            }
    860            else
    861            {
    862                if (mActiveSamplerTypes[textureUnit] != samplerBinding.textureType ||
    863                    mActiveSamplerYUV.test(textureUnit) !=
    864                        IsSamplerYUVType(samplerBinding.samplerType))
    865                {
    866                    hasSamplerTypeConflict(textureUnit);
    867                }
    868 
    869                if (mActiveSamplerFormats[textureUnit] != samplerBinding.format)
    870                {
    871                    hasSamplerFormatConflict(textureUnit);
    872                }
    873            }
    874            mActiveSamplersMask.set(textureUnit);
    875        }
    876    }
    877 
    878    // Invalidate the validation cache.
    879    resetCachedValidateSamplersResult();
    880 }
    881 
    882 void ProgramExecutable::updateActiveImages(const ProgramExecutable &executable)
    883 {
    884    const std::vector<ImageBinding> &imageBindings = executable.getImageBindings();
    885    for (uint32_t imageIndex = 0; imageIndex < imageBindings.size(); ++imageIndex)
    886    {
    887        const gl::ImageBinding &imageBinding = imageBindings.at(imageIndex);
    888 
    889        uint32_t uniformIndex = executable.getUniformIndexFromImageIndex(imageIndex);
    890        const gl::LinkedUniform &imageUniform = executable.getUniforms()[uniformIndex];
    891        const ShaderBitSet shaderBits         = imageUniform.activeShaders();
    892        for (GLint imageUnit : imageBinding.boundImageUnits)
    893        {
    894            mActiveImagesMask.set(imageUnit);
    895            mActiveImageShaderBits[imageUnit] |= shaderBits;
    896        }
    897    }
    898 }
    899 
    900 void ProgramExecutable::setSamplerUniformTextureTypeAndFormat(
    901    size_t textureUnitIndex,
    902    std::vector<SamplerBinding> &samplerBindings)
    903 {
    904    bool foundBinding         = false;
    905    TextureType foundType     = TextureType::InvalidEnum;
    906    bool foundYUV             = false;
    907    SamplerFormat foundFormat = SamplerFormat::InvalidEnum;
    908 
    909    for (uint32_t samplerIndex = 0; samplerIndex < samplerBindings.size(); ++samplerIndex)
    910    {
    911        const SamplerBinding &binding = samplerBindings[samplerIndex];
    912 
    913        // A conflict exists if samplers of different types are sourced by the same texture unit.
    914        // We need to check all bound textures to detect this error case.
    915        for (GLuint textureUnit : binding.boundTextureUnits)
    916        {
    917            if (textureUnit != textureUnitIndex)
    918            {
    919                continue;
    920            }
    921 
    922            if (!foundBinding)
    923            {
    924                foundBinding          = true;
    925                foundType             = binding.textureType;
    926                foundYUV              = IsSamplerYUVType(binding.samplerType);
    927                foundFormat           = binding.format;
    928                uint32_t uniformIndex = getUniformIndexFromSamplerIndex(samplerIndex);
    929                setActive(textureUnit, binding, mUniforms[uniformIndex]);
    930            }
    931            else
    932            {
    933                if (foundType != binding.textureType ||
    934                    foundYUV != IsSamplerYUVType(binding.samplerType))
    935                {
    936                    hasSamplerTypeConflict(textureUnit);
    937                }
    938 
    939                if (foundFormat != binding.format)
    940                {
    941                    hasSamplerFormatConflict(textureUnit);
    942                }
    943            }
    944        }
    945    }
    946 }
    947 
    948 void ProgramExecutable::updateCanDrawWith()
    949 {
    950    mCanDrawWith = hasLinkedShaderStage(ShaderType::Vertex);
    951 }
    952 
    953 void ProgramExecutable::saveLinkedStateInfo(const Context *context, const ProgramState &state)
    954 {
    955    for (ShaderType shaderType : getLinkedShaderStages())
    956    {
    957        Shader *shader = state.getAttachedShader(shaderType);
    958        ASSERT(shader);
    959        mLinkedOutputVaryings[shaderType] = shader->getOutputVaryings(context);
    960        mLinkedInputVaryings[shaderType]  = shader->getInputVaryings(context);
    961        mLinkedShaderVersions[shaderType] = shader->getShaderVersion(context);
    962        mLinkedUniforms[shaderType]       = shader->getUniforms(context);
    963        mLinkedUniformBlocks[shaderType]  = shader->getUniformBlocks(context);
    964    }
    965 }
    966 
    967 bool ProgramExecutable::isYUVOutput() const
    968 {
    969    return mYUVOutput;
    970 }
    971 
    972 ShaderType ProgramExecutable::getLinkedTransformFeedbackStage() const
    973 {
    974    return GetLastPreFragmentStage(mLinkedShaderStages);
    975 }
    976 
    977 bool ProgramExecutable::linkMergedVaryings(
    978    const Context *context,
    979    const ProgramMergedVaryings &mergedVaryings,
    980    const std::vector<std::string> &transformFeedbackVaryingNames,
    981    const LinkingVariables &linkingVariables,
    982    bool isSeparable,
    983    ProgramVaryingPacking *varyingPacking)
    984 {
    985    ShaderType tfStage = GetLastPreFragmentStage(linkingVariables.isShaderStageUsedBitset);
    986 
    987    if (!linkValidateTransformFeedback(context, mergedVaryings, tfStage,
    988                                       transformFeedbackVaryingNames))
    989    {
    990        return false;
    991    }
    992 
    993    // Map the varyings to the register file
    994    // In WebGL, we use a slightly different handling for packing variables.
    995    gl::PackMode packMode = PackMode::ANGLE_RELAXED;
    996    if (context->getLimitations().noFlexibleVaryingPacking)
    997    {
    998        // D3D9 pack mode is strictly more strict than WebGL, so takes priority.
    999        packMode = PackMode::ANGLE_NON_CONFORMANT_D3D9;
   1000    }
   1001    else if (context->isWebGL())
   1002    {
   1003        packMode = PackMode::WEBGL_STRICT;
   1004    }
   1005 
   1006    // Build active shader stage map.
   1007    ShaderBitSet activeShadersMask;
   1008    for (ShaderType shaderType : kAllGraphicsShaderTypes)
   1009    {
   1010        // - Check for attached shaders to handle the case of a Program linking the currently
   1011        // attached shaders.
   1012        // - Check for linked shaders to handle the case of a PPO linking separable programs before
   1013        // drawing.
   1014        if (linkingVariables.isShaderStageUsedBitset[shaderType] ||
   1015            getLinkedShaderStages().test(shaderType))
   1016        {
   1017            activeShadersMask[shaderType] = true;
   1018        }
   1019    }
   1020 
   1021    if (!varyingPacking->collectAndPackUserVaryings(mInfoLog, context->getCaps(), packMode,
   1022                                                    activeShadersMask, mergedVaryings,
   1023                                                    transformFeedbackVaryingNames, isSeparable))
   1024    {
   1025        return false;
   1026    }
   1027 
   1028    gatherTransformFeedbackVaryings(mergedVaryings, tfStage, transformFeedbackVaryingNames);
   1029    updateTransformFeedbackStrides();
   1030 
   1031    return true;
   1032 }
   1033 
   1034 bool ProgramExecutable::linkValidateTransformFeedback(
   1035    const Context *context,
   1036    const ProgramMergedVaryings &varyings,
   1037    ShaderType stage,
   1038    const std::vector<std::string> &transformFeedbackVaryingNames)
   1039 {
   1040    const Version &version = context->getClientVersion();
   1041 
   1042    // Validate the tf names regardless of the actual program varyings.
   1043    std::set<std::string> uniqueNames;
   1044    for (const std::string &tfVaryingName : transformFeedbackVaryingNames)
   1045    {
   1046        if (version < Version(3, 1) && tfVaryingName.find('[') != std::string::npos)
   1047        {
   1048            mInfoLog << "Capture of array elements is undefined and not supported.";
   1049            return false;
   1050        }
   1051        if (version >= Version(3, 1))
   1052        {
   1053            if (IncludeSameArrayElement(uniqueNames, tfVaryingName))
   1054            {
   1055                mInfoLog << "Two transform feedback varyings include the same array element ("
   1056                         << tfVaryingName << ").";
   1057                return false;
   1058            }
   1059        }
   1060        else
   1061        {
   1062            if (uniqueNames.count(tfVaryingName) > 0)
   1063            {
   1064                mInfoLog << "Two transform feedback varyings specify the same output variable ("
   1065                         << tfVaryingName << ").";
   1066                return false;
   1067            }
   1068        }
   1069        uniqueNames.insert(tfVaryingName);
   1070    }
   1071 
   1072    // From OpneGLES spec. 11.1.2.1: A program will fail to link if:
   1073    // the count specified by TransformFeedbackVaryings is non-zero, but the
   1074    // program object has no vertex, tessellation evaluation, or geometry shader
   1075    if (transformFeedbackVaryingNames.size() > 0 &&
   1076        !gl::ShaderTypeSupportsTransformFeedback(getLinkedTransformFeedbackStage()))
   1077    {
   1078        mInfoLog << "Linked transform feedback stage " << getLinkedTransformFeedbackStage()
   1079                 << " does not support transform feedback varying.";
   1080        return false;
   1081    }
   1082 
   1083    // Validate against program varyings.
   1084    size_t totalComponents = 0;
   1085    for (const std::string &tfVaryingName : transformFeedbackVaryingNames)
   1086    {
   1087        std::vector<unsigned int> subscripts;
   1088        std::string baseName = ParseResourceName(tfVaryingName, &subscripts);
   1089 
   1090        const sh::ShaderVariable *var = FindOutputVaryingOrField(varyings, stage, baseName);
   1091        if (var == nullptr)
   1092        {
   1093            mInfoLog << "Transform feedback varying " << tfVaryingName
   1094                     << " does not exist in the vertex shader.";
   1095            return false;
   1096        }
   1097 
   1098        // Validate the matching variable.
   1099        if (var->isStruct())
   1100        {
   1101            mInfoLog << "Struct cannot be captured directly (" << baseName << ").";
   1102            return false;
   1103        }
   1104 
   1105        size_t elementCount   = 0;
   1106        size_t componentCount = 0;
   1107 
   1108        if (var->isArray())
   1109        {
   1110            if (version < Version(3, 1))
   1111            {
   1112                mInfoLog << "Capture of arrays is undefined and not supported.";
   1113                return false;
   1114            }
   1115 
   1116            // GLSL ES 3.10 section 4.3.6: A vertex output can't be an array of arrays.
   1117            ASSERT(!var->isArrayOfArrays());
   1118 
   1119            if (!subscripts.empty() && subscripts[0] >= var->getOutermostArraySize())
   1120            {
   1121                mInfoLog << "Cannot capture outbound array element '" << tfVaryingName << "'.";
   1122                return false;
   1123            }
   1124            elementCount = (subscripts.empty() ? var->getOutermostArraySize() : 1);
   1125        }
   1126        else
   1127        {
   1128            if (!subscripts.empty())
   1129            {
   1130                mInfoLog << "Varying '" << baseName
   1131                         << "' is not an array to be captured by element.";
   1132                return false;
   1133            }
   1134            elementCount = 1;
   1135        }
   1136 
   1137        const Caps &caps = context->getCaps();
   1138 
   1139        // TODO(jmadill): Investigate implementation limits on D3D11
   1140        componentCount = VariableComponentCount(var->type) * elementCount;
   1141        if (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS &&
   1142            componentCount > static_cast<GLuint>(caps.maxTransformFeedbackSeparateComponents))
   1143        {
   1144            mInfoLog << "Transform feedback varying " << tfVaryingName << " components ("
   1145                     << componentCount << ") exceed the maximum separate components ("
   1146                     << caps.maxTransformFeedbackSeparateComponents << ").";
   1147            return false;
   1148        }
   1149 
   1150        totalComponents += componentCount;
   1151        if (mTransformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS &&
   1152            totalComponents > static_cast<GLuint>(caps.maxTransformFeedbackInterleavedComponents))
   1153        {
   1154            mInfoLog << "Transform feedback varying total components (" << totalComponents
   1155                     << ") exceed the maximum interleaved components ("
   1156                     << caps.maxTransformFeedbackInterleavedComponents << ").";
   1157            return false;
   1158        }
   1159    }
   1160    return true;
   1161 }
   1162 
   1163 void ProgramExecutable::gatherTransformFeedbackVaryings(
   1164    const ProgramMergedVaryings &varyings,
   1165    ShaderType stage,
   1166    const std::vector<std::string> &transformFeedbackVaryingNames)
   1167 {
   1168    // Gather the linked varyings that are used for transform feedback, they should all exist.
   1169    mLinkedTransformFeedbackVaryings.clear();
   1170    for (const std::string &tfVaryingName : transformFeedbackVaryingNames)
   1171    {
   1172        std::vector<unsigned int> subscripts;
   1173        std::string baseName = ParseResourceName(tfVaryingName, &subscripts);
   1174        size_t subscript     = GL_INVALID_INDEX;
   1175        if (!subscripts.empty())
   1176        {
   1177            subscript = subscripts.back();
   1178        }
   1179        for (const ProgramVaryingRef &ref : varyings)
   1180        {
   1181            if (ref.frontShaderStage != stage)
   1182            {
   1183                continue;
   1184            }
   1185 
   1186            const sh::ShaderVariable *varying = ref.get(stage);
   1187            if (baseName == varying->name)
   1188            {
   1189                mLinkedTransformFeedbackVaryings.emplace_back(*varying,
   1190                                                              static_cast<GLuint>(subscript));
   1191                break;
   1192            }
   1193            else if (varying->isStruct())
   1194            {
   1195                GLuint fieldIndex = 0;
   1196                const auto *field = varying->findField(tfVaryingName, &fieldIndex);
   1197                if (field != nullptr)
   1198                {
   1199                    mLinkedTransformFeedbackVaryings.emplace_back(*field, *varying);
   1200                    break;
   1201                }
   1202            }
   1203        }
   1204    }
   1205 }
   1206 
   1207 void ProgramExecutable::updateTransformFeedbackStrides()
   1208 {
   1209    if (mLinkedTransformFeedbackVaryings.empty())
   1210    {
   1211        return;
   1212    }
   1213 
   1214    if (mTransformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS)
   1215    {
   1216        mTransformFeedbackStrides.resize(1);
   1217        size_t totalSize = 0;
   1218        for (const TransformFeedbackVarying &varying : mLinkedTransformFeedbackVaryings)
   1219        {
   1220            totalSize += varying.size() * VariableExternalSize(varying.type);
   1221        }
   1222        mTransformFeedbackStrides[0] = static_cast<GLsizei>(totalSize);
   1223    }
   1224    else
   1225    {
   1226        mTransformFeedbackStrides.resize(mLinkedTransformFeedbackVaryings.size());
   1227        for (size_t i = 0; i < mLinkedTransformFeedbackVaryings.size(); i++)
   1228        {
   1229            TransformFeedbackVarying &varying = mLinkedTransformFeedbackVaryings[i];
   1230            mTransformFeedbackStrides[i] =
   1231                static_cast<GLsizei>(varying.size() * VariableExternalSize(varying.type));
   1232        }
   1233    }
   1234 }
   1235 
   1236 bool ProgramExecutable::validateSamplersImpl(InfoLog *infoLog, const Caps &caps) const
   1237 {
   1238    // if any two active samplers in a program are of different types, but refer to the same
   1239    // texture image unit, and this is the current program, then ValidateProgram will fail, and
   1240    // DrawArrays and DrawElements will issue the INVALID_OPERATION error.
   1241    for (size_t textureUnit : mActiveSamplersMask)
   1242    {
   1243        if (mActiveSamplerTypes[textureUnit] == TextureType::InvalidEnum)
   1244        {
   1245            if (infoLog)
   1246            {
   1247                (*infoLog) << "Samplers of conflicting types refer to the same texture "
   1248                              "image unit ("
   1249                           << textureUnit << ").";
   1250            }
   1251 
   1252            mCachedValidateSamplersResult = false;
   1253            return false;
   1254        }
   1255 
   1256        if (mActiveSamplerFormats[textureUnit] == SamplerFormat::InvalidEnum)
   1257        {
   1258            if (infoLog)
   1259            {
   1260                (*infoLog) << "Samplers of conflicting formats refer to the same texture "
   1261                              "image unit ("
   1262                           << textureUnit << ").";
   1263            }
   1264 
   1265            mCachedValidateSamplersResult = false;
   1266            return false;
   1267        }
   1268    }
   1269 
   1270    mCachedValidateSamplersResult = true;
   1271    return true;
   1272 }
   1273 
   1274 bool ProgramExecutable::linkValidateOutputVariables(
   1275    const Caps &caps,
   1276    const Extensions &extensions,
   1277    const Version &version,
   1278    GLuint combinedImageUniformsCount,
   1279    GLuint combinedShaderStorageBlocksCount,
   1280    const std::vector<sh::ShaderVariable> &outputVariables,
   1281    int fragmentShaderVersion,
   1282    const ProgramAliasedBindings &fragmentOutputLocations,
   1283    const ProgramAliasedBindings &fragmentOutputIndices)
   1284 {
   1285    ASSERT(mOutputVariableTypes.empty());
   1286    ASSERT(mActiveOutputVariablesMask.none());
   1287    ASSERT(mDrawBufferTypeMask.none());
   1288    ASSERT(!mYUVOutput);
   1289 
   1290    // Gather output variable types
   1291    for (const sh::ShaderVariable &outputVariable : outputVariables)
   1292    {
   1293        if (outputVariable.isBuiltIn() && outputVariable.name != "gl_FragColor" &&
   1294            outputVariable.name != "gl_FragData")
   1295        {
   1296            continue;
   1297        }
   1298 
   1299        unsigned int baseLocation =
   1300            (outputVariable.location == -1 ? 0u
   1301                                           : static_cast<unsigned int>(outputVariable.location));
   1302 
   1303        // GLSL ES 3.10 section 4.3.6: Output variables cannot be arrays of arrays or arrays of
   1304        // structures, so we may use getBasicTypeElementCount().
   1305        unsigned int elementCount = outputVariable.getBasicTypeElementCount();
   1306        for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
   1307        {
   1308            const unsigned int location = baseLocation + elementIndex;
   1309            if (location >= mOutputVariableTypes.size())
   1310            {
   1311                mOutputVariableTypes.resize(location + 1, GL_NONE);
   1312            }
   1313            ASSERT(location < mActiveOutputVariablesMask.size());
   1314            mActiveOutputVariablesMask.set(location);
   1315            mOutputVariableTypes[location] = VariableComponentType(outputVariable.type);
   1316            ComponentType componentType    = GLenumToComponentType(mOutputVariableTypes[location]);
   1317            SetComponentTypeMask(componentType, location, &mDrawBufferTypeMask);
   1318        }
   1319 
   1320        if (outputVariable.yuv)
   1321        {
   1322            ASSERT(outputVariables.size() == 1);
   1323            mYUVOutput = true;
   1324        }
   1325    }
   1326 
   1327    if (version >= ES_3_1)
   1328    {
   1329        // [OpenGL ES 3.1] Chapter 8.22 Page 203:
   1330        // A link error will be generated if the sum of the number of active image uniforms used in
   1331        // all shaders, the number of active shader storage blocks, and the number of active
   1332        // fragment shader outputs exceeds the implementation-dependent value of
   1333        // MAX_COMBINED_SHADER_OUTPUT_RESOURCES.
   1334        if (combinedImageUniformsCount + combinedShaderStorageBlocksCount +
   1335                mActiveOutputVariablesMask.count() >
   1336            static_cast<GLuint>(caps.maxCombinedShaderOutputResources))
   1337        {
   1338            mInfoLog
   1339                << "The sum of the number of active image uniforms, active shader storage blocks "
   1340                   "and active fragment shader outputs exceeds "
   1341                   "MAX_COMBINED_SHADER_OUTPUT_RESOURCES ("
   1342                << caps.maxCombinedShaderOutputResources << ")";
   1343            return false;
   1344        }
   1345    }
   1346 
   1347    mOutputVariables = outputVariables;
   1348 
   1349    if (fragmentShaderVersion == 100)
   1350    {
   1351        return true;
   1352    }
   1353 
   1354    // EXT_blend_func_extended doesn't specify anything related to binding specific elements of an
   1355    // output array in explicit terms.
   1356    //
   1357    // Assuming fragData is an output array, you can defend the position that:
   1358    // P1) you must support binding "fragData" because it's specified
   1359    // P2) you must support querying "fragData[x]" because it's specified
   1360    // P3) you must support binding "fragData[0]" because it's a frequently used pattern
   1361    //
   1362    // Then you can make the leap of faith:
   1363    // P4) you must support binding "fragData[x]" because you support "fragData[0]"
   1364    // P5) you must support binding "fragData[x]" because you support querying "fragData[x]"
   1365    //
   1366    // The spec brings in the "world of arrays" when it mentions binding the arrays and the
   1367    // automatic binding. Thus it must be interpreted that the thing is not undefined, rather you
   1368    // must infer the only possible interpretation (?). Note again: this need of interpretation
   1369    // might be completely off of what GL spec logic is.
   1370    //
   1371    // The other complexity is that unless you implement this feature, it's hard to understand what
   1372    // should happen when the client invokes the feature. You cannot add an additional error as it
   1373    // is not specified. One can ignore it, but obviously it creates the discrepancies...
   1374 
   1375    std::vector<VariableLocation> reservedLocations;
   1376 
   1377    // Process any output API bindings for arrays that don't alias to the first element.
   1378    for (const auto &bindingPair : fragmentOutputLocations)
   1379    {
   1380        const std::string &name       = bindingPair.first;
   1381        const ProgramBinding &binding = bindingPair.second;
   1382 
   1383        size_t nameLengthWithoutArrayIndex;
   1384        unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
   1385        if (arrayIndex == 0 || arrayIndex == GL_INVALID_INDEX)
   1386        {
   1387            continue;
   1388        }
   1389        for (unsigned int outputVariableIndex = 0; outputVariableIndex < mOutputVariables.size();
   1390             outputVariableIndex++)
   1391        {
   1392            const sh::ShaderVariable &outputVariable = mOutputVariables[outputVariableIndex];
   1393            // Check that the binding corresponds to an output array and its array index fits.
   1394            if (outputVariable.isBuiltIn() || !outputVariable.isArray() ||
   1395                !angle::BeginsWith(outputVariable.name, name, nameLengthWithoutArrayIndex) ||
   1396                arrayIndex >= outputVariable.getOutermostArraySize())
   1397            {
   1398                continue;
   1399            }
   1400 
   1401            // Get the API index that corresponds to this exact binding.
   1402            // This index may differ from the index used for the array's base.
   1403            std::vector<VariableLocation> &outputLocations =
   1404                fragmentOutputIndices.getBindingByName(name) == 1 ? mSecondaryOutputLocations
   1405                                                                  : mOutputLocations;
   1406            unsigned int location = binding.location;
   1407            VariableLocation locationInfo(arrayIndex, outputVariableIndex);
   1408            if (location >= outputLocations.size())
   1409            {
   1410                outputLocations.resize(location + 1);
   1411            }
   1412            if (outputLocations[location].used())
   1413            {
   1414                mInfoLog << "Location of variable " << outputVariable.name
   1415                         << " conflicts with another variable.";
   1416                return false;
   1417            }
   1418            outputLocations[location] = locationInfo;
   1419 
   1420            // Note the array binding location so that it can be skipped later.
   1421            reservedLocations.push_back(locationInfo);
   1422        }
   1423    }
   1424 
   1425    // Reserve locations for output variables whose location is fixed in the shader or through the
   1426    // API. Otherwise, the remaining unallocated outputs will be processed later.
   1427    for (unsigned int outputVariableIndex = 0; outputVariableIndex < mOutputVariables.size();
   1428         outputVariableIndex++)
   1429    {
   1430        const sh::ShaderVariable &outputVariable = mOutputVariables[outputVariableIndex];
   1431 
   1432        // Don't store outputs for gl_FragDepth, gl_FragColor, etc.
   1433        if (outputVariable.isBuiltIn())
   1434            continue;
   1435 
   1436        int fixedLocation = GetOutputLocationForLink(fragmentOutputLocations, outputVariable);
   1437        if (fixedLocation == -1)
   1438        {
   1439            // Here we're only reserving locations for variables whose location is fixed.
   1440            continue;
   1441        }
   1442        unsigned int baseLocation = static_cast<unsigned int>(fixedLocation);
   1443 
   1444        std::vector<VariableLocation> &outputLocations =
   1445            IsOutputSecondaryForLink(fragmentOutputIndices, outputVariable)
   1446                ? mSecondaryOutputLocations
   1447                : mOutputLocations;
   1448 
   1449        // GLSL ES 3.10 section 4.3.6: Output variables cannot be arrays of arrays or arrays of
   1450        // structures, so we may use getBasicTypeElementCount().
   1451        unsigned int elementCount = outputVariable.getBasicTypeElementCount();
   1452        if (FindUsedOutputLocation(outputLocations, baseLocation, elementCount, reservedLocations,
   1453                                   outputVariableIndex))
   1454        {
   1455            mInfoLog << "Location of variable " << outputVariable.name
   1456                     << " conflicts with another variable.";
   1457            return false;
   1458        }
   1459        AssignOutputLocations(outputLocations, baseLocation, elementCount, reservedLocations,
   1460                              outputVariableIndex, mOutputVariables[outputVariableIndex]);
   1461    }
   1462 
   1463    // Here we assign locations for the output variables that don't yet have them. Note that we're
   1464    // not necessarily able to fit the variables optimally, since then we might have to try
   1465    // different arrangements of output arrays. Now we just assign the locations in the order that
   1466    // we got the output variables. The spec isn't clear on what kind of algorithm is required for
   1467    // finding locations for the output variables, so this should be acceptable at least for now.
   1468    GLuint maxLocation = static_cast<GLuint>(caps.maxDrawBuffers);
   1469    if (!mSecondaryOutputLocations.empty())
   1470    {
   1471        // EXT_blend_func_extended: Program outputs will be validated against
   1472        // MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT if there's even one output with index one.
   1473        maxLocation = caps.maxDualSourceDrawBuffers;
   1474    }
   1475 
   1476    for (unsigned int outputVariableIndex = 0; outputVariableIndex < mOutputVariables.size();
   1477         outputVariableIndex++)
   1478    {
   1479        const sh::ShaderVariable &outputVariable = mOutputVariables[outputVariableIndex];
   1480 
   1481        // Don't store outputs for gl_FragDepth, gl_FragColor, etc.
   1482        if (outputVariable.isBuiltIn())
   1483            continue;
   1484 
   1485        int fixedLocation = GetOutputLocationForLink(fragmentOutputLocations, outputVariable);
   1486        std::vector<VariableLocation> &outputLocations =
   1487            IsOutputSecondaryForLink(fragmentOutputIndices, outputVariable)
   1488                ? mSecondaryOutputLocations
   1489                : mOutputLocations;
   1490        unsigned int baseLocation = 0;
   1491        unsigned int elementCount = outputVariable.getBasicTypeElementCount();
   1492        if (fixedLocation != -1)
   1493        {
   1494            // Secondary inputs might have caused the max location to drop below what has already
   1495            // been explicitly assigned locations. Check for any fixed locations above the max
   1496            // that should cause linking to fail.
   1497            baseLocation = static_cast<unsigned int>(fixedLocation);
   1498        }
   1499        else
   1500        {
   1501            // No fixed location, so try to fit the output in unassigned locations.
   1502            // Try baseLocations starting from 0 one at a time and see if the variable fits.
   1503            while (FindUsedOutputLocation(outputLocations, baseLocation, elementCount,
   1504                                          reservedLocations, outputVariableIndex))
   1505            {
   1506                baseLocation++;
   1507            }
   1508            AssignOutputLocations(outputLocations, baseLocation, elementCount, reservedLocations,
   1509                                  outputVariableIndex, mOutputVariables[outputVariableIndex]);
   1510        }
   1511 
   1512        // Check for any elements assigned above the max location that are actually used.
   1513        if (baseLocation + elementCount > maxLocation &&
   1514            (baseLocation >= maxLocation ||
   1515             FindUsedOutputLocation(outputLocations, maxLocation,
   1516                                    baseLocation + elementCount - maxLocation, reservedLocations,
   1517                                    outputVariableIndex)))
   1518        {
   1519            // EXT_blend_func_extended: Linking can fail:
   1520            // "if the explicit binding assignments do not leave enough space for the linker to
   1521            // automatically assign a location for a varying out array, which requires multiple
   1522            // contiguous locations."
   1523            mInfoLog << "Could not fit output variable into available locations: "
   1524                     << outputVariable.name;
   1525            return false;
   1526        }
   1527    }
   1528 
   1529    return true;
   1530 }
   1531 
   1532 bool ProgramExecutable::linkUniforms(
   1533    const Context *context,
   1534    const ShaderMap<std::vector<sh::ShaderVariable>> &shaderUniforms,
   1535    InfoLog &infoLog,
   1536    const ProgramAliasedBindings &uniformLocationBindings,
   1537    GLuint *combinedImageUniformsCountOut,
   1538    std::vector<UnusedUniform> *unusedUniformsOutOrNull,
   1539    std::vector<VariableLocation> *uniformLocationsOutOrNull)
   1540 {
   1541    UniformLinker linker(mLinkedShaderStages, shaderUniforms);
   1542    if (!linker.link(context->getCaps(), infoLog, uniformLocationBindings))
   1543    {
   1544        return false;
   1545    }
   1546 
   1547    linker.getResults(&mUniforms, unusedUniformsOutOrNull, uniformLocationsOutOrNull);
   1548 
   1549    linkSamplerAndImageBindings(combinedImageUniformsCountOut);
   1550 
   1551    if (!linkAtomicCounterBuffers(context, infoLog))
   1552    {
   1553        return false;
   1554    }
   1555 
   1556    return true;
   1557 }
   1558 
   1559 void ProgramExecutable::linkSamplerAndImageBindings(GLuint *combinedImageUniforms)
   1560 {
   1561    ASSERT(combinedImageUniforms);
   1562 
   1563    // Iterate over mExecutable->mUniforms from the back, and find the range of subpass inputs,
   1564    // atomic counters, images and samplers in that order.
   1565    auto highIter = mUniforms.rbegin();
   1566    auto lowIter  = highIter;
   1567 
   1568    unsigned int high = static_cast<unsigned int>(mUniforms.size());
   1569    unsigned int low  = high;
   1570 
   1571    // Note that uniform block uniforms are not yet appended to this list.
   1572    ASSERT(mUniforms.empty() || highIter->isAtomicCounter() || highIter->isImage() ||
   1573           highIter->isSampler() || highIter->isInDefaultBlock() || highIter->isFragmentInOut);
   1574 
   1575    for (; lowIter != mUniforms.rend() && lowIter->isFragmentInOut; ++lowIter)
   1576    {
   1577        --low;
   1578    }
   1579 
   1580    mFragmentInoutRange = RangeUI(low, high);
   1581 
   1582    highIter = lowIter;
   1583    high     = low;
   1584 
   1585    for (; lowIter != mUniforms.rend() && lowIter->isAtomicCounter(); ++lowIter)
   1586    {
   1587        --low;
   1588    }
   1589 
   1590    mAtomicCounterUniformRange = RangeUI(low, high);
   1591 
   1592    highIter = lowIter;
   1593    high     = low;
   1594 
   1595    for (; lowIter != mUniforms.rend() && lowIter->isImage(); ++lowIter)
   1596    {
   1597        --low;
   1598    }
   1599 
   1600    mImageUniformRange     = RangeUI(low, high);
   1601    *combinedImageUniforms = 0u;
   1602    // If uniform is a image type, insert it into the mImageBindings array.
   1603    for (unsigned int imageIndex : mImageUniformRange)
   1604    {
   1605        // ES3.1 (section 7.6.1) and GLSL ES3.1 (section 4.4.5), Uniform*i{v} commands
   1606        // cannot load values into a uniform defined as an image. if declare without a
   1607        // binding qualifier, any uniform image variable (include all elements of
   1608        // unbound image array) should be bound to unit zero.
   1609        auto &imageUniform      = mUniforms[imageIndex];
   1610        TextureType textureType = ImageTypeToTextureType(imageUniform.type);
   1611        const GLuint arraySize  = imageUniform.isArray() ? imageUniform.arraySizes[0] : 1u;
   1612 
   1613        if (imageUniform.binding == -1)
   1614        {
   1615            mImageBindings.emplace_back(
   1616                ImageBinding(imageUniform.getBasicTypeElementCount(), textureType));
   1617        }
   1618        else
   1619        {
   1620            // The arrays of arrays are flattened to arrays, it needs to record the array offset for
   1621            // the correct binding image unit.
   1622            mImageBindings.emplace_back(
   1623                ImageBinding(imageUniform.binding + imageUniform.parentArrayIndex() * arraySize,
   1624                             imageUniform.getBasicTypeElementCount(), textureType));
   1625        }
   1626 
   1627        *combinedImageUniforms += imageUniform.activeShaderCount() * arraySize;
   1628    }
   1629 
   1630    highIter = lowIter;
   1631    high     = low;
   1632 
   1633    for (; lowIter != mUniforms.rend() && lowIter->isSampler(); ++lowIter)
   1634    {
   1635        --low;
   1636    }
   1637 
   1638    mSamplerUniformRange = RangeUI(low, high);
   1639 
   1640    // If uniform is a sampler type, insert it into the mSamplerBindings array.
   1641    for (unsigned int samplerIndex : mSamplerUniformRange)
   1642    {
   1643        const auto &samplerUniform = mUniforms[samplerIndex];
   1644        TextureType textureType    = SamplerTypeToTextureType(samplerUniform.type);
   1645        GLenum samplerType         = samplerUniform.typeInfo->type;
   1646        unsigned int elementCount  = samplerUniform.getBasicTypeElementCount();
   1647        SamplerFormat format       = samplerUniform.typeInfo->samplerFormat;
   1648        mSamplerBindings.emplace_back(textureType, samplerType, format, elementCount);
   1649    }
   1650 
   1651    // Whatever is left constitutes the default uniforms.
   1652    mDefaultUniformRange = RangeUI(0, low);
   1653 }
   1654 
   1655 bool ProgramExecutable::linkAtomicCounterBuffers(const Context *context, InfoLog &infoLog)
   1656 {
   1657    for (unsigned int index : mAtomicCounterUniformRange)
   1658    {
   1659        auto &uniform                      = mUniforms[index];
   1660        uniform.blockInfo.offset           = uniform.offset;
   1661        uniform.blockInfo.arrayStride      = (uniform.isArray() ? 4 : 0);
   1662        uniform.blockInfo.matrixStride     = 0;
   1663        uniform.blockInfo.isRowMajorMatrix = false;
   1664 
   1665        bool found = false;
   1666        for (unsigned int bufferIndex = 0; bufferIndex < getActiveAtomicCounterBufferCount();
   1667             ++bufferIndex)
   1668        {
   1669            auto &buffer = mAtomicCounterBuffers[bufferIndex];
   1670            if (buffer.binding == uniform.binding)
   1671            {
   1672                buffer.memberIndexes.push_back(index);
   1673                uniform.bufferIndex = bufferIndex;
   1674                found               = true;
   1675                buffer.unionReferencesWith(uniform);
   1676                break;
   1677            }
   1678        }
   1679        if (!found)
   1680        {
   1681            AtomicCounterBuffer atomicCounterBuffer;
   1682            atomicCounterBuffer.binding = uniform.binding;
   1683            atomicCounterBuffer.memberIndexes.push_back(index);
   1684            atomicCounterBuffer.unionReferencesWith(uniform);
   1685            mAtomicCounterBuffers.push_back(atomicCounterBuffer);
   1686            uniform.bufferIndex = static_cast<int>(getActiveAtomicCounterBufferCount() - 1);
   1687        }
   1688    }
   1689 
   1690    // Count each atomic counter buffer to validate against
   1691    // per-stage and combined gl_Max*AtomicCounterBuffers.
   1692    GLint combinedShaderACBCount           = 0;
   1693    gl::ShaderMap<GLint> perShaderACBCount = {};
   1694    for (unsigned int bufferIndex = 0; bufferIndex < getActiveAtomicCounterBufferCount();
   1695         ++bufferIndex)
   1696    {
   1697        AtomicCounterBuffer &acb        = mAtomicCounterBuffers[bufferIndex];
   1698        const ShaderBitSet shaderStages = acb.activeShaders();
   1699        for (gl::ShaderType shaderType : shaderStages)
   1700        {
   1701            ++perShaderACBCount[shaderType];
   1702        }
   1703        ++combinedShaderACBCount;
   1704    }
   1705    const Caps &caps = context->getCaps();
   1706    if (combinedShaderACBCount > caps.maxCombinedAtomicCounterBuffers)
   1707    {
   1708        infoLog << " combined AtomicCounterBuffers count exceeds limit";
   1709        return false;
   1710    }
   1711    for (gl::ShaderType stage : gl::AllShaderTypes())
   1712    {
   1713        if (perShaderACBCount[stage] > caps.maxShaderAtomicCounterBuffers[stage])
   1714        {
   1715            infoLog << GetShaderTypeString(stage)
   1716                    << " shader AtomicCounterBuffers count exceeds limit";
   1717            return false;
   1718        }
   1719    }
   1720    return true;
   1721 }
   1722 
   1723 void ProgramExecutable::copyInputsFromProgram(const ProgramState &programState)
   1724 {
   1725    mProgramInputs = programState.getProgramInputs();
   1726 }
   1727 
   1728 void ProgramExecutable::copyShaderBuffersFromProgram(const ProgramState &programState,
   1729                                                     ShaderType shaderType)
   1730 {
   1731    AppendActiveBlocks(shaderType, programState.getUniformBlocks(), mUniformBlocks);
   1732    AppendActiveBlocks(shaderType, programState.getShaderStorageBlocks(), mShaderStorageBlocks);
   1733    AppendActiveBlocks(shaderType, programState.getAtomicCounterBuffers(), mAtomicCounterBuffers);
   1734 }
   1735 
   1736 void ProgramExecutable::clearSamplerBindings()
   1737 {
   1738    mSamplerBindings.clear();
   1739 }
   1740 
   1741 void ProgramExecutable::copySamplerBindingsFromProgram(const ProgramState &programState)
   1742 {
   1743    const std::vector<SamplerBinding> &bindings = programState.getSamplerBindings();
   1744    mSamplerBindings.insert(mSamplerBindings.end(), bindings.begin(), bindings.end());
   1745 }
   1746 
   1747 void ProgramExecutable::copyImageBindingsFromProgram(const ProgramState &programState)
   1748 {
   1749    const std::vector<ImageBinding> &bindings = programState.getImageBindings();
   1750    mImageBindings.insert(mImageBindings.end(), bindings.begin(), bindings.end());
   1751 }
   1752 
   1753 void ProgramExecutable::copyOutputsFromProgram(const ProgramState &programState)
   1754 {
   1755    mOutputVariables          = programState.getOutputVariables();
   1756    mOutputLocations          = programState.getOutputLocations();
   1757    mSecondaryOutputLocations = programState.getSecondaryOutputLocations();
   1758 }
   1759 
   1760 void ProgramExecutable::copyUniformsFromProgramMap(const ShaderMap<Program *> &programs)
   1761 {
   1762    // Merge default uniforms.
   1763    auto getDefaultRange = [](const ProgramState &state) { return state.getDefaultUniformRange(); };
   1764    mDefaultUniformRange = AddUniforms(programs, mLinkedShaderStages, mUniforms, getDefaultRange);
   1765 
   1766    // Merge sampler uniforms.
   1767    auto getSamplerRange = [](const ProgramState &state) { return state.getSamplerUniformRange(); };
   1768    mSamplerUniformRange = AddUniforms(programs, mLinkedShaderStages, mUniforms, getSamplerRange);
   1769 
   1770    // Merge image uniforms.
   1771    auto getImageRange = [](const ProgramState &state) { return state.getImageUniformRange(); };
   1772    mImageUniformRange = AddUniforms(programs, mLinkedShaderStages, mUniforms, getImageRange);
   1773 
   1774    // Merge atomic counter uniforms.
   1775    auto getAtomicRange = [](const ProgramState &state) {
   1776        return state.getAtomicCounterUniformRange();
   1777    };
   1778    mAtomicCounterUniformRange =
   1779        AddUniforms(programs, mLinkedShaderStages, mUniforms, getAtomicRange);
   1780 
   1781    // Merge fragment in/out uniforms.
   1782    auto getInoutRange  = [](const ProgramState &state) { return state.getFragmentInoutRange(); };
   1783    mFragmentInoutRange = AddUniforms(programs, mLinkedShaderStages, mUniforms, getInoutRange);
   1784 }
   1785 }  // namespace gl