//
// Copyright 2020 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// ProgramExecutable.cpp: Collects the interfaces common to both Programs and
// ProgramPipelines in order to execute/draw with either.

#include "libANGLE/ProgramExecutable.h"

#include "common/string_utils.h"
#include "libANGLE/Context.h"
#include "libANGLE/Program.h"
#include "libANGLE/Shader.h"
#include "libANGLE/queryconversions.h"
#include "libANGLE/renderer/GLImplFactory.h"
#include "libANGLE/renderer/ProgramExecutableImpl.h"
#include "libANGLE/renderer/ProgramImpl.h"

namespace gl
{
namespace
{
ANGLE_ENABLE_STRUCT_PADDING_WARNINGS
// A placeholder struct just to ensure sh::BlockMemberInfo is tightly packed since vulkan backend
// uses it and memcpy the entire vector which requires it tightly packed to make msan happy.
struct BlockMemberInfoPaddingTest
{
    sh::BlockMemberInfo blockMemberInfo;
};
ANGLE_DISABLE_STRUCT_PADDING_WARNINGS

bool IncludeSameArrayElement(const std::set<std::string> &nameSet, const std::string &name)
{
    std::vector<unsigned int> subscripts;
    std::string baseName = ParseResourceName(name, &subscripts);
    for (const std::string &nameInSet : nameSet)
    {
        std::vector<unsigned int> arrayIndices;
        std::string arrayName = ParseResourceName(nameInSet, &arrayIndices);
        if (baseName == arrayName &&
            (subscripts.empty() || arrayIndices.empty() || subscripts == arrayIndices))
        {
            return true;
        }
    }
    return false;
}

// Find the matching varying or field by name.
const sh::ShaderVariable *FindOutputVaryingOrField(const ProgramMergedVaryings &varyings,
                                                   ShaderType stage,
                                                   const std::string &name)
{
    const sh::ShaderVariable *var = nullptr;
    for (const ProgramVaryingRef &ref : varyings)
    {
        if (ref.frontShaderStage != stage)
        {
            continue;
        }

        const sh::ShaderVariable *varying = ref.get(stage);
        if (varying->name == name)
        {
            var = varying;
            break;
        }
        GLuint fieldIndex = 0;
        var               = varying->findField(name, &fieldIndex);
        if (var != nullptr)
        {
            break;
        }
    }
    return var;
}

bool FindUsedOutputLocation(std::vector<VariableLocation> &outputLocations,
                            unsigned int baseLocation,
                            unsigned int elementCount,
                            const std::vector<VariableLocation> &reservedLocations,
                            unsigned int variableIndex)
{
    if (baseLocation + elementCount > outputLocations.size())
    {
        elementCount = baseLocation < outputLocations.size()
                           ? static_cast<unsigned int>(outputLocations.size() - baseLocation)
                           : 0;
    }
    for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
    {
        const unsigned int location = baseLocation + elementIndex;
        if (outputLocations[location].used())
        {
            VariableLocation locationInfo(elementIndex, variableIndex);
            if (std::find(reservedLocations.begin(), reservedLocations.end(), locationInfo) ==
                reservedLocations.end())
            {
                return true;
            }
        }
    }
    return false;
}

void AssignOutputLocations(std::vector<VariableLocation> &outputLocations,
                           unsigned int baseLocation,
                           unsigned int elementCount,
                           const std::vector<VariableLocation> &reservedLocations,
                           unsigned int variableIndex,
                           ProgramOutput &outputVariable)
{
    if (baseLocation + elementCount > outputLocations.size())
    {
        outputLocations.resize(baseLocation + elementCount);
    }
    for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
    {
        VariableLocation locationInfo(elementIndex, variableIndex);
        if (std::find(reservedLocations.begin(), reservedLocations.end(), locationInfo) ==
            reservedLocations.end())
        {
            outputVariable.pod.location = baseLocation;
            const unsigned int location = baseLocation + elementIndex;
            outputLocations[location]   = locationInfo;
        }
    }
}

int GetOutputLocationForLink(const ProgramAliasedBindings &fragmentOutputLocations,
                             const ProgramOutput &outputVariable)
{
    if (outputVariable.pod.location != -1)
    {
        return outputVariable.pod.location;
    }
    int apiLocation = fragmentOutputLocations.getBinding(outputVariable);
    if (apiLocation != -1)
    {
        return apiLocation;
    }
    return -1;
}

bool IsOutputSecondaryForLink(const ProgramAliasedBindings &fragmentOutputIndexes,
                              const ProgramOutput &outputVariable)
{
    if (outputVariable.pod.index != -1)
    {
        ASSERT(outputVariable.pod.index == 0 || outputVariable.pod.index == 1);
        return (outputVariable.pod.index == 1);
    }
    int apiIndex = fragmentOutputIndexes.getBinding(outputVariable);
    if (apiIndex != -1)
    {
        // Index layout qualifier from the shader takes precedence, so the index from the API is
        // checked only if the index was not set in the shader. This is not specified in the EXT
        // spec, but is specified in desktop OpenGL specs.
        return (apiIndex == 1);
    }
    // EXT_blend_func_extended: Outputs get index 0 by default.
    return false;
}

RangeUI AddUniforms(const ShaderMap<SharedProgramExecutable> &executables,
                    ShaderBitSet activeShaders,
                    std::vector<LinkedUniform> *outputUniforms,
                    std::vector<std::string> *outputUniformNames,
                    std::vector<std::string> *outputUniformMappedNames,
                    const std::function<RangeUI(const ProgramExecutable &)> &getRange)
{
    unsigned int startRange = static_cast<unsigned int>(outputUniforms->size());
    for (ShaderType shaderType : activeShaders)
    {
        const ProgramExecutable &executable = *executables[shaderType];
        const RangeUI uniformRange          = getRange(executable);

        const std::vector<LinkedUniform> &programUniforms = executable.getUniforms();
        outputUniforms->insert(outputUniforms->end(), programUniforms.begin() + uniformRange.low(),
                               programUniforms.begin() + uniformRange.high());

        const std::vector<std::string> &uniformNames = executable.getUniformNames();
        outputUniformNames->insert(outputUniformNames->end(),
                                   uniformNames.begin() + uniformRange.low(),
                                   uniformNames.begin() + uniformRange.high());

        const std::vector<std::string> &uniformMappedNames = executable.getUniformMappedNames();
        outputUniformMappedNames->insert(outputUniformMappedNames->end(),
                                         uniformMappedNames.begin() + uniformRange.low(),
                                         uniformMappedNames.begin() + uniformRange.high());
    }
    return RangeUI(startRange, static_cast<unsigned int>(outputUniforms->size()));
}

template <typename BlockT>
void AppendActiveBlocks(ShaderType shaderType,
                        const std::vector<BlockT> &blocksIn,
                        std::vector<BlockT> &blocksOut,
                        ProgramUniformBlockArray<GLuint> *ppoBlockMap)
{
    for (size_t index = 0; index < blocksIn.size(); ++index)
    {
        const BlockT &block = blocksIn[index];
        if (block.isActive(shaderType))
        {
            // Have a way for the PPO to know how to map the program's UBO index into its own UBO
            // array.  This is used to propagate changes to the program's UBOs to the PPO's UBO
            // list.
            if (ppoBlockMap != nullptr)
            {
                (*ppoBlockMap)[static_cast<uint32_t>(index)] =
                    static_cast<uint32_t>(blocksOut.size());
            }

            blocksOut.push_back(block);
        }
    }
}

void SaveProgramInputs(BinaryOutputStream *stream, const std::vector<ProgramInput> &programInputs)
{
    stream->writeInt(programInputs.size());
    for (const ProgramInput &attrib : programInputs)
    {
        stream->writeString(attrib.name);
        stream->writeString(attrib.mappedName);
        stream->writeStruct(attrib.pod);
    }
}
void LoadProgramInputs(BinaryInputStream *stream, std::vector<ProgramInput> *programInputs)
{
    size_t attribCount = stream->readInt<size_t>();
    ASSERT(programInputs->empty());
    if (attribCount > 0)
    {
        programInputs->resize(attribCount);
        for (size_t attribIndex = 0; attribIndex < attribCount; ++attribIndex)
        {
            ProgramInput &attrib = (*programInputs)[attribIndex];
            stream->readString(&attrib.name);
            stream->readString(&attrib.mappedName);
            stream->readStruct(&attrib.pod);
        }
    }
}

void SaveUniforms(BinaryOutputStream *stream,
                  const std::vector<LinkedUniform> &uniforms,
                  const std::vector<std::string> &uniformNames,
                  const std::vector<std::string> &uniformMappedNames,
                  const std::vector<VariableLocation> &uniformLocations)
{
    stream->writeVector(uniforms);
    ASSERT(uniforms.size() == uniformNames.size());
    ASSERT(uniforms.size() == uniformMappedNames.size());
    for (const std::string &name : uniformNames)
    {
        stream->writeString(name);
    }
    for (const std::string &name : uniformMappedNames)
    {
        stream->writeString(name);
    }
    stream->writeVector(uniformLocations);
}
void LoadUniforms(BinaryInputStream *stream,
                  std::vector<LinkedUniform> *uniforms,
                  std::vector<std::string> *uniformNames,
                  std::vector<std::string> *uniformMappedNames,
                  std::vector<VariableLocation> *uniformLocations)
{
    stream->readVector(uniforms);
    if (!uniforms->empty())
    {
        uniformNames->resize(uniforms->size());
        for (size_t uniformIndex = 0; uniformIndex < uniforms->size(); ++uniformIndex)
        {
            stream->readString(&(*uniformNames)[uniformIndex]);
        }
        uniformMappedNames->resize(uniforms->size());
        for (size_t uniformIndex = 0; uniformIndex < uniforms->size(); ++uniformIndex)
        {
            stream->readString(&(*uniformMappedNames)[uniformIndex]);
        }
    }
    stream->readVector(uniformLocations);
}

void SaveSamplerBindings(BinaryOutputStream *stream,
                         const std::vector<SamplerBinding> &samplerBindings,
                         const std::vector<GLuint> &samplerBoundTextureUnits)
{
    stream->writeVector(samplerBindings);
    stream->writeInt(samplerBoundTextureUnits.size());
}
void LoadSamplerBindings(BinaryInputStream *stream,
                         std::vector<SamplerBinding> *samplerBindings,
                         std::vector<GLuint> *samplerBoundTextureUnits)
{
    stream->readVector(samplerBindings);
    ASSERT(samplerBoundTextureUnits->empty());
    size_t boundTextureUnitsCount = stream->readInt<size_t>();
    samplerBoundTextureUnits->resize(boundTextureUnitsCount, 0);
}

void WriteBufferVariable(BinaryOutputStream *stream, const BufferVariable &var)
{
    stream->writeString(var.name);
    stream->writeString(var.mappedName);
    stream->writeStruct(var.pod);
}

void LoadBufferVariable(BinaryInputStream *stream, BufferVariable *var)
{
    var->name       = stream->readString();
    var->mappedName = stream->readString();
    stream->readStruct(&var->pod);
}

void WriteAtomicCounterBuffer(BinaryOutputStream *stream, const AtomicCounterBuffer &var)
{
    stream->writeVector(var.memberIndexes);
    stream->writeStruct(var.pod);
}

void LoadAtomicCounterBuffer(BinaryInputStream *stream, AtomicCounterBuffer *var)
{
    stream->readVector(&var->memberIndexes);
    stream->readStruct(&var->pod);
}

void WriteInterfaceBlock(BinaryOutputStream *stream, const InterfaceBlock &block)
{
    stream->writeString(block.name);
    stream->writeString(block.mappedName);
    stream->writeVector(block.memberIndexes);
    stream->writeStruct(block.pod);
}

void LoadInterfaceBlock(BinaryInputStream *stream, InterfaceBlock *block)
{
    block->name       = stream->readString();
    block->mappedName = stream->readString();
    stream->readVector(&block->memberIndexes);
    stream->readStruct(&block->pod);
}

void CopyStringToBuffer(GLchar *buffer,
                        const std::string &string,
                        GLsizei bufSize,
                        GLsizei *lengthOut)
{
    ASSERT(bufSize > 0);
    size_t length = std::min<size_t>(bufSize - 1, string.length());
    memcpy(buffer, string.c_str(), length);
    buffer[length] = '\0';

    if (lengthOut)
    {
        *lengthOut = static_cast<GLsizei>(length);
    }
}

template <typename T>
GLuint GetResourceMaxNameSize(const T &resource, GLint max)
{
    if (resource.isArray())
    {
        return std::max(max, clampCast<GLint>((resource.name + "[0]").size()));
    }
    else
    {
        return std::max(max, clampCast<GLint>((resource.name).size()));
    }
}

template <typename T>
GLuint GetResourceLocation(const GLchar *name, const T &variable, GLint location)
{
    if (variable.isBuiltIn())
    {
        return GL_INVALID_INDEX;
    }

    if (variable.isArray())
    {
        size_t nameLengthWithoutArrayIndexOut;
        size_t arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndexOut);
        // The 'name' string may not contain the array notation "[0]"
        if (arrayIndex != GL_INVALID_INDEX)
        {
            location += arrayIndex;
        }
    }

    return location;
}

template <typename T>
const std::string GetResourceName(const T &resource)
{
    std::string resourceName = resource.name;

    if (resource.isArray())
    {
        resourceName += "[0]";
    }

    return resourceName;
}

GLint GetVariableLocation(const std::vector<gl::ProgramOutput> &list,
                          const std::vector<VariableLocation> &locationList,
                          const std::string &name)
{
    size_t nameLengthWithoutArrayIndex;
    unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);

    for (size_t location = 0u; location < locationList.size(); ++location)
    {
        const VariableLocation &variableLocation = locationList[location];
        if (!variableLocation.used())
        {
            continue;
        }

        const gl::ProgramOutput &variable = list[variableLocation.index];

        // Array output variables may be bound out of order, so we need to ensure we only pick the
        // first element if given the base name.
        if ((variable.name == name) && (variableLocation.arrayIndex == 0))
        {
            return static_cast<GLint>(location);
        }
        if (variable.isArray() && variableLocation.arrayIndex == arrayIndex &&
            angle::BeginsWith(variable.name, name, nameLengthWithoutArrayIndex))
        {
            return static_cast<GLint>(location);
        }
    }

