//
// 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"

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)
{
    memset(&mPod, 0, sizeof(mPod));
    reset();
}

ProgramExecutable::~ProgramExecutable()
{
    ASSERT(mImplementation == nullptr);
}

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

    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();
}

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
{
    if (location.value < 0)
    {
        return true;
    }

    if (static_cast<size_t>(location.value) >= mUniformLocations.size())
    {
        ERR() << "Invalid uniform location " << location.value << ", expected [0, "
              << mUniformLocations.size() << ")";
        return true;
    }

    return 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);
    onStateChange(angle::SubjectMessage::ProgramUniformUpdated);
}

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);
    }
    else
    {
        onStateChange(angle::SubjectMessage::ProgramUniformUpdated);
    }
}

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);
    onStateChange(angle::SubjectMessage::ProgramUniformUpdated);
}

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 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