    return -1;
}

template <typename VarT>
GLuint GetResourceIndexFromName(const std::vector<VarT> &list, const std::string &name)
{
    std::string nameAsArrayName = name + "[0]";
    for (size_t index = 0; index < list.size(); index++)
    {
        const VarT &resource = list[index];
        if (resource.name == name || (resource.isArray() && resource.name == nameAsArrayName))
        {
            return static_cast<GLuint>(index);
        }
    }

    return GL_INVALID_INDEX;
}

GLuint GetUniformIndexFromName(const std::vector<LinkedUniform> &uniformList,
                               const std::vector<std::string> &nameList,
                               const std::string &name)
{
    std::string nameAsArrayName = name + "[0]";
    for (size_t index = 0; index < nameList.size(); index++)
    {
        const std::string &uniformName = nameList[index];
        if (uniformName == name || (uniformList[index].isArray() && uniformName == nameAsArrayName))
        {
            return static_cast<GLuint>(index);
        }
    }

    return GL_INVALID_INDEX;
}

GLint GetUniformLocation(const std::vector<LinkedUniform> &uniformList,
                         const std::vector<std::string> &nameList,
                         const std::vector<VariableLocation> &locationList,
                         const std::string &name)
{
    size_t nameLengthWithoutArrayIndex;
    unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);

    for (size_t location = 0u; location < locationList.size(); ++location)
    {
        const VariableLocation &variableLocation = locationList[location];
        if (!variableLocation.used())
        {
            continue;
        }

        const LinkedUniform &variable  = uniformList[variableLocation.index];
        const std::string &uniformName = nameList[variableLocation.index];

        // Array output variables may be bound out of order, so we need to ensure we only pick the
        // first element if given the base name. Uniforms don't allow this behavior and some code
        // seemingly depends on the opposite behavior, so only enable it for output variables.
        if (angle::BeginsWith(uniformName, name) && (variableLocation.arrayIndex == 0))
        {
            if (name.length() == uniformName.length())
            {
                ASSERT(name == uniformName);
                // GLES 3.1 November 2016 page 87.
                // The string exactly matches the name of the active variable.
                return static_cast<GLint>(location);
            }
            if (name.length() + 3u == uniformName.length() && variable.isArray())
            {
                ASSERT(name + "[0]" == uniformName);
                // The string identifies the base name of an active array, where the string would
                // exactly match the name of the variable if the suffix "[0]" were appended to the
                // string.
                return static_cast<GLint>(location);
            }
        }
        if (variable.isArray() && variableLocation.arrayIndex == arrayIndex &&
            nameLengthWithoutArrayIndex + 3u == uniformName.length() &&
            angle::BeginsWith(uniformName, name, nameLengthWithoutArrayIndex))
        {
            ASSERT(name.substr(0u, nameLengthWithoutArrayIndex) + "[0]" == uniformName);
            // The string identifies an active element of the array, where the string ends with the
            // concatenation of the "[" character, an integer (with no "+" sign, extra leading
            // zeroes, or whitespace) identifying an array element, and the "]" character, the
            // integer is less than the number of active elements of the array variable, and where
            // the string would exactly match the enumerated name of the array if the decimal
            // integer were replaced with zero.
            return static_cast<GLint>(location);
        }
    }

    return -1;
}

GLuint GetInterfaceBlockIndex(const std::vector<InterfaceBlock> &list, const std::string &name)
{
    std::vector<unsigned int> subscripts;
    std::string baseName = ParseResourceName(name, &subscripts);

    unsigned int numBlocks = static_cast<unsigned int>(list.size());
    for (unsigned int blockIndex = 0; blockIndex < numBlocks; blockIndex++)
    {
        const auto &block = list[blockIndex];
        if (block.name == baseName)
        {
            const bool arrayElementZero =
                (subscripts.empty() && (!block.pod.isArray || block.pod.arrayElement == 0));
            const bool arrayElementMatches =
                (subscripts.size() == 1 && subscripts[0] == block.pod.arrayElement);
            if (arrayElementMatches || arrayElementZero)
            {
                return blockIndex;
            }
        }
    }

    return GL_INVALID_INDEX;
}

void GetInterfaceBlockName(const UniformBlockIndex index,
                           const std::vector<InterfaceBlock> &list,
                           GLsizei bufSize,
                           GLsizei *length,
                           GLchar *name)
{
    ASSERT(index.value < list.size());

    const auto &block = list[index.value];

    if (bufSize > 0)
    {
        std::string blockName = block.name;

        if (block.pod.isArray)
        {
            blockName += ArrayString(block.pod.arrayElement);
        }
        CopyStringToBuffer(name, blockName, bufSize, length);
    }
}

template <typename T>
GLint GetActiveInterfaceBlockMaxNameLength(const std::vector<T> &resources)
{
    int maxLength = 0;

    for (const T &resource : resources)
    {
        if (!resource.name.empty())
        {
            int length = static_cast<int>(resource.nameWithArrayIndex().length());
            maxLength  = std::max(length + 1, maxLength);
        }
    }

    return maxLength;
}

// This simplified cast function doesn't need to worry about advanced concepts like
// depth range values, or casting to bool.
template <typename DestT, typename SrcT>
DestT UniformStateQueryCast(SrcT value);

// From-Float-To-Integer Casts
template <>
GLint UniformStateQueryCast(GLfloat value)
{
    return clampCast<GLint>(roundf(value));
}

template <>
GLuint UniformStateQueryCast(GLfloat value)
{
    return clampCast<GLuint>(roundf(value));
}

// From-Integer-to-Integer Casts
template <>
GLint UniformStateQueryCast(GLuint value)
{
    return clampCast<GLint>(value);
}

template <>
GLuint UniformStateQueryCast(GLint value)
{
    return clampCast<GLuint>(value);
}

// From-Boolean-to-Anything Casts
template <>
GLfloat UniformStateQueryCast(GLboolean value)
{
    return (ConvertToBool(value) ? 1.0f : 0.0f);
}

template <>
GLint UniformStateQueryCast(GLboolean value)
{
    return (ConvertToBool(value) ? 1 : 0);
}

template <>
GLuint UniformStateQueryCast(GLboolean value)
{
    return (ConvertToBool(value) ? 1u : 0u);
}

// Default to static_cast
template <typename DestT, typename SrcT>
DestT UniformStateQueryCast(SrcT value)
{
    return static_cast<DestT>(value);
}

template <typename SrcT, typename DestT>
void UniformStateQueryCastLoop(DestT *dataOut, const uint8_t *srcPointer, int components)
{
    for (int comp = 0; comp < components; ++comp)
    {
        // We only work with strides of 4 bytes for uniform components. (GLfloat/GLint)
        // Don't use SrcT stride directly since GLboolean has a stride of 1 byte.
        size_t offset               = comp * 4;
        const SrcT *typedSrcPointer = reinterpret_cast<const SrcT *>(&srcPointer[offset]);
        dataOut[comp]               = UniformStateQueryCast<DestT>(*typedSrcPointer);
    }
}
}  // anonymous namespace

// ImageBinding implementation.
ImageBinding::ImageBinding(GLuint imageUnit, size_t count, TextureType textureTypeIn)
    : textureType(textureTypeIn)
{
    for (size_t index = 0; index < count; ++index)
    {
        boundImageUnits.push_back(imageUnit + static_cast<GLuint>(index));
    }
}

// ProgramInput implementation.
ProgramInput::ProgramInput(const sh::ShaderVariable &var)
{
    ASSERT(!var.isStruct());

    name       = var.name;
    mappedName = var.mappedName;

    SetBitField(pod.type, var.type);
    pod.location = var.hasImplicitLocation ? -1 : var.location;
    SetBitField(pod.interpolation, var.interpolation);
    pod.flagBitsAsUByte              = 0;
    pod.flagBits.active              = var.active;
    pod.flagBits.isPatch             = var.isPatch;
    pod.flagBits.hasImplicitLocation = var.hasImplicitLocation;
    pod.flagBits.isArray             = var.isArray();
    pod.flagBits.isBuiltIn           = IsBuiltInName(var.name);
    SetBitField(pod.basicTypeElementCount, var.getBasicTypeElementCount());
    pod.id = var.id;
    SetBitField(pod.arraySizeProduct, var.getArraySizeProduct());
}

// ProgramOutput implementation.
ProgramOutput::ProgramOutput(const sh::ShaderVariable &var)
{
    name       = var.name;
    mappedName = var.mappedName;

    pod.type     = var.type;
    pod.location = var.location;
    pod.index    = var.index;
    pod.id       = var.id;

    SetBitField(pod.outermostArraySize, var.getOutermostArraySize());
    SetBitField(pod.basicTypeElementCount, var.getBasicTypeElementCount());

    SetBitField(pod.isPatch, var.isPatch);
    SetBitField(pod.yuv, var.yuv);
    SetBitField(pod.isBuiltIn, IsBuiltInName(var.name));
    SetBitField(pod.isArray, var.isArray());
    SetBitField(pod.hasImplicitLocation, var.hasImplicitLocation);
    SetBitField(pod.pad, 0);
}

// ProgramExecutable implementation.
ProgramExecutable::ProgramExecutable(rx::GLImplFactory *factory, InfoLog *infoLog)
    : mImplementation(factory->createProgramExecutable(this)),
      mInfoLog(infoLog),
      mCachedBaseVertex(0),
      mCachedBaseInstance(0),
      mIsPPO(false)
{
    memset(&mPod, 0, sizeof(mPod));
    reset();
}

ProgramExecutable::~ProgramExecutable()
{
    ASSERT(mPostLinkSubTasks.empty());
    ASSERT(mPostLinkSubTaskWaitableEvents.empty());
    ASSERT(mImplementation == nullptr);
}

void ProgramExecutable::destroy(const Context *context)
{
    ASSERT(mImplementation != nullptr);

    for (SharedProgramExecutable &executable : mPPOProgramExecutables)
    {
        if (executable)
        {
            UninstallExecutable(context, &executable);
        }
    }

    mImplementation->destroy(context);
    SafeDelete(mImplementation);
}

void ProgramExecutable::reset()
{
    mPod.activeAttribLocationsMask.reset();
    mPod.attributesTypeMask.reset();
    mPod.attributesMask.reset();
    mPod.maxActiveAttribLocation = 0;
    mPod.activeOutputVariablesMask.reset();
    mPod.activeSecondaryOutputVariablesMask.reset();

    mPod.defaultUniformRange       = RangeUI(0, 0);
    mPod.samplerUniformRange       = RangeUI(0, 0);
    mPod.imageUniformRange         = RangeUI(0, 0);
    mPod.atomicCounterUniformRange = RangeUI(0, 0);

    mPod.fragmentInoutIndices.reset();

    mPod.hasClipDistance         = false;
    mPod.hasDiscard              = false;
    mPod.enablesPerSampleShading = false;
    mPod.hasYUVOutput            = false;

    mPod.advancedBlendEquations.reset();

    mPod.geometryShaderInputPrimitiveType  = PrimitiveMode::Triangles;
    mPod.geometryShaderOutputPrimitiveType = PrimitiveMode::TriangleStrip;
    mPod.geometryShaderInvocations         = 1;
    mPod.geometryShaderMaxVertices         = 0;

    mPod.transformFeedbackBufferMode = GL_INTERLEAVED_ATTRIBS;

    mPod.numViews = -1;

    mPod.drawIDLocation = -1;

    mPod.baseVertexLocation   = -1;
    mPod.baseInstanceLocation = -1;

    mPod.tessControlShaderVertices = 0;
    mPod.tessGenMode               = GL_NONE;
    mPod.tessGenSpacing            = GL_NONE;
    mPod.tessGenVertexOrder        = GL_NONE;
    mPod.tessGenPointMode          = GL_NONE;
    mPod.drawBufferTypeMask.reset();
    mPod.computeShaderLocalSize.fill(1);

    mPod.specConstUsageBits.reset();

    mActiveSamplersMask.reset();
    mActiveSamplerRefCounts = {};
    mActiveSamplerTypes.fill(TextureType::InvalidEnum);
    mActiveSamplerYUV.reset();
    mActiveSamplerFormats.fill(SamplerFormat::InvalidEnum);

    mActiveImagesMask.reset();

    mUniformBlockIndexToBufferBinding = {};

    mProgramInputs.clear();
    mLinkedTransformFeedbackVaryings.clear();
    mTransformFeedbackStrides.clear();
    mUniforms.clear();
    mUniformNames.clear();
    mUniformMappedNames.clear();
    mUniformBlocks.clear();
    mUniformLocations.clear();
    mShaderStorageBlocks.clear();
    mAtomicCounterBuffers.clear();
    mBufferVariables.clear();
    mOutputVariables.clear();
    mOutputLocations.clear();
    mSecondaryOutputLocations.clear();
    mSamplerBindings.clear();
    mSamplerBoundTextureUnits.clear();
    mImageBindings.clear();

    mPostLinkSubTasks.clear();
    mPostLinkSubTaskWaitableEvents.clear();
}

void ProgramExecutable::load(gl::BinaryInputStream *stream)
{
    static_assert(MAX_VERTEX_ATTRIBS * 2 <= sizeof(uint32_t) * 8,
                  "Too many vertex attribs for mask: All bits of mAttributesTypeMask types and "
                  "mask fit into 32 bits each");
    static_assert(IMPLEMENTATION_MAX_DRAW_BUFFERS * 2 <= 8 * sizeof(uint32_t),
                  "All bits of mDrawBufferTypeMask and mActiveOutputVariables types and mask fit "
                  "into 32 bits each");

    stream->readStruct(&mPod);

    LoadProgramInputs(stream, &mProgramInputs);
    LoadUniforms(stream, &mUniforms, &mUniformNames, &mUniformMappedNames, &mUniformLocations);

    size_t uniformBlockCount = stream->readInt<size_t>();
    ASSERT(getUniformBlocks().empty());
    mUniformBlocks.resize(uniformBlockCount);
    for (size_t uniformBlockIndex = 0; uniformBlockIndex < uniformBlockCount; ++uniformBlockIndex)
    {
        InterfaceBlock &uniformBlock = mUniformBlocks[uniformBlockIndex];
        LoadInterfaceBlock(stream, &uniformBlock);
    }

    size_t shaderStorageBlockCount = stream->readInt<size_t>();
    ASSERT(getShaderStorageBlocks().empty());
    mShaderStorageBlocks.resize(shaderStorageBlockCount);
    for (size_t shaderStorageBlockIndex = 0; shaderStorageBlockIndex < shaderStorageBlockCount;
         ++shaderStorageBlockIndex)
    {
        InterfaceBlock &shaderStorageBlock = mShaderStorageBlocks[shaderStorageBlockIndex];
        LoadInterfaceBlock(stream, &shaderStorageBlock);
    }

    size_t atomicCounterBufferCount = stream->readInt<size_t>();
    ASSERT(getAtomicCounterBuffers().empty());
    mAtomicCounterBuffers.resize(atomicCounterBufferCount);
    for (size_t bufferIndex = 0; bufferIndex < atomicCounterBufferCount; ++bufferIndex)
    {
        AtomicCounterBuffer &atomicCounterBuffer = mAtomicCounterBuffers[bufferIndex];
        LoadAtomicCounterBuffer(stream, &atomicCounterBuffer);
    }

    size_t bufferVariableCount = stream->readInt<size_t>();
    ASSERT(getBufferVariables().empty());
    mBufferVariables.resize(bufferVariableCount);
    for (size_t bufferVarIndex = 0; bufferVarIndex < bufferVariableCount; ++bufferVarIndex)
    {
        LoadBufferVariable(stream, &mBufferVariables[bufferVarIndex]);
    }

    size_t transformFeedbackVaryingCount = stream->readInt<size_t>();
    ASSERT(mLinkedTransformFeedbackVaryings.empty());
    mLinkedTransformFeedbackVaryings.resize(transformFeedbackVaryingCount);
    for (size_t transformFeedbackVaryingIndex = 0;
         transformFeedbackVaryingIndex < transformFeedbackVaryingCount;
         ++transformFeedbackVaryingIndex)
    {
        TransformFeedbackVarying &varying =
            mLinkedTransformFeedbackVaryings[transformFeedbackVaryingIndex];
        stream->readVector(&varying.arraySizes);
        stream->readInt(&varying.type);
        stream->readString(&varying.name);
        varying.arrayIndex = stream->readInt<GLuint>();
    }

    size_t outputCount = stream->readInt<size_t>();
    ASSERT(getOutputVariables().empty());
    mOutputVariables.resize(outputCount);
    for (size_t outputIndex = 0; outputIndex < outputCount; ++outputIndex)
    {
        ProgramOutput &output = mOutputVariables[outputIndex];
        stream->readString(&output.name);
        stream->readString(&output.mappedName);
        stream->readStruct(&output.pod);
    }

    stream->readVector(&mOutputLocations);
    stream->readVector(&mSecondaryOutputLocations);
    LoadSamplerBindings(stream, &mSamplerBindings, &mSamplerBoundTextureUnits);

    size_t imageBindingCount = stream->readInt<size_t>();
    ASSERT(mImageBindings.empty());
    mImageBindings.resize(imageBindingCount);
    for (size_t imageIndex = 0; imageIndex < imageBindingCount; ++imageIndex)
    {
        ImageBinding &imageBinding = mImageBindings[imageIndex];
        size_t elementCount        = stream->readInt<size_t>();
        imageBinding.textureType   = static_cast<TextureType>(stream->readInt<unsigned int>());
        imageBinding.boundImageUnits.resize(elementCount);
        for (size_t elementIndex = 0; elementIndex < elementCount; ++elementIndex)
        {
            imageBinding.boundImageUnits[elementIndex] = stream->readInt<unsigned int>();
        }
    }

    // These values are currently only used by PPOs, so only load them when the program is marked
    // separable to save memory.
    if (mPod.isSeparable)
    {
        for (ShaderType shaderType : getLinkedShaderStages())
        {
            mLinkedOutputVaryings[shaderType].resize(stream->readInt<size_t>());
            for (sh::ShaderVariable &variable : mLinkedOutputVaryings[shaderType])
            {
                LoadShaderVar(stream, &variable);
            }
            mLinkedInputVaryings[shaderType].resize(stream->readInt<size_t>());
            for (sh::ShaderVariable &variable : mLinkedInputVaryings[shaderType])
            {
                LoadShaderVar(stream, &variable);
            }
            mLinkedUniforms[shaderType].resize(stream->readInt<size_t>());
            for (sh::ShaderVariable &variable : mLinkedUniforms[shaderType])
            {
                LoadShaderVar(stream, &variable);
            }
            mLinkedUniformBlocks[shaderType].resize(stream->readInt<size_t>());
            for (sh::InterfaceBlock &shaderStorageBlock : mLinkedUniformBlocks[shaderType])
            {
                LoadShInterfaceBlock(stream, &shaderStorageBlock);
            }
        }
    }
}

void ProgramExecutable::save(gl::BinaryOutputStream *stream) const
{
    static_assert(MAX_VERTEX_ATTRIBS * 2 <= sizeof(uint32_t) * 8,
                  "All bits of mAttributesTypeMask types and mask fit into 32 bits each");
    static_assert(
        IMPLEMENTATION_MAX_DRAW_BUFFERS * 2 <= 8 * sizeof(uint32_t),
        "All bits of mDrawBufferTypeMask and mActiveOutputVariables can be contained in 32 bits");

    ASSERT(mPod.geometryShaderInvocations >= 1 && mPod.geometryShaderMaxVertices >= 0);
    stream->writeStruct(mPod);

    SaveProgramInputs(stream, mProgramInputs);
    SaveUniforms(stream, mUniforms, mUniformNames, mUniformMappedNames, mUniformLocations);

    stream->writeInt(getUniformBlocks().size());
    for (const InterfaceBlock &uniformBlock : getUniformBlocks())
    {
        WriteInterfaceBlock(stream, uniformBlock);
    }

    stream->writeInt(getShaderStorageBlocks().size());
    for (const InterfaceBlock &shaderStorageBlock : getShaderStorageBlocks())
    {
        WriteInterfaceBlock(stream, shaderStorageBlock);
    }

    stream->writeInt(mAtomicCounterBuffers.size());
    for (const AtomicCounterBuffer &atomicCounterBuffer : getAtomicCounterBuffers())
    {
        WriteAtomicCounterBuffer(stream, atomicCounterBuffer);
    }

    stream->writeInt(getBufferVariables().size());
    for (const BufferVariable &bufferVariable : getBufferVariables())
    {
        WriteBufferVariable(stream, bufferVariable);
    }

    stream->writeInt(getLinkedTransformFeedbackVaryings().size());
    for (const auto &var : getLinkedTransformFeedbackVaryings())
    {
        stream->writeVector(var.arraySizes);
        stream->writeInt(var.type);
        stream->writeString(var.name);

        stream->writeIntOrNegOne(var.arrayIndex);
    }

    stream->writeInt(getOutputVariables().size());
    for (const ProgramOutput &output : getOutputVariables())
    {
        stream->writeString(output.name);
        stream->writeString(output.mappedName);
        stream->writeStruct(output.pod);
    }

    stream->writeVector(mOutputLocations);
    stream->writeVector(mSecondaryOutputLocations);
    SaveSamplerBindings(stream, mSamplerBindings, mSamplerBoundTextureUnits);

    stream->writeInt(getImageBindings().size());
    for (const auto &imageBinding : getImageBindings())
    {
        stream->writeInt(imageBinding.boundImageUnits.size());
        stream->writeInt(static_cast<unsigned int>(imageBinding.textureType));
        for (size_t i = 0; i < imageBinding.boundImageUnits.size(); ++i)
        {
            stream->writeInt(imageBinding.boundImageUnits[i]);
        }
    }

    // These values are currently only used by PPOs, so only save them when the program is marked
    // separable to save memory.
    if (mPod.isSeparable)
    {
        for (ShaderType shaderType : getLinkedShaderStages())
        {
            stream->writeInt(mLinkedOutputVaryings[shaderType].size());
            for (const sh::ShaderVariable &shaderVariable : mLinkedOutputVaryings[shaderType])
            {
                WriteShaderVar(stream, shaderVariable);
            }
            stream->writeInt(mLinkedInputVaryings[shaderType].size());
            for (const sh::ShaderVariable &shaderVariable : mLinkedInputVaryings[shaderType])
            {
                WriteShaderVar(stream, shaderVariable);
            }
            stream->writeInt(mLinkedUniforms[shaderType].size());
            for (const sh::ShaderVariable &shaderVariable : mLinkedUniforms[shaderType])
            {
                WriteShaderVar(stream, shaderVariable);
            }
            stream->writeInt(mLinkedUniformBlocks[shaderType].size());
            for (const sh::InterfaceBlock &shaderStorageBlock : mLinkedUniformBlocks[shaderType])
            {
                WriteShInterfaceBlock(stream, shaderStorageBlock);
            }
        }
    }
}

std::string ProgramExecutable::getInfoLogString() const
{
    return mInfoLog->str();
}

ShaderType ProgramExecutable::getFirstLinkedShaderStageType() const
{
    const ShaderBitSet linkedStages = mPod.linkedShaderStages;
    if (linkedStages.none())
    {
        return ShaderType::InvalidEnum;
    }

    return linkedStages.first();
}

ShaderType ProgramExecutable::getLastLinkedShaderStageType() const
{
    const ShaderBitSet linkedStages = mPod.linkedShaderStages;
    if (linkedStages.none())
    {
        return ShaderType::InvalidEnum;
    }

    return linkedStages.last();
}

void ProgramExecutable::setActive(size_t textureUnit,
                                  const SamplerBinding &samplerBinding,
                                  const gl::LinkedUniform &samplerUniform)
{
    mActiveSamplersMask.set(textureUnit);
    mActiveSamplerTypes[textureUnit]      = samplerBinding.textureType;
    mActiveSamplerYUV[textureUnit]        = IsSamplerYUVType(samplerBinding.samplerType);
    mActiveSamplerFormats[textureUnit]    = samplerBinding.format;
    mActiveSamplerShaderBits[textureUnit] = samplerUniform.activeShaders();
}

void ProgramExecutable::setInactive(size_t textureUnit)
{
    mActiveSamplersMask.reset(textureUnit);
    mActiveSamplerTypes[textureUnit] = TextureType::InvalidEnum;
    mActiveSamplerYUV.reset(textureUnit);
    mActiveSamplerFormats[textureUnit] = SamplerFormat::InvalidEnum;
    mActiveSamplerShaderBits[textureUnit].reset();
}

void ProgramExecutable::hasSamplerTypeConflict(size_t textureUnit)
{
    // Conflicts are marked with InvalidEnum
    mActiveSamplerYUV.reset(textureUnit);
    mActiveSamplerTypes[textureUnit] = TextureType::InvalidEnum;
}

void ProgramExecutable::hasSamplerFormatConflict(size_t textureUnit)
{
    // Conflicts are marked with InvalidEnum
    mActiveSamplerFormats[textureUnit] = SamplerFormat::InvalidEnum;
}

void ProgramExecutable::updateActiveSamplers(const ProgramExecutable &executable)
{
    const std::vector<SamplerBinding> &samplerBindings = executable.getSamplerBindings();
    const std::vector<GLuint> &boundTextureUnits       = executable.getSamplerBoundTextureUnits();

    for (uint32_t samplerIndex = 0; samplerIndex < samplerBindings.size(); ++samplerIndex)
    {
        const SamplerBinding &samplerBinding = samplerBindings[samplerIndex];

        for (uint16_t index = 0; index < samplerBinding.textureUnitsCount; index++)
        {
            GLint textureUnit = samplerBinding.getTextureUnit(boundTextureUnits, index);
            if (++mActiveSamplerRefCounts[textureUnit] == 1)
            {
                uint32_t uniformIndex = executable.getUniformIndexFromSamplerIndex(samplerIndex);
                setActive(textureUnit, samplerBinding, executable.getUniforms()[uniformIndex]);
            }
            else
            {
                if (mActiveSamplerTypes[textureUnit] != samplerBinding.textureType ||
                    mActiveSamplerYUV.test(textureUnit) !=
                        IsSamplerYUVType(samplerBinding.samplerType))
                {
                    hasSamplerTypeConflict(textureUnit);
                }

                if (mActiveSamplerFormats[textureUnit] != samplerBinding.format)
                {
                    hasSamplerFormatConflict(textureUnit);
                }
            }
            mActiveSamplersMask.set(textureUnit);
        }
    }

    // Invalidate the validation cache.
    resetCachedValidateSamplersResult();
}

void ProgramExecutable::updateActiveImages(const ProgramExecutable &executable)
{
    const std::vector<ImageBinding> &imageBindings = executable.getImageBindings();
    for (uint32_t imageIndex = 0; imageIndex < imageBindings.size(); ++imageIndex)
    {
        const gl::ImageBinding &imageBinding = imageBindings.at(imageIndex);

        uint32_t uniformIndex = executable.getUniformIndexFromImageIndex(imageIndex);
        const gl::LinkedUniform &imageUniform = executable.getUniforms()[uniformIndex];
        const ShaderBitSet shaderBits         = imageUniform.activeShaders();
        for (GLint imageUnit : imageBinding.boundImageUnits)
        {
            mActiveImagesMask.set(imageUnit);
            mActiveImageShaderBits[imageUnit] |= shaderBits;
        }
    }
}

void ProgramExecutable::setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex)
{
    bool foundBinding         = false;
    TextureType foundType     = TextureType::InvalidEnum;
    bool foundYUV             = false;
    SamplerFormat foundFormat = SamplerFormat::InvalidEnum;

    for (uint32_t samplerIndex = 0; samplerIndex < mSamplerBindings.size(); ++samplerIndex)
    {
        const SamplerBinding &binding = mSamplerBindings[samplerIndex];

        // A conflict exists if samplers of different types are sourced by the same texture unit.
        // We need to check all bound textures to detect this error case.
        for (uint16_t index = 0; index < binding.textureUnitsCount; index++)
        {
            GLuint textureUnit = binding.getTextureUnit(mSamplerBoundTextureUnits, index);
            if (textureUnit != textureUnitIndex)
            {
                continue;
            }

            if (!foundBinding)
            {
                foundBinding          = true;
                foundType             = binding.textureType;
                foundYUV              = IsSamplerYUVType(binding.samplerType);
                foundFormat           = binding.format;
                uint32_t uniformIndex = getUniformIndexFromSamplerIndex(samplerIndex);
                setActive(textureUnit, binding, mUniforms[uniformIndex]);
            }
            else
            {
                if (foundType != binding.textureType ||
                    foundYUV != IsSamplerYUVType(binding.samplerType))
                {
                    hasSamplerTypeConflict(textureUnit);
                }

                if (foundFormat != binding.format)
                {
                    hasSamplerFormatConflict(textureUnit);
                }
            }
        }
    }
}

void ProgramExecutable::saveLinkedStateInfo(const ProgramState &state)
{
    for (ShaderType shaderType : getLinkedShaderStages())
    {
        const SharedCompiledShaderState &shader = state.getAttachedShader(shaderType);
        ASSERT(shader);
        mPod.linkedShaderVersions[shaderType] = shader->shaderVersion;
        mLinkedOutputVaryings[shaderType]     = shader->outputVaryings;
        mLinkedInputVaryings[shaderType]      = shader->inputVaryings;
        mLinkedUniforms[shaderType]           = shader->uniforms;
        mLinkedUniformBlocks[shaderType]      = shader->uniformBlocks;
    }
}

bool ProgramExecutable::linkMergedVaryings(const Caps &caps,
                                           const Limitations &limitations,
                                           const Version &clientVersion,
                                           bool webglCompatibility,
                                           const ProgramMergedVaryings &mergedVaryings,
                                           const LinkingVariables &linkingVariables,
                                           ProgramVaryingPacking *varyingPacking)
{
    ShaderType tfStage = GetLastPreFragmentStage(linkingVariables.isShaderStageUsedBitset);

    if (!linkValidateTransformFeedback(caps, clientVersion, mergedVaryings, tfStage))
    {
        return false;
    }

    // Map the varyings to the register file
    // In WebGL, we use a slightly different handling for packing variables.
    gl::PackMode packMode = PackMode::ANGLE_RELAXED;
    if (limitations.noFlexibleVaryingPacking)
    {
        // D3D9 pack mode is strictly more strict than WebGL, so takes priority.
        packMode = PackMode::ANGLE_NON_CONFORMANT_D3D9;
    }
    else if (webglCompatibility)
    {
        packMode = PackMode::WEBGL_STRICT;
    }

    // Build active shader stage map.
    ShaderBitSet activeShadersMask;
    for (ShaderType shaderType : kAllGraphicsShaderTypes)
    {
        // - Check for attached shaders to handle the case of a Program linking the currently
        // attached shaders.
        // - Check for linked shaders to handle the case of a PPO linking separable programs before
        // drawing.
        if (linkingVariables.isShaderStageUsedBitset[shaderType] ||
            getLinkedShaderStages().test(shaderType))
        {
            activeShadersMask[shaderType] = true;
        }
    }

    if (!varyingPacking->collectAndPackUserVaryings(*mInfoLog, caps, packMode, activeShadersMask,
                                                    mergedVaryings, mTransformFeedbackVaryingNames,
                                                    mPod.isSeparable))
    {
        return false;
    }

    gatherTransformFeedbackVaryings(mergedVaryings, tfStage);
    updateTransformFeedbackStrides();

    return true;
}

bool ProgramExecutable::linkValidateTransformFeedback(const Caps &caps,
                                                      const Version &clientVersion,
                                                      const ProgramMergedVaryings &varyings,
                                                      ShaderType stage)
{
    // Validate the tf names regardless of the actual program varyings.
    std::set<std::string> uniqueNames;
    for (const std::string &tfVaryingName : mTransformFeedbackVaryingNames)
    {
        if (clientVersion < Version(3, 1) && tfVaryingName.find('[') != std::string::npos)
        {
            *mInfoLog << "Capture of array elements is undefined and not supported.";
            return false;
        }
        if (clientVersion >= Version(3, 1))
        {
            if (IncludeSameArrayElement(uniqueNames, tfVaryingName))
            {
                *mInfoLog << "Two transform feedback varyings include the same array element ("
                          << tfVaryingName << ").";
                return false;
            }
        }
        else
        {
            if (uniqueNames.count(tfVaryingName) > 0)
            {
                *mInfoLog << "Two transform feedback varyings specify the same output variable ("
                          << tfVaryingName << ").";
                return false;
            }
        }
        uniqueNames.insert(tfVaryingName);
    }

    // From OpneGLES spec. 11.1.2.1: A program will fail to link if:
    // the count specified by TransformFeedbackVaryings is non-zero, but the
    // program object has no vertex, tessellation evaluation, or geometry shader
    if (mTransformFeedbackVaryingNames.size() > 0 &&
        !gl::ShaderTypeSupportsTransformFeedback(getLinkedTransformFeedbackStage()))
    {
        *mInfoLog << "Linked transform feedback stage " << getLinkedTransformFeedbackStage()
                  << " does not support transform feedback varying.";
        return false;
    }

    // Validate against program varyings.
    size_t totalComponents = 0;
    for (const std::string &tfVaryingName : mTransformFeedbackVaryingNames)
    {
        std::vector<unsigned int> subscripts;
        std::string baseName = ParseResourceName(tfVaryingName, &subscripts);

        const sh::ShaderVariable *var = FindOutputVaryingOrField(varyings, stage, baseName);
        if (var == nullptr)
        {
            *mInfoLog << "Transform feedback varying " << tfVaryingName
                      << " does not exist in the vertex shader.";
            return false;
        }

        // Validate the matching variable.
        if (var->isStruct())
        {
            *mInfoLog << "Struct cannot be captured directly (" << baseName << ").";
            return false;
        }

        size_t elementCount   = 0;
        size_t componentCount = 0;

        if (var->isArray())
        {
            if (clientVersion < Version(3, 1))
            {
                *mInfoLog << "Capture of arrays is undefined and not supported.";
                return false;
            }

            // GLSL ES 3.10 section 4.3.6: A vertex output can't be an array of arrays.
            ASSERT(!var->isArrayOfArrays());

            if (!subscripts.empty() && subscripts[0] >= var->getOutermostArraySize())
            {
                *mInfoLog << "Cannot capture outbound array element '" << tfVaryingName << "'.";
                return false;
            }
            elementCount = (subscripts.empty() ? var->getOutermostArraySize() : 1);
        }
        else
        {
            if (!subscripts.empty())
            {
                *mInfoLog << "Varying '" << baseName
                          << "' is not an array to be captured by element.";
                return false;
            }
            elementCount = 1;
        }

        componentCount = VariableComponentCount(var->type) * elementCount;
        if (mPod.transformFeedbackBufferMode == GL_SEPARATE_ATTRIBS &&
            componentCount > static_cast<GLuint>(caps.maxTransformFeedbackSeparateComponents))
        {
            *mInfoLog << "Transform feedback varying " << tfVaryingName << " components ("
                      << componentCount << ") exceed the maximum separate components ("
                      << caps.maxTransformFeedbackSeparateComponents << ").";
            return false;
        }

        totalComponents += componentCount;
        if (mPod.transformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS &&
            totalComponents > static_cast<GLuint>(caps.maxTransformFeedbackInterleavedComponents))
        {
            *mInfoLog << "Transform feedback varying total components (" << totalComponents
                      << ") exceed the maximum interleaved components ("
                      << caps.maxTransformFeedbackInterleavedComponents << ").";
            return false;
        }
    }
    return true;
}

void ProgramExecutable::gatherTransformFeedbackVaryings(const ProgramMergedVaryings &varyings,
                                                        ShaderType stage)
{
    // Gather the linked varyings that are used for transform feedback, they should all exist.
    mLinkedTransformFeedbackVaryings.clear();
    for (const std::string &tfVaryingName : mTransformFeedbackVaryingNames)
    {
        std::vector<unsigned int> subscripts;
        std::string baseName = ParseResourceName(tfVaryingName, &subscripts);
        size_t subscript     = GL_INVALID_INDEX;
        if (!subscripts.empty())
        {
            subscript = subscripts.back();
        }
        for (const ProgramVaryingRef &ref : varyings)
        {
            if (ref.frontShaderStage != stage)
            {
                continue;
            }

            const sh::ShaderVariable *varying = ref.get(stage);
            if (baseName == varying->name)
            {
                mLinkedTransformFeedbackVaryings.emplace_back(*varying,
                                                              static_cast<GLuint>(subscript));
                break;
            }
            else if (varying->isStruct())
            {
                GLuint fieldIndex = 0;
                const auto *field = varying->findField(tfVaryingName, &fieldIndex);
                if (field != nullptr)
                {
                    mLinkedTransformFeedbackVaryings.emplace_back(*field, *varying);
                    break;
                }
            }
        }
    }
}

void ProgramExecutable::updateTransformFeedbackStrides()
{
    if (mLinkedTransformFeedbackVaryings.empty())
    {
        return;
    }

    if (mPod.transformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS)
    {
        mTransformFeedbackStrides.resize(1);
        size_t totalSize = 0;
        for (const TransformFeedbackVarying &varying : mLinkedTransformFeedbackVaryings)
        {
            totalSize += varying.size() * VariableExternalSize(varying.type);
        }
        mTransformFeedbackStrides[0] = static_cast<GLsizei>(totalSize);
    }
    else
    {
        mTransformFeedbackStrides.resize(mLinkedTransformFeedbackVaryings.size());
        for (size_t i = 0; i < mLinkedTransformFeedbackVaryings.size(); i++)
        {
            TransformFeedbackVarying &varying = mLinkedTransformFeedbackVaryings[i];
            mTransformFeedbackStrides[i] =
                static_cast<GLsizei>(varying.size() * VariableExternalSize(varying.type));
        }
    }
}

bool ProgramExecutable::validateSamplersImpl(const Caps &caps) const
{
    // if any two active samplers in a program are of different types, but refer to the same
    // texture image unit, and this is the current program, then ValidateProgram will fail, and
    // DrawArrays and DrawElements will issue the INVALID_OPERATION error.
    for (size_t textureUnit : mActiveSamplersMask)
    {
        if (mActiveSamplerTypes[textureUnit] == TextureType::InvalidEnum)
        {
            mCachedValidateSamplersResult = false;
            return false;
        }

        if (mActiveSamplerFormats[textureUnit] == SamplerFormat::InvalidEnum)
        {
            mCachedValidateSamplersResult = false;
            return false;
        }
    }

    mCachedValidateSamplersResult = true;
    return true;
}

bool ProgramExecutable::linkValidateOutputVariables(
    const Caps &caps,
    const Version &version,
    GLuint combinedImageUniformsCount,
    GLuint combinedShaderStorageBlocksCount,
    int fragmentShaderVersion,
    const ProgramAliasedBindings &fragmentOutputLocations,
    const ProgramAliasedBindings &fragmentOutputIndices)
{
    ASSERT(mPod.activeOutputVariablesMask.none());
    ASSERT(mPod.activeSecondaryOutputVariablesMask.none());
    ASSERT(mPod.drawBufferTypeMask.none());
    ASSERT(!mPod.hasYUVOutput);

    if (fragmentShaderVersion == 100)
    {
        return gatherOutputTypes();
    }

    // EXT_blend_func_extended doesn't specify anything related to binding specific elements of an
    // output array in explicit terms.
    //
    // Assuming fragData is an output array, you can defend the position that:
    // P1) you must support binding "fragData" because it's specified
    // P2) you must support querying "fragData[x]" because it's specified
    // P3) you must support binding "fragData[0]" because it's a frequently used pattern
    //
    // Then you can make the leap of faith:
    // P4) you must support binding "fragData[x]" because you support "fragData[0]"
    // P5) you must support binding "fragData[x]" because you support querying "fragData[x]"
    //
    // The spec brings in the "world of arrays" when it mentions binding the arrays and the
    // automatic binding. Thus it must be interpreted that the thing is not undefined, rather you
    // must infer the only possible interpretation (?). Note again: this need of interpretation
    // might be completely off of what GL spec logic is.
    //
    // The other complexity is that unless you implement this feature, it's hard to understand what
    // should happen when the client invokes the feature. You cannot add an additional error as it
    // is not specified. One can ignore it, but obviously it creates the discrepancies...

    std::vector<VariableLocation> reservedLocations;

    // Process any output API bindings for arrays that don't alias to the first element.
    for (const auto &bindingPair : fragmentOutputLocations)
    {
        const std::string &name       = bindingPair.first;
        const ProgramBinding &binding = bindingPair.second;

        size_t nameLengthWithoutArrayIndex;
        unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
        if (arrayIndex == 0 || arrayIndex == GL_INVALID_INDEX)
        {
            continue;
        }
        for (unsigned int outputVariableIndex = 0; outputVariableIndex < mOutputVariables.size();
             outputVariableIndex++)
        {
            const ProgramOutput &outputVariable = mOutputVariables[outputVariableIndex];
            // Check that the binding corresponds to an output array and its array index fits.
            if (outputVariable.isBuiltIn() || !outputVariable.isArray() ||
                !angle::BeginsWith(outputVariable.name, name, nameLengthWithoutArrayIndex) ||
                arrayIndex >= outputVariable.getOutermostArraySize())
            {
                continue;
            }

            // Get the API index that corresponds to this exact binding.
            // This index may differ from the index used for the array's base.
            std::vector<VariableLocation> &outputLocations =
                fragmentOutputIndices.getBindingByName(name) == 1 ? mSecondaryOutputLocations
                                                                  : mOutputLocations;
            unsigned int location = binding.location;
            VariableLocation locationInfo(arrayIndex, outputVariableIndex);
            if (location >= outputLocations.size())
            {
                outputLocations.resize(location + 1);
            }
            if (outputLocations[location].used())
            {
                *mInfoLog << "Location of variable " << outputVariable.name
                          << " conflicts with another variable.";
                return false;
            }
            outputLocations[location] = locationInfo;

            // Note the array binding location so that it can be skipped later.
            reservedLocations.push_back(locationInfo);
        }
    }

    // Reserve locations for output variables whose location is fixed in the shader or through the
    // API. Otherwise, the remaining unallocated outputs will be processed later.
    for (unsigned int outputVariableIndex = 0; outputVariableIndex < mOutputVariables.size();
         outputVariableIndex++)
    {
        const ProgramOutput &outputVariable = mOutputVariables[outputVariableIndex];

        // Don't store outputs for gl_FragDepth, gl_FragColor, etc.
        if (outputVariable.isBuiltIn())
            continue;

        int fixedLocation = GetOutputLocationForLink(fragmentOutputLocations, outputVariable);
        if (fixedLocation == -1)
        {
            // Here we're only reserving locations for variables whose location is fixed.
            continue;
        }
        unsigned int baseLocation = static_cast<unsigned int>(fixedLocation);

        std::vector<VariableLocation> &outputLocations =
            IsOutputSecondaryForLink(fragmentOutputIndices, outputVariable)
                ? mSecondaryOutputLocations
                : mOutputLocations;

        // GLSL ES 3.10 section 4.3.6: Output variables cannot be arrays of arrays or arrays of
        // structures, so we may use getBasicTypeElementCount().
        unsigned int elementCount = outputVariable.pod.basicTypeElementCount;
        if (FindUsedOutputLocation(outputLocations, baseLocation, elementCount, reservedLocations,
                                   outputVariableIndex))
        {
            *mInfoLog << "Location of variable " << outputVariable.name
                      << " conflicts with another variable.";
            return false;
        }
        AssignOutputLocations(outputLocations, baseLocation, elementCount, reservedLocations,
                              outputVariableIndex, mOutputVariables[outputVariableIndex]);
    }

    // Here we assign locations for the output variables that don't yet have them. Note that we're
    // not necessarily able to fit the variables optimally, since then we might have to try
    // different arrangements of output arrays. Now we just assign the locations in the order that
    // we got the output variables. The spec isn't clear on what kind of algorithm is required for
    // finding locations for the output variables, so this should be acceptable at least for now.
    GLuint maxLocation = static_cast<GLuint>(caps.maxDrawBuffers);
    if (!mSecondaryOutputLocations.empty())
    {
        // EXT_blend_func_extended: Program outputs will be validated against
        // MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT if there's even one output with index one.
        maxLocation = caps.maxDualSourceDrawBuffers;
    }

    for (unsigned int outputVariableIndex = 0; outputVariableIndex < mOutputVariables.size();
         outputVariableIndex++)
    {
        const ProgramOutput &outputVariable = mOutputVariables[outputVariableIndex];

        // Don't store outputs for gl_FragDepth, gl_FragColor, etc.
        if (outputVariable.isBuiltIn())
            continue;

        int fixedLocation = GetOutputLocationForLink(fragmentOutputLocations, outputVariable);
        std::vector<VariableLocation> &outputLocations =
            IsOutputSecondaryForLink(fragmentOutputIndices, outputVariable)
                ? mSecondaryOutputLocations
                : mOutputLocations;
        unsigned int baseLocation = 0;
        unsigned int elementCount = outputVariable.pod.basicTypeElementCount;
        if (fixedLocation != -1)
        {
            // Secondary inputs might have caused the max location to drop below what has already
            // been explicitly assigned locations. Check for any fixed locations above the max
            // that should cause linking to fail.
            baseLocation = static_cast<unsigned int>(fixedLocation);
        }
        else
        {
            // No fixed location, so try to fit the output in unassigned locations.
            // Try baseLocations starting from 0 one at a time and see if the variable fits.
            while (FindUsedOutputLocation(outputLocations, baseLocation, elementCount,
                                          reservedLocations, outputVariableIndex))
            {
                baseLocation++;
            }
            AssignOutputLocations(outputLocations, baseLocation, elementCount, reservedLocations,
                                  outputVariableIndex, mOutputVariables[outputVariableIndex]);
        }

        // Check for any elements assigned above the max location that are actually used.
        if (baseLocation + elementCount > maxLocation &&
            (baseLocation >= maxLocation ||
             FindUsedOutputLocation(outputLocations, maxLocation,
                                    baseLocation + elementCount - maxLocation, reservedLocations,
                                    outputVariableIndex)))
        {
            // EXT_blend_func_extended: Linking can fail:
            // "if the explicit binding assignments do not leave enough space for the linker to
            // automatically assign a location for a varying out array, which requires multiple
            // contiguous locations."
            *mInfoLog << "Could not fit output variable into available locations: "
                      << outputVariable.name;
            return false;
        }
    }

    if (!gatherOutputTypes())
    {
        return false;
    }

    if (version >= ES_3_1)
    {
        // [OpenGL ES 3.1] Chapter 8.22 Page 203:
        // A link error will be generated if the sum of the number of active image uniforms used in
        // all shaders, the number of active shader storage blocks, and the number of active
        // fragment shader outputs exceeds the implementation-dependent value of
        // MAX_COMBINED_SHADER_OUTPUT_RESOURCES.
        if (combinedImageUniformsCount + combinedShaderStorageBlocksCount +
                mPod.activeOutputVariablesMask.count() >
            static_cast<GLuint>(caps.maxCombinedShaderOutputResources))
        {
            *mInfoLog
                << "The sum of the number of active image uniforms, active shader storage blocks "
                   "and active fragment shader outputs exceeds "
                   "MAX_COMBINED_SHADER_OUTPUT_RESOURCES ("
                << caps.maxCombinedShaderOutputResources << ")";
            return false;
        }
    }

    return true;
}

bool ProgramExecutable::gatherOutputTypes()
{
    for (const ProgramOutput &outputVariable : mOutputVariables)
    {
        if (outputVariable.isBuiltIn() && outputVariable.name != "gl_FragColor" &&
            outputVariable.name != "gl_FragData" &&
            outputVariable.name != "gl_SecondaryFragColorEXT" &&
            outputVariable.name != "gl_SecondaryFragDataEXT")
        {
            continue;
        }

        unsigned int baseLocation = (outputVariable.pod.location == -1
                                         ? 0u
                                         : static_cast<unsigned int>(outputVariable.pod.location));

        const bool secondary =
            outputVariable.pod.index == 1 || (outputVariable.name == "gl_SecondaryFragColorEXT" ||
                                              outputVariable.name == "gl_SecondaryFragDataEXT");

        const ComponentType componentType =
            GLenumToComponentType(VariableComponentType(outputVariable.pod.type));

        // GLSL ES 3.10 section 4.3.6: Output variables cannot be arrays of arrays or arrays of
        // structures, so we may use getBasicTypeElementCount().
        unsigned int elementCount = outputVariable.pod.basicTypeElementCount;
        for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
        {
            const unsigned int location = baseLocation + elementIndex;
            ASSERT(location < mPod.activeOutputVariablesMask.size());
            ASSERT(location < mPod.activeSecondaryOutputVariablesMask.size());
            if (secondary)
            {
                mPod.activeSecondaryOutputVariablesMask.set(location);
            }
            else
            {
                mPod.activeOutputVariablesMask.set(location);
            }
            const ComponentType storedComponentType =
                gl::GetComponentTypeMask(mPod.drawBufferTypeMask, location);
            if (storedComponentType == ComponentType::InvalidEnum)
            {
                SetComponentTypeMask(componentType, location, &mPod.drawBufferTypeMask);
            }
            else if (storedComponentType != componentType)
            {
                *mInfoLog << "Inconsistent component types for fragment outputs at location "
                          << location;
                return false;
            }
        }

        if (outputVariable.pod.yuv)
        {
            ASSERT(mOutputVariables.size() == 1);
            mPod.hasYUVOutput = true;
        }
    }

    return true;
}

bool ProgramExecutable::linkUniforms(
    const Caps &caps,
    const ShaderMap<std::vector<sh::ShaderVariable>> &shaderUniforms,
    const ProgramAliasedBindings &uniformLocationBindings,
    GLuint *combinedImageUniformsCountOut,
    std::vector<UnusedUniform> *unusedUniformsOutOrNull)
{
    UniformLinker linker(mPod.linkedShaderStages, shaderUniforms);
    if (!linker.link(caps, *mInfoLog, uniformLocationBindings))
    {
        return false;
    }

    linker.getResults(&mUniforms, &mUniformNames, &mUniformMappedNames, unusedUniformsOutOrNull,
                      &mUniformLocations);

    linkSamplerAndImageBindings(combinedImageUniformsCountOut);

    if (!linkAtomicCounterBuffers(caps))
    {
        return false;
    }

    return true;
}

void ProgramExecutable::linkSamplerAndImageBindings(GLuint *combinedImageUniforms)
{
    ASSERT(combinedImageUniforms);

    // Iterate over mExecutable->mUniforms from the back, and find the range of subpass inputs,
    // atomic counters, images and samplers in that order.
    auto highIter = mUniforms.rbegin();
    auto lowIter  = highIter;

    unsigned int high = static_cast<unsigned int>(mUniforms.size());
    unsigned int low  = high;

    // Note that uniform block uniforms are not yet appended to this list.
    ASSERT(mUniforms.empty() || highIter->isAtomicCounter() || highIter->isImage() ||
           highIter->isSampler() || highIter->isInDefaultBlock());

    for (; lowIter != mUniforms.rend() && lowIter->isAtomicCounter(); ++lowIter)
    {
        --low;
    }

    mPod.atomicCounterUniformRange = RangeUI(low, high);

    highIter = lowIter;
    high     = low;

    for (; lowIter != mUniforms.rend() && lowIter->isImage(); ++lowIter)
    {
        --low;
    }

    mPod.imageUniformRange = RangeUI(low, high);
    *combinedImageUniforms = 0u;
    // If uniform is a image type, insert it into the mImageBindings array.
    for (unsigned int imageIndex : mPod.imageUniformRange)
    {
        // ES3.1 (section 7.6.1) and GLSL ES3.1 (section 4.4.5), Uniform*i{v} commands
        // cannot load values into a uniform defined as an image. if declare without a
        // binding qualifier, any uniform image variable (include all elements of
        // unbound image array) should be bound to unit zero.
        auto &imageUniform      = mUniforms[imageIndex];
        TextureType textureType = ImageTypeToTextureType(imageUniform.getType());
        const GLuint arraySize  = imageUniform.getBasicTypeElementCount();

        if (imageUniform.getBinding() == -1)
        {
            mImageBindings.emplace_back(
                ImageBinding(imageUniform.getBasicTypeElementCount(), textureType));
        }
        else
        {
            // The arrays of arrays are flattened to arrays, it needs to record the array offset for
            // the correct binding image unit.
            mImageBindings.emplace_back(ImageBinding(
                imageUniform.getBinding() + imageUniform.pod.parentArrayIndex * arraySize,
                imageUniform.getBasicTypeElementCount(), textureType));
        }

        *combinedImageUniforms += imageUniform.activeShaderCount() * arraySize;
    }

    highIter = lowIter;
    high     = low;

    for (; lowIter != mUniforms.rend() && lowIter->isSampler(); ++lowIter)
    {
        --low;
    }

    mPod.samplerUniformRange = RangeUI(low, high);

    // If uniform is a sampler type, insert it into the mSamplerBindings array.
    uint16_t totalCount = 0;
    for (unsigned int samplerIndex : mPod.samplerUniformRange)
    {
        const auto &samplerUniform = mUniforms[samplerIndex];
        TextureType textureType    = SamplerTypeToTextureType(samplerUniform.getType());
        GLenum samplerType         = samplerUniform.getType();
        uint16_t elementCount      = samplerUniform.getBasicTypeElementCount();
        SamplerFormat format       = GetUniformTypeInfo(samplerType).samplerFormat;
        mSamplerBindings.emplace_back(textureType, samplerType, format, totalCount, elementCount);
        totalCount += elementCount;
    }
    mSamplerBoundTextureUnits.resize(totalCount, 0);

    // Whatever is left constitutes the default uniforms.
    mPod.defaultUniformRange = RangeUI(0, low);
}

bool ProgramExecutable::linkAtomicCounterBuffers(const Caps &caps)
{
    for (unsigned int index : mPod.atomicCounterUniformRange)
    {
        auto &uniform = mUniforms[index];

        uniform.pod.blockOffset                    = uniform.getOffset();
        uniform.pod.blockArrayStride               = uniform.isArray() ? 4 : 0;
        uniform.pod.blockMatrixStride              = 0;
        uniform.pod.flagBits.blockIsRowMajorMatrix = false;
        uniform.pod.flagBits.isBlock               = true;

        bool found = false;
        for (size_t bufferIndex = 0; bufferIndex < mAtomicCounterBuffers.size(); ++bufferIndex)
        {
            AtomicCounterBuffer &buffer = mAtomicCounterBuffers[bufferIndex];
            if (buffer.pod.inShaderBinding == uniform.getBinding())
            {
                buffer.memberIndexes.push_back(index);
                SetBitField(uniform.pod.bufferIndex, bufferIndex);
                found = true;
                buffer.unionReferencesWith(uniform);
                break;
            }
        }
        if (!found)
        {
            AtomicCounterBuffer atomicCounterBuffer;
            atomicCounterBuffer.pod.inShaderBinding = uniform.getBinding();
            atomicCounterBuffer.memberIndexes.push_back(index);
            atomicCounterBuffer.unionReferencesWith(uniform);
            mAtomicCounterBuffers.push_back(atomicCounterBuffer);
            SetBitField(uniform.pod.bufferIndex, mAtomicCounterBuffers.size() - 1);
        }
    }

    // Count each atomic counter buffer to validate against
    // per-stage and combined gl_Max*AtomicCounterBuffers.
    GLint combinedShaderACBCount           = 0;
    gl::ShaderMap<GLint> perShaderACBCount = {};
    for (size_t bufferIndex = 0; bufferIndex < mAtomicCounterBuffers.size(); ++bufferIndex)
    {
        AtomicCounterBuffer &acb        = mAtomicCounterBuffers[bufferIndex];
        const ShaderBitSet shaderStages = acb.activeShaders();
        for (gl::ShaderType shaderType : shaderStages)
        {
            ++perShaderACBCount[shaderType];
        }
        ++combinedShaderACBCount;
    }
    if (combinedShaderACBCount > caps.maxCombinedAtomicCounterBuffers)
    {
        *mInfoLog << " combined AtomicCounterBuffers count exceeds limit";
        return false;
    }
    for (gl::ShaderType stage : gl::AllShaderTypes())
    {
        if (perShaderACBCount[stage] > caps.maxShaderAtomicCounterBuffers[stage])
        {
            *mInfoLog << GetShaderTypeString(stage)
                      << " shader AtomicCounterBuffers count exceeds limit";
            return false;
        }
    }
    return true;
}

void ProgramExecutable::copyInputsFromProgram(const ProgramExecutable &executable)
{
    mProgramInputs = executable.getProgramInputs();
}

void ProgramExecutable::copyUniformBuffersFromProgram(
    const ProgramExecutable &executable,
    ShaderType shaderType,
    ProgramUniformBlockArray<GLuint> *ppoUniformBlockMap)
{
    AppendActiveBlocks(shaderType, executable.getUniformBlocks(), mUniformBlocks,
                       ppoUniformBlockMap);

    const std::vector<InterfaceBlock> &blocks = executable.getUniformBlocks();
    for (size_t blockIndex = 0; blockIndex < blocks.size(); ++blockIndex)
    {
        if (!blocks[blockIndex].isActive(shaderType))
        {
            continue;
        }
        const uint32_t blockIndexInPPO = (*ppoUniformBlockMap)[static_cast<uint32_t>(blockIndex)];
        ASSERT(blockIndexInPPO < mUniformBlocks.size());

        // Set the block buffer binding in the PPO to the same binding as the program's.
        remapUniformBlockBinding({blockIndexInPPO}, executable.getUniformBlockBinding(blockIndex));
    }
}

void ProgramExecutable::copyStorageBuffersFromProgram(const ProgramExecutable &executable,
                                                      ShaderType shaderType)
{
    AppendActiveBlocks(shaderType, executable.getShaderStorageBlocks(), mShaderStorageBlocks,
                       nullptr);
    AppendActiveBlocks(shaderType, executable.getAtomicCounterBuffers(), mAtomicCounterBuffers,
                       nullptr);

    // Buffer variable info is queried through the program, and program pipelines don't access it.
    ASSERT(mBufferVariables.empty());
}

void ProgramExecutable::clearSamplerBindings()
{
    mSamplerBindings.clear();
    mSamplerBoundTextureUnits.clear();
}

void ProgramExecutable::copySamplerBindingsFromProgram(const ProgramExecutable &executable)
{
    const std::vector<SamplerBinding> &bindings = executable.getSamplerBindings();
    const std::vector<GLuint> &textureUnits     = executable.getSamplerBoundTextureUnits();
    uint16_t adjustedStartIndex                 = mSamplerBoundTextureUnits.size();
    mSamplerBoundTextureUnits.insert(mSamplerBoundTextureUnits.end(), textureUnits.begin(),
                                     textureUnits.end());
    for (const SamplerBinding &binding : bindings)
    {
        mSamplerBindings.push_back(binding);
        mSamplerBindings.back().textureUnitsStartIndex += adjustedStartIndex;
    }
}

void ProgramExecutable::copyImageBindingsFromProgram(const ProgramExecutable &executable)
{
    const std::vector<ImageBinding> &bindings = executable.getImageBindings();
    mImageBindings.insert(mImageBindings.end(), bindings.begin(), bindings.end());
}

void ProgramExecutable::copyOutputsFromProgram(const ProgramExecutable &executable)
{
    mOutputVariables          = executable.getOutputVariables();
    mOutputLocations          = executable.getOutputLocations();
    mSecondaryOutputLocations = executable.getSecondaryOutputLocations();
}

void ProgramExecutable::copyUniformsFromProgramMap(
    const ShaderMap<SharedProgramExecutable> &executables)
{
    // Merge default uniforms.
    auto getDefaultRange = [](const ProgramExecutable &state) {
        return state.getDefaultUniformRange();
    };
    mPod.defaultUniformRange = AddUniforms(executables, mPod.linkedShaderStages, &mUniforms,
                                           &mUniformNames, &mUniformMappedNames, getDefaultRange);

    // Merge sampler uniforms.
    auto getSamplerRange = [](const ProgramExecutable &state) {
        return state.getSamplerUniformRange();
    };
    mPod.samplerUniformRange = AddUniforms(executables, mPod.linkedShaderStages, &mUniforms,
                                           &mUniformNames, &mUniformMappedNames, getSamplerRange);

    // Merge image uniforms.
    auto getImageRange = [](const ProgramExecutable &state) {
        return state.getImageUniformRange();
    };
    mPod.imageUniformRange = AddUniforms(executables, mPod.linkedShaderStages, &mUniforms,
                                         &mUniformNames, &mUniformMappedNames, getImageRange);

    // Merge atomic counter uniforms.
    auto getAtomicRange = [](const ProgramExecutable &state) {
        return state.getAtomicCounterUniformRange();
    };
    mPod.atomicCounterUniformRange =
        AddUniforms(executables, mPod.linkedShaderStages, &mUniforms, &mUniformNames,
                    &mUniformMappedNames, getAtomicRange);

    // Note: uniforms are set through the program, and the program pipeline never needs it.
    ASSERT(mUniformLocations.empty());
}

void ProgramExecutable::getResourceName(const std::string name,
                                        GLsizei bufSize,
                                        GLsizei *length,
                                        GLchar *dest) const
{
    if (length)
    {
        *length = 0;
    }

    if (bufSize > 0)
    {
        CopyStringToBuffer(dest, name, bufSize, length);
    }
}

GLuint ProgramExecutable::getInputResourceIndex(const GLchar *name) const
{
    const std::string nameString = StripLastArrayIndex(name);

    for (size_t index = 0; index < mProgramInputs.size(); index++)
    {
        if (mProgramInputs[index].name == nameString)
        {
            return static_cast<GLuint>(index);
        }
    }

    return GL_INVALID_INDEX;
}

GLuint ProgramExecutable::getInputResourceMaxNameSize() const
{
    GLint max = 0;

    for (const ProgramInput &resource : mProgramInputs)
    {
        max = GetResourceMaxNameSize(resource, max);
    }

    return max;
}

GLuint ProgramExecutable::getOutputResourceMaxNameSize() const
{
    GLint max = 0;

    for (const gl::ProgramOutput &resource : mOutputVariables)
    {
        max = GetResourceMaxNameSize(resource, max);
    }

    return max;
}

GLuint ProgramExecutable::getInputResourceLocation(const GLchar *name) const
{
    const GLuint index = getInputResourceIndex(name);
    if (index == GL_INVALID_INDEX)
    {
        return index;
    }

    const ProgramInput &variable = getInputResource(index);

    return GetResourceLocation(name, variable, variable.getLocation());
}

GLuint ProgramExecutable::getOutputResourceLocation(const GLchar *name) const
{
    const GLuint index = getOutputResourceIndex(name);
    if (index == GL_INVALID_INDEX)
    {
        return index;
    }

    const gl::ProgramOutput &variable = getOutputResource(index);

    return GetResourceLocation(name, variable, variable.pod.location);
}

GLuint ProgramExecutable::getOutputResourceIndex(const GLchar *name) const
{
    const std::string nameString = StripLastArrayIndex(name);

    for (size_t index = 0; index < mOutputVariables.size(); index++)
    {
        if (mOutputVariables[index].name == nameString)
        {
            return static_cast<GLuint>(index);
        }
    }

    return GL_INVALID_INDEX;
}

void ProgramExecutable::getInputResourceName(GLuint index,
                                             GLsizei bufSize,
                                             GLsizei *length,
                                             GLchar *name) const
{
    getResourceName(getInputResourceName(index), bufSize, length, name);
}

void ProgramExecutable::getOutputResourceName(GLuint index,
                                              GLsizei bufSize,
                                              GLsizei *length,
                                              GLchar *name) const
{
    getResourceName(getOutputResourceName(index), bufSize, length, name);
}

void ProgramExecutable::getUniformResourceName(GLuint index,
                                               GLsizei bufSize,
                                               GLsizei *length,
                                               GLchar *name) const
{
    getResourceName(getUniformNameByIndex(index), bufSize, length, name);
}

void ProgramExecutable::getBufferVariableResourceName(GLuint index,
                                                      GLsizei bufSize,
                                                      GLsizei *length,
                                                      GLchar *name) const
{
    ASSERT(index < mBufferVariables.size());
    getResourceName(mBufferVariables[index].name, bufSize, length, name);
}

const std::string ProgramExecutable::getInputResourceName(GLuint index) const
{
    return GetResourceName(getInputResource(index));
}

const std::string ProgramExecutable::getOutputResourceName(GLuint index) const
{
    return GetResourceName(getOutputResource(index));
}

GLint ProgramExecutable::getFragDataLocation(const std::string &name) const
{
    const GLint primaryLocation = GetVariableLocation(mOutputVariables, mOutputLocations, name);
    if (primaryLocation != -1)
    {
        return primaryLocation;
    }
    return GetVariableLocation(mOutputVariables, mSecondaryOutputLocations, name);
}

GLint ProgramExecutable::getFragDataIndex(const std::string &name) const
{
    if (GetVariableLocation(mOutputVariables, mOutputLocations, name) != -1)
    {
        return 0;
    }
    if (GetVariableLocation(mOutputVariables, mSecondaryOutputLocations, name) != -1)
    {
        return 1;
    }
    return -1;
}

GLsizei ProgramExecutable::getTransformFeedbackVaryingMaxLength() const
{
    GLsizei maxSize = 0;
    for (const TransformFeedbackVarying &var : mLinkedTransformFeedbackVaryings)
    {
        maxSize = std::max(maxSize, static_cast<GLsizei>(var.nameWithArrayIndex().length() + 1));
    }

    return maxSize;
}

GLuint ProgramExecutable::getTransformFeedbackVaryingResourceIndex(const GLchar *name) const
{
    for (GLuint tfIndex = 0; tfIndex < mLinkedTransformFeedbackVaryings.size(); ++tfIndex)
    {
        if (mLinkedTransformFeedbackVaryings[tfIndex].nameWithArrayIndex() == name)
        {
            return tfIndex;
        }
    }
    return GL_INVALID_INDEX;
}

const TransformFeedbackVarying &ProgramExecutable::getTransformFeedbackVaryingResource(
    GLuint index) const
{
    ASSERT(index < mLinkedTransformFeedbackVaryings.size());
    return mLinkedTransformFeedbackVaryings[index];
}

void ProgramExecutable::getTransformFeedbackVarying(GLuint index,
                                                    GLsizei bufSize,
                                                    GLsizei *length,
                                                    GLsizei *size,
                                                    GLenum *type,
                                                    GLchar *name) const
{
    if (mLinkedTransformFeedbackVaryings.empty())
    {
        // Program is not successfully linked
        return;
    }

    ASSERT(index < mLinkedTransformFeedbackVaryings.size());
    const auto &var     = mLinkedTransformFeedbackVaryings[index];
    std::string varName = var.nameWithArrayIndex();
    GLsizei lastNameIdx = std::min(bufSize - 1, static_cast<GLsizei>(varName.length()));
    if (length)
    {
        *length = lastNameIdx;
    }
    if (size)
    {
        *size = var.size();
    }
    if (type)
    {
        *type = var.type;
    }
    if (name)
    {
        memcpy(name, varName.c_str(), lastNameIdx);
        name[lastNameIdx] = '\0';
    }
}

void ProgramExecutable::getActiveAttribute(GLuint index,
                                           GLsizei bufsize,
                                           GLsizei *length,
                                           GLint *size,
                                           GLenum *type,
                                           GLchar *name) const
{
    if (mProgramInputs.empty())
    {
        // Program is not successfully linked
        if (bufsize > 0)
        {
            name[0] = '\0';
        }

        if (length)
        {
            *length = 0;
        }

        *type = GL_NONE;
        *size = 1;
        return;
    }

    ASSERT(index < mProgramInputs.size());
    const ProgramInput &attrib = mProgramInputs[index];

    if (bufsize > 0)
    {
        CopyStringToBuffer(name, attrib.name, bufsize, length);
    }

    // Always a single 'type' instance
    *size = 1;
    *type = attrib.getType();
}

GLint ProgramExecutable::getActiveAttributeMaxLength() const
{
    size_t maxLength = 0;

    for (const ProgramInput &attrib : mProgramInputs)
    {
        maxLength = std::max(attrib.name.length() + 1, maxLength);
    }

    return static_cast<GLint>(maxLength);
}

GLuint ProgramExecutable::getAttributeLocation(const std::string &name) const
{
    for (const ProgramInput &attribute : mProgramInputs)
    {
        if (attribute.name == name)
        {
            return attribute.getLocation();
        }
    }

    return static_cast<GLuint>(-1);
}

void ProgramExecutable::getActiveUniform(GLuint index,
                                         GLsizei bufsize,
                                         GLsizei *length,
                                         GLint *size,
                                         GLenum *type,
                                         GLchar *name) const
{
    if (mUniforms.empty())
    {
        // Program is not successfully linked
        if (bufsize > 0)
        {
            name[0] = '\0';
        }

        if (length)
        {
            *length = 0;
        }

        *size = 0;
        *type = GL_NONE;
    }

    ASSERT(index < mUniforms.size());
    const LinkedUniform &uniform = mUniforms[index];

    if (bufsize > 0)
    {
        const std::string &string = getUniformNameByIndex(index);
        CopyStringToBuffer(name, string, bufsize, length);
    }

    *size = clampCast<GLint>(uniform.getBasicTypeElementCount());
    *type = uniform.getType();
}

GLint ProgramExecutable::getActiveUniformMaxLength() const
{
    size_t maxLength = 0;

    for (GLuint index = 0; index < static_cast<size_t>(mUniformNames.size()); index++)
    {
        const std::string &uniformName = getUniformNameByIndex(index);
        if (!uniformName.empty())
        {
            size_t length = uniformName.length() + 1u;
            if (getUniformByIndex(index).isArray())
            {
                length += 3;  // Counting in "[0]".
            }
            maxLength = std::max(length, maxLength);
        }
    }

    return static_cast<GLint>(maxLength);
}

bool ProgramExecutable::isValidUniformLocation(UniformLocation location) const
{
    ASSERT(angle::IsValueInRangeForNumericType<GLint>(mUniformLocations.size()));
    return location.value >= 0 && static_cast<size_t>(location.value) < mUniformLocations.size() &&
           mUniformLocations[location.value].used();
}

const LinkedUniform &ProgramExecutable::getUniformByLocation(UniformLocation location) const
{
    ASSERT(location.value >= 0 && static_cast<size_t>(location.value) < mUniformLocations.size());
    return mUniforms[getUniformIndexFromLocation(location)];
}

const VariableLocation &ProgramExecutable::getUniformLocation(UniformLocation location) const
{
    ASSERT(location.value >= 0 && static_cast<size_t>(location.value) < mUniformLocations.size());
    return mUniformLocations[location.value];
}

UniformLocation ProgramExecutable::getUniformLocation(const std::string &name) const
{
    return {GetUniformLocation(mUniforms, mUniformNames, mUniformLocations, name)};
}

GLuint ProgramExecutable::getUniformIndex(const std::string &name) const
{
    return getUniformIndexFromName(name);
}

bool ProgramExecutable::shouldIgnoreUniform(UniformLocation location) const
{
    // Casting to size_t will convert negative values to large positive avoiding double check.
    // Adding ERR() log to report out of bound location harms performance on Android.
    return ANGLE_UNLIKELY(static_cast<size_t>(location.value) >= mUniformLocations.size() ||
                          mUniformLocations[location.value].ignored);
}

GLuint ProgramExecutable::getUniformIndexFromName(const std::string &name) const
{
    return GetUniformIndexFromName(mUniforms, mUniformNames, name);
}

GLuint ProgramExecutable::getBufferVariableIndexFromName(const std::string &name) const
{
    return GetResourceIndexFromName(mBufferVariables, name);
}

GLuint ProgramExecutable::getUniformIndexFromLocation(UniformLocation location) const
{
    ASSERT(location.value >= 0 && static_cast<size_t>(location.value) < mUniformLocations.size());
    return mUniformLocations[location.value].index;
}

Optional<GLuint> ProgramExecutable::getSamplerIndex(UniformLocation location) const
{
    GLuint index = getUniformIndexFromLocation(location);
    if (!isSamplerUniformIndex(index))
    {
        return Optional<GLuint>::Invalid();
    }

    return getSamplerIndexFromUniformIndex(index);
}

bool ProgramExecutable::isSamplerUniformIndex(GLuint index) const
{
    return mPod.samplerUniformRange.contains(index);
}

GLuint ProgramExecutable::getSamplerIndexFromUniformIndex(GLuint uniformIndex) const
{
    ASSERT(isSamplerUniformIndex(uniformIndex));
    return uniformIndex - mPod.samplerUniformRange.low();
}

bool ProgramExecutable::isImageUniformIndex(GLuint index) const
{
    return mPod.imageUniformRange.contains(index);
}

GLuint ProgramExecutable::getImageIndexFromUniformIndex(GLuint uniformIndex) const
{
    ASSERT(isImageUniformIndex(uniformIndex));
    return uniformIndex - mPod.imageUniformRange.low();
}

void ProgramExecutable::getActiveUniformBlockName(const Context *context,
                                                  const UniformBlockIndex blockIndex,
                                                  GLsizei bufSize,
                                                  GLsizei *length,
                                                  GLchar *blockName) const
{
    GetInterfaceBlockName(blockIndex, mUniformBlocks, bufSize, length, blockName);
}

void ProgramExecutable::getActiveShaderStorageBlockName(const GLuint blockIndex,
                                                        GLsizei bufSize,
                                                        GLsizei *length,
                                                        GLchar *blockName) const
{
    GetInterfaceBlockName({blockIndex}, mShaderStorageBlocks, bufSize, length, blockName);
}

GLint ProgramExecutable::getActiveUniformBlockMaxNameLength() const
{
    return GetActiveInterfaceBlockMaxNameLength(mUniformBlocks);
}

GLint ProgramExecutable::getActiveShaderStorageBlockMaxNameLength() const
{
    return GetActiveInterfaceBlockMaxNameLength(mShaderStorageBlocks);
}

GLuint ProgramExecutable::getUniformBlockIndex(const std::string &name) const
{
    return GetInterfaceBlockIndex(mUniformBlocks, name);
}

GLuint ProgramExecutable::getShaderStorageBlockIndex(const std::string &name) const
{
    return GetInterfaceBlockIndex(mShaderStorageBlocks, name);
}

GLuint ProgramExecutable::getSamplerUniformBinding(const VariableLocation &uniformLocation) const
{
    GLuint samplerIndex                  = getSamplerIndexFromUniformIndex(uniformLocation.index);
    const SamplerBinding &samplerBinding = mSamplerBindings[samplerIndex];
    if (uniformLocation.arrayIndex >= samplerBinding.textureUnitsCount)
    {
        return 0;
    }

    const std::vector<GLuint> &boundTextureUnits = mSamplerBoundTextureUnits;
    return samplerBinding.getTextureUnit(boundTextureUnits, uniformLocation.arrayIndex);
}

GLuint ProgramExecutable::getImageUniformBinding(const VariableLocation &uniformLocation) const
{
    GLuint imageIndex = getImageIndexFromUniformIndex(uniformLocation.index);

    const std::vector<GLuint> &boundImageUnits = mImageBindings[imageIndex].boundImageUnits;
    return boundImageUnits[uniformLocation.arrayIndex];
}

template <typename UniformT,
          GLint UniformSize,
          void (rx::ProgramExecutableImpl::*SetUniformFunc)(GLint, GLsizei, const UniformT *)>
void ProgramExecutable::setUniformGeneric(UniformLocation location,
                                          GLsizei count,
                                          const UniformT *v)
{
    if (shouldIgnoreUniform(location))
    {
        return;
    }

    const VariableLocation &locationInfo = mUniformLocations[location.value];
    GLsizei clampedCount                 = clampUniformCount(locationInfo, count, UniformSize, v);
    (mImplementation->*SetUniformFunc)(location.value, clampedCount, v);
}

void ProgramExecutable::setUniform1fv(UniformLocation location, GLsizei count, const GLfloat *v)
{
    setUniformGeneric<GLfloat, 1, &rx::ProgramExecutableImpl::setUniform1fv>(location, count, v);
}

void ProgramExecutable::setUniform2fv(UniformLocation location, GLsizei count, const GLfloat *v)
{
    setUniformGeneric<GLfloat, 2, &rx::ProgramExecutableImpl::setUniform2fv>(location, count, v);
}

void ProgramExecutable::setUniform3fv(UniformLocation location, GLsizei count, const GLfloat *v)
{
    setUniformGeneric<GLfloat, 3, &rx::ProgramExecutableImpl::setUniform3fv>(location, count, v);
}

void ProgramExecutable::setUniform4fv(UniformLocation location, GLsizei count, const GLfloat *v)
{
    setUniformGeneric<GLfloat, 4, &rx::ProgramExecutableImpl::setUniform4fv>(location, count, v);
}

void ProgramExecutable::setUniform1iv(Context *context,
                                      UniformLocation location,
                                      GLsizei count,
                                      const GLint *v)
{
    if (shouldIgnoreUniform(location))
    {
        return;
    }

    const VariableLocation &locationInfo = mUniformLocations[location.value];
    GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 1, v);

    mImplementation->setUniform1iv(location.value, clampedCount, v);

    if (isSamplerUniformIndex(locationInfo.index))
    {
        updateSamplerUniform(context, locationInfo, clampedCount, v);
    }
}

void ProgramExecutable::setUniform2iv(UniformLocation location, GLsizei count, const GLint *v)
{
    setUniformGeneric<GLint, 2, &rx::ProgramExecutableImpl::setUniform2iv>(location, count, v);
}

void ProgramExecutable::setUniform3iv(UniformLocation location, GLsizei count, const GLint *v)
{
    setUniformGeneric<GLint, 3, &rx::ProgramExecutableImpl::setUniform3iv>(location, count, v);
}

void ProgramExecutable::setUniform4iv(UniformLocation location, GLsizei count, const GLint *v)
{
    setUniformGeneric<GLint, 4, &rx::ProgramExecutableImpl::setUniform4iv>(location, count, v);
}

void ProgramExecutable::setUniform1uiv(UniformLocation location, GLsizei count, const GLuint *v)
{
    setUniformGeneric<GLuint, 1, &rx::ProgramExecutableImpl::setUniform1uiv>(location, count, v);
}

void ProgramExecutable::setUniform2uiv(UniformLocation location, GLsizei count, const GLuint *v)
{
    setUniformGeneric<GLuint, 2, &rx::ProgramExecutableImpl::setUniform2uiv>(location, count, v);
}

void ProgramExecutable::setUniform3uiv(UniformLocation location, GLsizei count, const GLuint *v)
{
    setUniformGeneric<GLuint, 3, &rx::ProgramExecutableImpl::setUniform3uiv>(location, count, v);
}

void ProgramExecutable::setUniform4uiv(UniformLocation location, GLsizei count, const GLuint *v)
{
    setUniformGeneric<GLuint, 4, &rx::ProgramExecutableImpl::setUniform4uiv>(location, count, v);
}

template <typename UniformT,
          GLint MatrixC,
          GLint MatrixR,
          void (rx::ProgramExecutableImpl::*
                    SetUniformMatrixFunc)(GLint, GLsizei, GLboolean, const UniformT *)>
void ProgramExecutable::setUniformMatrixGeneric(UniformLocation location,
                                                GLsizei count,
                                                GLboolean transpose,
                                                const UniformT *v)
{
    if (shouldIgnoreUniform(location))
    {
        return;
    }

    GLsizei clampedCount = clampMatrixUniformCount<MatrixC, MatrixR>(location, count, transpose, v);
    (mImplementation->*SetUniformMatrixFunc)(location.value, clampedCount, transpose, v);
}

void ProgramExecutable::setUniformMatrix2fv(UniformLocation location,
                                            GLsizei count,
                                            GLboolean transpose,
                                            const GLfloat *v)
{
    setUniformMatrixGeneric<GLfloat, 2, 2, &rx::ProgramExecutableImpl::setUniformMatrix2fv>(
        location, count, transpose, v);
}

void ProgramExecutable::setUniformMatrix3fv(UniformLocation location,
                                            GLsizei count,
                                            GLboolean transpose,
                                            const GLfloat *v)
{
    setUniformMatrixGeneric<GLfloat, 3, 3, &rx::ProgramExecutableImpl::setUniformMatrix3fv>(
        location, count, transpose, v);
}

void ProgramExecutable::setUniformMatrix4fv(UniformLocation location,
                                            GLsizei count,
                                            GLboolean transpose,
                                            const GLfloat *v)
{
    setUniformMatrixGeneric<GLfloat, 4, 4, &rx::ProgramExecutableImpl::setUniformMatrix4fv>(
        location, count, transpose, v);
}

void ProgramExecutable::setUniformMatrix2x3fv(UniformLocation location,
                                              GLsizei count,
                                              GLboolean transpose,
                                              const GLfloat *v)
{
    setUniformMatrixGeneric<GLfloat, 2, 3, &rx::ProgramExecutableImpl::setUniformMatrix2x3fv>(
        location, count, transpose, v);
}

void ProgramExecutable::setUniformMatrix2x4fv(UniformLocation location,
                                              GLsizei count,
                                              GLboolean transpose,
                                              const GLfloat *v)
{
    setUniformMatrixGeneric<GLfloat, 2, 4, &rx::ProgramExecutableImpl::setUniformMatrix2x4fv>(
        location, count, transpose, v);
}

void ProgramExecutable::setUniformMatrix3x2fv(UniformLocation location,
                                              GLsizei count,
                                              GLboolean transpose,
                                              const GLfloat *v)
{
    setUniformMatrixGeneric<GLfloat, 3, 2, &rx::ProgramExecutableImpl::setUniformMatrix3x2fv>(
        location, count, transpose, v);
}

void ProgramExecutable::setUniformMatrix3x4fv(UniformLocation location,
                                              GLsizei count,
                                              GLboolean transpose,
                                              const GLfloat *v)
{
    setUniformMatrixGeneric<GLfloat, 3, 4, &rx::ProgramExecutableImpl::setUniformMatrix3x4fv>(
        location, count, transpose, v);
}

void ProgramExecutable::setUniformMatrix4x2fv(UniformLocation location,
                                              GLsizei count,
                                              GLboolean transpose,
                                              const GLfloat *v)
{
    setUniformMatrixGeneric<GLfloat, 4, 2, &rx::ProgramExecutableImpl::setUniformMatrix4x2fv>(
        location, count, transpose, v);
}

void ProgramExecutable::setUniformMatrix4x3fv(UniformLocation location,
                                              GLsizei count,
                                              GLboolean transpose,
                                              const GLfloat *v)
{
    setUniformMatrixGeneric<GLfloat, 4, 3, &rx::ProgramExecutableImpl::setUniformMatrix4x3fv>(
        location, count, transpose, v);
}

void ProgramExecutable::getUniformfv(const Context *context,
                                     UniformLocation location,
                                     GLfloat *v) const
{
    const VariableLocation &uniformLocation = mUniformLocations[location.value];
    const LinkedUniform &uniform            = mUniforms[uniformLocation.index];

    if (uniform.isSampler())
    {
        *v = static_cast<GLfloat>(getSamplerUniformBinding(uniformLocation));
        return;
    }
    else if (uniform.isImage())
    {
        *v = static_cast<GLfloat>(getImageUniformBinding(uniformLocation));
        return;
    }

    const GLenum nativeType = VariableComponentType(uniform.getType());
    if (nativeType == GL_FLOAT)
    {
        mImplementation->getUniformfv(context, location.value, v);
    }
    else
    {
        getUniformInternal(context, v, location, nativeType,
                           VariableComponentCount(uniform.getType()));
    }
}

void ProgramExecutable::getUniformiv(const Context *context,
                                     UniformLocation location,
                                     GLint *v) const
{
    const VariableLocation &uniformLocation = mUniformLocations[location.value];
    const LinkedUniform &uniform            = mUniforms[uniformLocation.index];

    if (uniform.isSampler())
    {
        *v = static_cast<GLint>(getSamplerUniformBinding(uniformLocation));
        return;
    }
    else if (uniform.isImage())
    {
        *v = static_cast<GLint>(getImageUniformBinding(uniformLocation));
        return;
    }

    const GLenum nativeType = VariableComponentType(uniform.getType());
    if (nativeType == GL_INT || nativeType == GL_BOOL)
    {
        mImplementation->getUniformiv(context, location.value, v);
    }
    else
    {
        getUniformInternal(context, v, location, nativeType,
                           VariableComponentCount(uniform.getType()));
    }
}

void ProgramExecutable::getUniformuiv(const Context *context,
                                      UniformLocation location,
                                      GLuint *v) const
{
    const VariableLocation &uniformLocation = mUniformLocations[location.value];
    const LinkedUniform &uniform            = mUniforms[uniformLocation.index];

    if (uniform.isSampler())
    {
        *v = getSamplerUniformBinding(uniformLocation);
        return;
    }
    else if (uniform.isImage())
    {
        *v = getImageUniformBinding(uniformLocation);
        return;
    }

    const GLenum nativeType = VariableComponentType(uniform.getType());
    if (nativeType == GL_UNSIGNED_INT)
    {
        mImplementation->getUniformuiv(context, location.value, v);
    }
    else
    {
        getUniformInternal(context, v, location, nativeType,
                           VariableComponentCount(uniform.getType()));
    }
}

void ProgramExecutable::initInterfaceBlockBindings()
{
    // Set initial bindings from shader.
    for (size_t blockIndex = 0; blockIndex < mUniformBlocks.size(); blockIndex++)
    {
        InterfaceBlock &uniformBlock = mUniformBlocks[blockIndex];
        // All interface blocks either have |binding| defined, or default to binding 0.
        ASSERT(uniformBlock.pod.inShaderBinding >= 0);
        remapUniformBlockBinding({static_cast<uint32_t>(blockIndex)},
                                 uniformBlock.pod.inShaderBinding);

        // This is called on program link/binary, which means the executable has changed.  There is
        // no need to send any additional notifications to the contexts (where the program may be
        // current) or program pipeline objects (that have this program attached), because they
        // already assume all blocks are dirty.
    }
}

void ProgramExecutable::remapUniformBlockBinding(UniformBlockIndex uniformBlockIndex,
                                                 GLuint uniformBlockBinding)
{
    // Remove previous binding
    const GLuint previousBinding = mUniformBlockIndexToBufferBinding[uniformBlockIndex.value];
    mUniformBufferBindingToUniformBlocks[previousBinding].reset(uniformBlockIndex.value);

    // Set new binding
    mUniformBlockIndexToBufferBinding[uniformBlockIndex.value] = uniformBlockBinding;
    mUniformBufferBindingToUniformBlocks[uniformBlockBinding].set(uniformBlockIndex.value);
}

void ProgramExecutable::setUniformValuesFromBindingQualifiers()
{
    for (unsigned int samplerIndex : mPod.samplerUniformRange)
    {
        const auto &samplerUniform = mUniforms[samplerIndex];
        if (samplerUniform.getBinding() != -1)
        {
            const std::string &uniformName = getUniformNameByIndex(samplerIndex);
            UniformLocation location       = getUniformLocation(uniformName);
            ASSERT(location.value != -1);
            std::vector<GLint> boundTextureUnits;
            for (unsigned int elementIndex = 0;
                 elementIndex < samplerUniform.getBasicTypeElementCount(); ++elementIndex)
            {
                boundTextureUnits.push_back(samplerUniform.getBinding() + elementIndex);
            }

            // Here we pass nullptr to avoid a large chain of calls that need a non-const Context.
            // We know it's safe not to notify the Context because this is only called after link.
            setUniform1iv(nullptr, location, static_cast<GLsizei>(boundTextureUnits.size()),
                          boundTextureUnits.data());
        }
    }
}

template <typename T>
GLsizei ProgramExecutable::clampUniformCount(const VariableLocation &locationInfo,
                                             GLsizei count,
                                             int vectorSize,
                                             const T *v)
{
    if (count == 1)
        return 1;

    const LinkedUniform &linkedUniform = mUniforms[locationInfo.index];

    // OpenGL ES 3.0.4 spec pg 67: "Values for any array element that exceeds the highest array
    // element index used, as reported by GetActiveUniform, will be ignored by the GL."
    unsigned int remainingElements =
        linkedUniform.getBasicTypeElementCount() - locationInfo.arrayIndex;
    GLsizei maxElementCount =
        static_cast<GLsizei>(remainingElements * linkedUniform.getElementComponents());

    if (count * vectorSize > maxElementCount)
    {
        return maxElementCount / vectorSize;
    }

    return count;
}

template <size_t cols, size_t rows, typename T>
GLsizei ProgramExecutable::clampMatrixUniformCount(UniformLocation location,
                                                   GLsizei count,
                                                   GLboolean transpose,
                                                   const T *v)
{
    const VariableLocation &locationInfo = mUniformLocations[location.value];

    if (!transpose)
    {
        return clampUniformCount(locationInfo, count, cols * rows, v);
    }

    const LinkedUniform &linkedUniform = mUniforms[locationInfo.index];

    // OpenGL ES 3.0.4 spec pg 67: "Values for any array element that exceeds the highest array
    // element index used, as reported by GetActiveUniform, will be ignored by the GL."
    unsigned int remainingElements =
        linkedUniform.getBasicTypeElementCount() - locationInfo.arrayIndex;
    return std::min(count, static_cast<GLsizei>(remainingElements));
}

void ProgramExecutable::updateSamplerUniform(Context *context,
                                             const VariableLocation &locationInfo,
                                             GLsizei clampedCount,
                                             const GLint *v)
{
    ASSERT(isSamplerUniformIndex(locationInfo.index));
    GLuint samplerIndex                    = getSamplerIndexFromUniformIndex(locationInfo.index);
    SamplerBinding &samplerBinding         = mSamplerBindings[samplerIndex];
    std::vector<GLuint> &boundTextureUnits = mSamplerBoundTextureUnits;

    if (locationInfo.arrayIndex >= samplerBinding.textureUnitsCount)
    {
        return;
    }
    GLsizei safeUniformCount =
        std::min(clampedCount,
                 static_cast<GLsizei>(samplerBinding.textureUnitsCount - locationInfo.arrayIndex));

    // Update the sampler uniforms.
    for (uint16_t arrayIndex = 0; arrayIndex < safeUniformCount; ++arrayIndex)
    {
        GLint oldTextureUnit =
            samplerBinding.getTextureUnit(boundTextureUnits, arrayIndex + locationInfo.arrayIndex);
        GLint newTextureUnit = v[arrayIndex];

        if (oldTextureUnit == newTextureUnit)
        {
            continue;
        }

        // Update sampler's bound textureUnit
        boundTextureUnits[samplerBinding.textureUnitsStartIndex + arrayIndex +
                          locationInfo.arrayIndex] = newTextureUnit;

        // Update the reference counts.
        uint32_t &oldRefCount = mActiveSamplerRefCounts[oldTextureUnit];
        uint32_t &newRefCount = mActiveSamplerRefCounts[newTextureUnit];
        ASSERT(oldRefCount > 0);
        ASSERT(newRefCount < std::numeric_limits<uint32_t>::max());
        oldRefCount--;
        newRefCount++;

        // Check for binding type change.
        TextureType newSamplerType     = mActiveSamplerTypes[newTextureUnit];
        TextureType oldSamplerType     = mActiveSamplerTypes[oldTextureUnit];
        SamplerFormat newSamplerFormat = mActiveSamplerFormats[newTextureUnit];
        SamplerFormat oldSamplerFormat = mActiveSamplerFormats[oldTextureUnit];
        bool newSamplerYUV             = mActiveSamplerYUV.test(newTextureUnit);

        if (newRefCount == 1)
        {
            setActive(newTextureUnit, samplerBinding, mUniforms[locationInfo.index]);
        }
        else
        {
            if (newSamplerType != samplerBinding.textureType ||
                newSamplerYUV != IsSamplerYUVType(samplerBinding.samplerType))
            {
                hasSamplerTypeConflict(newTextureUnit);
            }

            if (newSamplerFormat != samplerBinding.format)
            {
                hasSamplerFormatConflict(newTextureUnit);
            }
        }

        // Unset previously active sampler.
        if (oldRefCount == 0)
        {
            setInactive(oldTextureUnit);
        }
        else
        {
            if (oldSamplerType == TextureType::InvalidEnum ||
                oldSamplerFormat == SamplerFormat::InvalidEnum)
            {
                // Previous conflict. Check if this new change fixed the conflict.
                setSamplerUniformTextureTypeAndFormat(oldTextureUnit);
            }
        }

        // Update the observing PPO's executable, if any.
        // Do this before any of the Context work, since that uses the current ProgramExecutable,
        // which will be the PPO's if this Program is bound to it, rather than this Program's.
        if (mPod.isSeparable)
        {
            onStateChange(angle::SubjectMessage::ProgramTextureOrImageBindingChanged);
        }

        // Notify context.
        if (context)
        {
            context->onSamplerUniformChange(newTextureUnit);
            context->onSamplerUniformChange(oldTextureUnit);
        }
    }

    // Invalidate the validation cache.
    resetCachedValidateSamplersResult();
    // Inform any PPOs this Program may be bound to.
    onStateChange(angle::SubjectMessage::SamplerUniformsUpdated);
}

// Driver differences mean that doing the uniform value cast ourselves gives consistent results.
// EG: on NVIDIA drivers, it was observed that getUniformi for MAX_INT+1 returned MIN_INT.
template <typename DestT>
void ProgramExecutable::getUniformInternal(const Context *context,
                                           DestT *dataOut,
                                           UniformLocation location,
                                           GLenum nativeType,
                                           int components) const
{
    switch (nativeType)
    {
        case GL_BOOL:
        {
            GLint tempValue[16] = {0};
            mImplementation->getUniformiv(context, location.value, tempValue);
            UniformStateQueryCastLoop<GLboolean>(
                dataOut, reinterpret_cast<const uint8_t *>(tempValue), components);
            break;
        }
        case GL_INT:
        {
            GLint tempValue[16] = {0};
            mImplementation->getUniformiv(context, location.value, tempValue);
            UniformStateQueryCastLoop<GLint>(dataOut, reinterpret_cast<const uint8_t *>(tempValue),
                                             components);
            break;
        }
        case GL_UNSIGNED_INT:
        {
            GLuint tempValue[16] = {0};
            mImplementation->getUniformuiv(context, location.value, tempValue);
            UniformStateQueryCastLoop<GLuint>(dataOut, reinterpret_cast<const uint8_t *>(tempValue),
                                              components);
            break;
        }
        case GL_FLOAT:
        {
            GLfloat tempValue[16] = {0};
            mImplementation->getUniformfv(context, location.value, tempValue);
            UniformStateQueryCastLoop<GLfloat>(
                dataOut, reinterpret_cast<const uint8_t *>(tempValue), components);
            break;
        }
        default:
            UNREACHABLE();
            break;
    }
}

void ProgramExecutable::setDrawIDUniform(GLint drawid)
{
    ASSERT(hasDrawIDUniform());
    mImplementation->setUniform1iv(mPod.drawIDLocation, 1, &drawid);
}

void ProgramExecutable::setBaseVertexUniform(GLint baseVertex)
{
    ASSERT(hasBaseVertexUniform());
    if (baseVertex == mCachedBaseVertex)
    {
        return;
    }
    mCachedBaseVertex = baseVertex;
    mImplementation->setUniform1iv(mPod.baseVertexLocation, 1, &baseVertex);
}

void ProgramExecutable::setBaseInstanceUniform(GLuint baseInstance)
{
    ASSERT(hasBaseInstanceUniform());
    if (baseInstance == mCachedBaseInstance)
    {
        return;
    }
    mCachedBaseInstance   = baseInstance;
    GLint baseInstanceInt = baseInstance;
    mImplementation->setUniform1iv(mPod.baseInstanceLocation, 1, &baseInstanceInt);
}

void ProgramExecutable::waitForPostLinkTasks(const Context *context)
{
    if (mPostLinkSubTasks.empty())
    {
        return;
    }

    mImplementation->waitForPostLinkTasks(context);

    // Implementation is expected to call |onPostLinkTasksComplete|.
    ASSERT(mPostLinkSubTasks.empty());
}

void InstallExecutable(const Context *context,
                       const SharedProgramExecutable &toInstall,
                       SharedProgramExecutable *executable)
{
    // There should never be a need to re-install the same executable.
    ASSERT(toInstall.get() != executable->get());

    // Destroy the old executable before it gets deleted.
    UninstallExecutable(context, executable);

    // Install the new executable.
    *executable = toInstall;
}

void UninstallExecutable(const Context *context, SharedProgramExecutable *executable)
{
    if (executable->use_count() == 1)
    {
        (*executable)->destroy(context);
    }

    executable->reset();
}

}  // namespace gl
