//
// 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.h: Collects the information and interfaces common to both Programs and
// ProgramPipelines in order to execute/draw with either.

#ifndef LIBANGLE_PROGRAMEXECUTABLE_H_
#define LIBANGLE_PROGRAMEXECUTABLE_H_

#include "common/BinaryStream.h"
#include "libANGLE/Caps.h"
#include "libANGLE/InfoLog.h"
#include "libANGLE/ProgramLinkedResources.h"
#include "libANGLE/Shader.h"
#include "libANGLE/Uniform.h"
#include "libANGLE/VaryingPacking.h"
#include "libANGLE/angletypes.h"

namespace rx
{
class GLImplFactory;
class LinkSubTask;
class ProgramExecutableImpl;
}  // namespace rx

namespace gl
{

// This small structure encapsulates binding sampler uniforms to active GL textures.
ANGLE_ENABLE_STRUCT_PADDING_WARNINGS
struct SamplerBinding
{
    SamplerBinding() = default;
    SamplerBinding(TextureType textureTypeIn,
                   GLenum samplerTypeIn,
                   SamplerFormat formatIn,
                   uint16_t startIndex,
                   uint16_t elementCount)
        : textureType(textureTypeIn),
          format(formatIn),
          textureUnitsStartIndex(startIndex),
          textureUnitsCount(elementCount)
    {
        SetBitField(samplerType, samplerTypeIn);
    }

    GLuint getTextureUnit(const std::vector<GLuint> &boundTextureUnits,
                          unsigned int arrayIndex) const
    {
        return boundTextureUnits[textureUnitsStartIndex + arrayIndex];
    }

    // Necessary for retrieving active textures from the GL state.
    TextureType textureType;
    SamplerFormat format;
    uint16_t samplerType;
    // [textureUnitsStartIndex, textureUnitsStartIndex+textureUnitsCount) Points to the subset in
    // mSamplerBoundTextureUnits that stores the texture unit bound to this sampler. Cropped by the
    // amount of unused elements reported by the driver.
    uint16_t textureUnitsStartIndex;
    uint16_t textureUnitsCount;
};
ANGLE_DISABLE_STRUCT_PADDING_WARNINGS

struct ImageBinding
{
    ImageBinding() = default;
    ImageBinding(size_t count, TextureType textureTypeIn)
        : textureType(textureTypeIn), boundImageUnits(count, 0)
    {}
    ImageBinding(GLuint imageUnit, size_t count, TextureType textureTypeIn);

    // Necessary for distinguishing between textures with images and texture buffers.
    TextureType textureType;

    // List of all textures bound.
    // Cropped by the amount of unused elements reported by the driver.
    std::vector<GLuint> boundImageUnits;
};

ANGLE_ENABLE_STRUCT_PADDING_WARNINGS
struct ProgramInput
{
    ProgramInput() = default;
    ProgramInput(const sh::ShaderVariable &var);

    GLenum getType() const { return pod.type; }
    bool isBuiltIn() const { return pod.flagBits.isBuiltIn; }
    bool isArray() const { return pod.flagBits.isArray; }
    bool isActive() const { return pod.flagBits.active; }
    bool isPatch() const { return pod.flagBits.isPatch; }
    int getLocation() const { return pod.location; }
    unsigned int getBasicTypeElementCount() const { return pod.basicTypeElementCount; }
    unsigned int getArraySizeProduct() const { return pod.arraySizeProduct; }
    uint32_t getId() const { return pod.id; }
    sh::InterpolationType getInterpolation() const
    {
        return static_cast<sh::InterpolationType>(pod.interpolation);
    }

    void setLocation(int location) { pod.location = location; }
    void resetEffectiveLocation()
    {
        if (pod.flagBits.hasImplicitLocation)
        {
            pod.location = -1;
        }
    }

    std::string name;
    std::string mappedName;

    // The struct bellow must only contain data of basic type so that entire struct can memcpy-able.
    struct PODStruct
    {
        uint16_t type;  // GLenum
        uint16_t arraySizeProduct;

        int location;

        uint8_t interpolation;  // sh::InterpolationType
        union
        {
            struct
            {
                uint8_t active : 1;
                uint8_t isPatch : 1;
                uint8_t hasImplicitLocation : 1;
                uint8_t isArray : 1;
                uint8_t isBuiltIn : 1;
                uint8_t padding : 3;
            } flagBits;
            uint8_t flagBitsAsUByte;
        };
        int16_t basicTypeElementCount;

        uint32_t id;
    } pod;
};
ANGLE_DISABLE_STRUCT_PADDING_WARNINGS

ANGLE_ENABLE_STRUCT_PADDING_WARNINGS
struct ProgramOutput
{
    ProgramOutput() = default;
    ProgramOutput(const sh::ShaderVariable &var);
    GLenum getType() const { return pod.type; }
    bool isBuiltIn() const { return pod.isBuiltIn; }
    bool isArray() const { return pod.isArray; }
    int getLocation() const { return pod.location; }
    unsigned int getOutermostArraySize() const { return pod.outermostArraySize; }
    unsigned int getBasicTypeElementCount() const { return pod.basicTypeElementCount; }
    void resetEffectiveLocation()
    {
        if (pod.hasImplicitLocation)
        {
            pod.location = -1;
        }
    }

    std::string name;
    std::string mappedName;

    struct PODStruct
    {
        GLenum type;
        int location;
        int index;
        uint32_t id;

        uint16_t outermostArraySize;
        uint16_t basicTypeElementCount;

        uint32_t isPatch : 1;
        uint32_t yuv : 1;
        uint32_t isBuiltIn : 1;
        uint32_t isArray : 1;
        uint32_t hasImplicitLocation : 1;
        uint32_t hasShaderAssignedLocation : 1;
        uint32_t hasApiAssignedLocation : 1;
        uint32_t pad : 25;
    } pod;
};
ANGLE_DISABLE_STRUCT_PADDING_WARNINGS

// A varying with transform feedback enabled. If it's an array, either the whole array or one of its
// elements specified by 'arrayIndex' can set to be enabled.
struct TransformFeedbackVarying : public sh::ShaderVariable
{
    TransformFeedbackVarying() = default;

    TransformFeedbackVarying(const sh::ShaderVariable &varyingIn, GLuint arrayIndexIn)
        : sh::ShaderVariable(varyingIn), arrayIndex(arrayIndexIn)
    {
        ASSERT(!isArrayOfArrays());
    }

    TransformFeedbackVarying(const sh::ShaderVariable &field, const sh::ShaderVariable &parent)
        : arrayIndex(GL_INVALID_INDEX)
    {
        sh::ShaderVariable *thisVar = this;
        *thisVar                    = field;
        interpolation               = parent.interpolation;
        isInvariant                 = parent.isInvariant;
        ASSERT(parent.isShaderIOBlock || !parent.name.empty());
        if (!parent.name.empty())
        {
            name       = parent.name + "." + name;
            mappedName = parent.mappedName + "." + mappedName;
        }
        structOrBlockName       = parent.structOrBlockName;
        mappedStructOrBlockName = parent.mappedStructOrBlockName;
    }

    std::string nameWithArrayIndex() const
    {
        std::stringstream fullNameStr;
        fullNameStr << name;
        if (arrayIndex != GL_INVALID_INDEX)
        {
            fullNameStr << "[" << arrayIndex << "]";
        }
        return fullNameStr.str();
    }
    GLsizei size() const
    {
        return (isArray() && arrayIndex == GL_INVALID_INDEX ? getOutermostArraySize() : 1);
    }

    GLuint arrayIndex;
};

class ProgramState;
class ProgramPipelineState;

class ProgramExecutable;
using SharedProgramExecutable = std::shared_ptr<ProgramExecutable>;

class ProgramExecutable final : public angle::Subject
{
  public:
    ProgramExecutable(rx::GLImplFactory *factory, InfoLog *infoLog);
    ~ProgramExecutable() override;

    void destroy(const Context *context);

    ANGLE_INLINE rx::ProgramExecutableImpl *getImplementation() const { return mImplementation; }

    void save(gl::BinaryOutputStream *stream) const;
    void load(gl::BinaryInputStream *stream);

    InfoLog &getInfoLog() const { return *mInfoLog; }
    std::string getInfoLogString() const;
    void resetInfoLog() const { mInfoLog->reset(); }

    void resetLinkedShaderStages() { mPod.linkedShaderStages.reset(); }
    const ShaderBitSet getLinkedShaderStages() const { return mPod.linkedShaderStages; }
    void setLinkedShaderStages(ShaderType shaderType)
    {
        mPod.linkedShaderStages.set(shaderType);
        updateCanDrawWith();
    }
    bool hasLinkedShaderStage(ShaderType shaderType) const
    {
        ASSERT(shaderType != ShaderType::InvalidEnum);
        return mPod.linkedShaderStages[shaderType];
    }
    size_t getLinkedShaderStageCount() const { return mPod.linkedShaderStages.count(); }
    bool hasLinkedGraphicsShader() const
    {
        return mPod.linkedShaderStages.any() &&
               mPod.linkedShaderStages != gl::ShaderBitSet{gl::ShaderType::Compute};
    }
    bool hasLinkedTessellationShader() const
    {
        return mPod.linkedShaderStages[ShaderType::TessEvaluation];
    }
    ShaderType getFirstLinkedShaderStageType() const;
    ShaderType getLastLinkedShaderStageType() const;

    ShaderType getLinkedTransformFeedbackStage() const
    {
        return GetLastPreFragmentStage(mPod.linkedShaderStages);
    }

    const AttributesMask &getActiveAttribLocationsMask() const
    {
        return mPod.activeAttribLocationsMask;
    }
    bool isAttribLocationActive(size_t attribLocation) const
    {
        ASSERT(attribLocation < mPod.activeAttribLocationsMask.size());
        return mPod.activeAttribLocationsMask[attribLocation];
    }

    AttributesMask getNonBuiltinAttribLocationsMask() const { return mPod.attributesMask; }
    unsigned int getMaxActiveAttribLocation() const { return mPod.maxActiveAttribLocation; }
    ComponentTypeMask getAttributesTypeMask() const { return mPod.attributesTypeMask; }
    AttributesMask getAttributesMask() const { return mPod.attributesMask; }

    const ActiveTextureMask &getActiveSamplersMask() const { return mActiveSamplersMask; }
    void setActiveTextureMask(ActiveTextureMask mask) { mActiveSamplersMask = mask; }
    SamplerFormat getSamplerFormatForTextureUnitIndex(size_t textureUnitIndex) const
    {
        return mActiveSamplerFormats[textureUnitIndex];
    }
    const ShaderBitSet getSamplerShaderBitsForTextureUnitIndex(size_t textureUnitIndex) const
    {
        return mActiveSamplerShaderBits[textureUnitIndex];
    }
    const ActiveTextureMask &getActiveImagesMask() const { return mActiveImagesMask; }
    void setActiveImagesMask(ActiveTextureMask mask) { mActiveImagesMask = mask; }
    const ActiveTextureArray<ShaderBitSet> &getActiveImageShaderBits() const
    {
        return mActiveImageShaderBits;
    }

    const ActiveTextureMask &getActiveYUVSamplers() const { return mActiveSamplerYUV; }

    const ActiveTextureArray<TextureType> &getActiveSamplerTypes() const
    {
        return mActiveSamplerTypes;
    }

    const ProgramUniformBlockMask &getActiveUniformBufferBlocks() const
    {
        return mActiveUniformBufferBlocks;
    }

    const ProgramStorageBlockMask &getActiveStorageBufferBlocks() const
    {
        return mActiveStorageBufferBlocks;
    }

    void setActive(size_t textureUnit,
                   const SamplerBinding &samplerBinding,
                   const gl::LinkedUniform &samplerUniform);
    void setInactive(size_t textureUnit);
    void hasSamplerTypeConflict(size_t textureUnit);
    void hasSamplerFormatConflict(size_t textureUnit);

    void updateActiveSamplers(const ProgramExecutable &executable);

    bool hasDefaultUniforms() const { return !getDefaultUniformRange().empty(); }
    bool hasTextures() const { return !getSamplerBindings().empty(); }
    bool hasUniformBuffers() const { return !mUniformBlocks.empty(); }
    bool hasStorageBuffers() const { return !mShaderStorageBlocks.empty(); }
    bool hasAtomicCounterBuffers() const { return !mAtomicCounterBuffers.empty(); }
    bool hasImages() const { return !mImageBindings.empty(); }
    bool hasTransformFeedbackOutput() const
    {
        return !getLinkedTransformFeedbackVaryings().empty();
    }
    bool usesColorFramebufferFetch() const { return mPod.fragmentInoutIndices.any(); }
    bool usesDepthFramebufferFetch() const { return mPod.hasDepthInputAttachment; }
    bool usesStencilFramebufferFetch() const { return mPod.hasStencilInputAttachment; }

    // Count the number of uniform and storage buffer declarations, counting arrays as one.
    size_t getTransformFeedbackBufferCount() const { return mTransformFeedbackStrides.size(); }

    void updateCanDrawWith() { mPod.canDrawWith = hasLinkedShaderStage(ShaderType::Vertex); }
    bool hasVertexShader() const { return mPod.canDrawWith; }

    const std::vector<ProgramInput> &getProgramInputs() const { return mProgramInputs; }
    const std::vector<ProgramOutput> &getOutputVariables() const { return mOutputVariables; }
    const std::vector<VariableLocation> &getOutputLocations() const { return mOutputLocations; }
    const std::vector<VariableLocation> &getSecondaryOutputLocations() const
    {
        return mSecondaryOutputLocations;
    }
    const std::vector<LinkedUniform> &getUniforms() const { return mUniforms; }
    const std::vector<std::string> &getUniformNames() const { return mUniformNames; }
    const std::vector<std::string> &getUniformMappedNames() const { return mUniformMappedNames; }
    const std::vector<InterfaceBlock> &getUniformBlocks() const { return mUniformBlocks; }
    const std::vector<VariableLocation> &getUniformLocations() const { return mUniformLocations; }
    const std::vector<SamplerBinding> &getSamplerBindings() const { return mSamplerBindings; }
    const std::vector<GLuint> &getSamplerBoundTextureUnits() const
    {
        return mSamplerBoundTextureUnits;
    }
    const std::vector<ImageBinding> &getImageBindings() const { return mImageBindings; }
    const std::vector<ShPixelLocalStorageLayout> &getPixelLocalStorageLayouts() const
    {
        return mPixelLocalStorageLayouts;
    }
    std::vector<ImageBinding> *getImageBindings() { return &mImageBindings; }
    const RangeUI &getDefaultUniformRange() const { return mPod.defaultUniformRange; }
    const RangeUI &getSamplerUniformRange() const { return mPod.samplerUniformRange; }
    const RangeUI &getImageUniformRange() const { return mPod.imageUniformRange; }
    const RangeUI &getAtomicCounterUniformRange() const { return mPod.atomicCounterUniformRange; }
    DrawBufferMask getFragmentInoutIndices() const { return mPod.fragmentInoutIndices; }
    bool hasClipDistance() const { return mPod.hasClipDistance; }
    bool hasDiscard() const { return mPod.hasDiscard; }
    bool hasFragCoord() const { return mPod.hasFragCoord; }
    bool hasDepthInputAttachment() const { return mPod.hasDepthInputAttachment; }
    bool hasStencilInputAttachment() const { return mPod.hasStencilInputAttachment; }
    bool enablesPerSampleShading() const { return mPod.enablesPerSampleShading; }
    BlendEquationBitSet getAdvancedBlendEquations() const { return mPod.advancedBlendEquations; }
    const std::vector<TransformFeedbackVarying> &getLinkedTransformFeedbackVaryings() const
    {
        return mLinkedTransformFeedbackVaryings;
    }
    GLint getTransformFeedbackBufferMode() const { return mPod.transformFeedbackBufferMode; }
    const sh::WorkGroupSize &getComputeShaderLocalSize() const
    {
        return mPod.computeShaderLocalSize;
    }
    void remapUniformBlockBinding(UniformBlockIndex uniformBlockIndex, GLuint uniformBlockBinding);
    GLuint getUniformBlockBinding(size_t uniformBlockIndex) const
    {
        ASSERT(uniformBlockIndex < mUniformBlocks.size());

        // Unlike SSBOs and atomic counter buffers, GLES allows UBOs bindings to be remapped.  Note
        // that desktop GL allows SSBO bindings to also be remapped, but that's not allowed in GLES.
        //
        // It's therefore important to never directly reference block.pod.inShaderBinding unless the
        // specific shader-specified binding is required.
        return mUniformBlockIndexToBufferBinding[uniformBlockIndex];
    }
    GLuint getShaderStorageBlockBinding(size_t blockIndex) const
    {
        ASSERT(blockIndex < mShaderStorageBlocks.size());
        // The buffer binding for SSBOs is the one specified in the shader
        return mShaderStorageBlocks[blockIndex].pod.inShaderBinding;
    }
    GLuint getAtomicCounterBufferBinding(size_t blockIndex) const
    {
        ASSERT(blockIndex < mAtomicCounterBuffers.size());
        // The buffer binding for atomic counter buffers is the one specified in the shader
        return mAtomicCounterBuffers[blockIndex].pod.inShaderBinding;
    }
    const InterfaceBlock &getUniformBlockByIndex(size_t index) const
    {
        ASSERT(index < mUniformBlocks.size());
        return mUniformBlocks[index];
    }
    const InterfaceBlock &getShaderStorageBlockByIndex(size_t index) const
    {
        ASSERT(index < mShaderStorageBlocks.size());
        return mShaderStorageBlocks[index];
    }
    const BufferVariable &getBufferVariableByIndex(size_t index) const
    {
        ASSERT(index < mBufferVariables.size());
        return mBufferVariables[index];
    }
    const std::vector<GLsizei> &getTransformFeedbackStrides() const
    {
        return mTransformFeedbackStrides;
    }
    const std::vector<AtomicCounterBuffer> &getAtomicCounterBuffers() const
    {
        return mAtomicCounterBuffers;
    }
    const std::vector<InterfaceBlock> &getShaderStorageBlocks() const
    {
        return mShaderStorageBlocks;
    }
    const std::vector<BufferVariable> &getBufferVariables() const { return mBufferVariables; }
    const LinkedUniform &getUniformByIndex(size_t index) const
    {
        ASSERT(index < static_cast<size_t>(mUniforms.size()));
        return mUniforms[index];
    }
    const std::string &getUniformNameByIndex(size_t index) const
    {
        ASSERT(index < static_cast<size_t>(mUniforms.size()));
        return mUniformNames[index];
    }

    GLuint getUniformIndexFromImageIndex(size_t imageIndex) const
    {
        ASSERT(imageIndex < mPod.imageUniformRange.length());
        return static_cast<GLuint>(imageIndex) + mPod.imageUniformRange.low();
    }

    GLuint getUniformIndexFromSamplerIndex(size_t samplerIndex) const
    {
        ASSERT(samplerIndex < mPod.samplerUniformRange.length());
        return static_cast<GLuint>(samplerIndex) + mPod.samplerUniformRange.low();
    }

    void saveLinkedStateInfo(const ProgramState &state);
    const std::vector<sh::ShaderVariable> &getLinkedOutputVaryings(ShaderType shaderType) const
    {
        return mLinkedOutputVaryings[shaderType];
    }
    const std::vector<sh::ShaderVariable> &getLinkedInputVaryings(ShaderType shaderType) const
    {
        return mLinkedInputVaryings[shaderType];
    }

    const std::vector<sh::ShaderVariable> &getLinkedUniforms(ShaderType shaderType) const
    {
        return mLinkedUniforms[shaderType];
    }

    const std::vector<sh::InterfaceBlock> &getLinkedUniformBlocks(ShaderType shaderType) const
    {
        return mLinkedUniformBlocks[shaderType];
    }

    int getLinkedShaderVersion(ShaderType shaderType) const
    {
        return mPod.linkedShaderVersions[shaderType];
    }

    bool isYUVOutput() const { return mPod.hasYUVOutput; }

    PrimitiveMode getGeometryShaderInputPrimitiveType() const
    {
        return mPod.geometryShaderInputPrimitiveType;
    }

    PrimitiveMode getGeometryShaderOutputPrimitiveType() const
    {
        return mPod.geometryShaderOutputPrimitiveType;
    }

    int getGeometryShaderInvocations() const { return mPod.geometryShaderInvocations; }

    int getGeometryShaderMaxVertices() const { return mPod.geometryShaderMaxVertices; }

    GLint getTessControlShaderVertices() const { return mPod.tessControlShaderVertices; }
    GLenum getTessGenMode() const { return mPod.tessGenMode; }
    GLenum getTessGenPointMode() const { return mPod.tessGenPointMode; }
    GLenum getTessGenSpacing() const { return mPod.tessGenSpacing; }
    GLenum getTessGenVertexOrder() const { return mPod.tessGenVertexOrder; }

    int getNumViews() const { return mPod.numViews; }
    bool usesMultiview() const { return mPod.numViews != -1; }

    int getDrawIDLocation() const { return mPod.drawIDLocation; }
    int getBaseVertexLocation() const { return mPod.baseVertexLocation; }
    int getBaseInstanceLocation() const { return mPod.baseInstanceLocation; }

    bool hasDrawIDUniform() const { return getDrawIDLocation() >= 0; }
    bool hasBaseVertexUniform() const { return getBaseVertexLocation() >= 0; }
    bool hasBaseInstanceUniform() const { return getBaseInstanceLocation() >= 0; }

    void resetCachedValidateSamplersResult() { mCachedValidateSamplersResult.reset(); }
    bool validateSamplers(const Caps &caps) const
    {
        // Use the cache if:
        // - we aren't using an info log (which gives the full error).
        // - The sample mapping hasn't changed and we've already validated.
        if (mCachedValidateSamplersResult.valid())
        {
            return mCachedValidateSamplersResult.value();
        }

        return validateSamplersImpl(caps);
    }

    ComponentTypeMask getFragmentOutputsTypeMask() const { return mPod.drawBufferTypeMask; }
    DrawBufferMask getActiveOutputVariablesMask() const { return mPod.activeOutputVariablesMask; }
    DrawBufferMask getActiveSecondaryOutputVariablesMask() const
    {
        return mPod.activeSecondaryOutputVariablesMask;
    }

    GLuint getInputResourceIndex(const GLchar *name) const;
    GLuint getOutputResourceIndex(const GLchar *name) const;
    void getInputResourceName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const;
    void getOutputResourceName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const;
    void getUniformResourceName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const;
    void getBufferVariableResourceName(GLuint index,
                                       GLsizei bufSize,
                                       GLsizei *length,
                                       GLchar *name) const;
    const ProgramInput &getInputResource(size_t index) const
    {
        ASSERT(index < mProgramInputs.size());
        return mProgramInputs[index];
    }
    GLuint getInputResourceMaxNameSize() const;
    GLuint getOutputResourceMaxNameSize() const;
    GLuint getInputResourceLocation(const GLchar *name) const;
    GLuint getOutputResourceLocation(const GLchar *name) const;
    const std::string getInputResourceName(GLuint index) const;
    const std::string getOutputResourceName(GLuint index) const;
    const gl::ProgramOutput &getOutputResource(size_t index) const
    {
        ASSERT(index < mOutputVariables.size());
        return mOutputVariables[index];
    }

    GLint getFragDataLocation(const std::string &name) const;

    // EXT_blend_func_extended
    GLint getFragDataIndex(const std::string &name) const;

    GLsizei getTransformFeedbackVaryingMaxLength() const;
    GLuint getTransformFeedbackVaryingResourceIndex(const GLchar *name) const;
    const TransformFeedbackVarying &getTransformFeedbackVaryingResource(GLuint index) const;
    void getTransformFeedbackVarying(GLuint index,
                                     GLsizei bufSize,
                                     GLsizei *length,
                                     GLsizei *size,
                                     GLenum *type,
                                     GLchar *name) const;

    void getActiveAttribute(GLuint index,
                            GLsizei bufsize,
                            GLsizei *length,
                            GLint *size,
                            GLenum *type,
                            GLchar *name) const;
    GLint getActiveAttributeMaxLength() const;
    GLuint getAttributeLocation(const std::string &name) const;

    void getActiveUniform(GLuint index,
                          GLsizei bufsize,
                          GLsizei *length,
                          GLint *size,
                          GLenum *type,
                          GLchar *name) const;
    GLint getActiveUniformMaxLength() const;
    bool isValidUniformLocation(UniformLocation location) const;
    const LinkedUniform &getUniformByLocation(UniformLocation location) const;
    const VariableLocation &getUniformLocation(UniformLocation location) const;
    UniformLocation getUniformLocation(const std::string &name) const;
    GLuint getUniformIndex(const std::string &name) const;

    void getActiveUniformBlockName(const Context *context,
                                   const UniformBlockIndex blockIndex,
                                   GLsizei bufSize,
                                   GLsizei *length,
                                   GLchar *blockName) const;
    void getActiveShaderStorageBlockName(const GLuint blockIndex,
                                         GLsizei bufSize,
                                         GLsizei *length,
                                         GLchar *blockName) const;

    GLint getActiveUniformBlockMaxNameLength() const;
    GLint getActiveShaderStorageBlockMaxNameLength() const;

    GLuint getUniformBlockIndex(const std::string &name) const;
    GLuint getShaderStorageBlockIndex(const std::string &name) const;

    GLuint getUniformIndexFromName(const std::string &name) const;
    GLuint getUniformIndexFromLocation(UniformLocation location) const;
    Optional<GLuint> getSamplerIndex(UniformLocation location) const;
    bool isSamplerUniformIndex(GLuint index) const;
    GLuint getSamplerIndexFromUniformIndex(GLuint uniformIndex) const;
    bool isImageUniformIndex(GLuint index) const;
    GLuint getImageIndexFromUniformIndex(GLuint uniformIndex) const;
    GLuint getBufferVariableIndexFromName(const std::string &name) const;

    bool linkUniforms(const Caps &caps,
                      const ShaderMap<std::vector<sh::ShaderVariable>> &shaderUniforms,
                      const ProgramAliasedBindings &uniformLocationBindings,
                      GLuint *combinedImageUniformsCount,
                      std::vector<UnusedUniform> *unusedUniforms);

    void copyInputsFromProgram(const ProgramExecutable &executable);
    void copyUniformBuffersFromProgram(const ProgramExecutable &executable,
                                       ShaderType shaderType,
                                       ProgramUniformBlockArray<GLuint> *ppoUniformBlockMap);
    void copyStorageBuffersFromProgram(const ProgramExecutable &executable, ShaderType shaderType);
    void clearSamplerBindings();
    void copySamplerBindingsFromProgram(const ProgramExecutable &executable);
    void copyImageBindingsFromProgram(const ProgramExecutable &executable);
    void copyOutputsFromProgram(const ProgramExecutable &executable);
    void copyUniformsFromProgramMap(const ShaderMap<SharedProgramExecutable> &executables);

    void setUniform1fv(UniformLocation location, GLsizei count, const GLfloat *v);
    void setUniform2fv(UniformLocation location, GLsizei count, const GLfloat *v);
    void setUniform3fv(UniformLocation location, GLsizei count, const GLfloat *v);
    void setUniform4fv(UniformLocation location, GLsizei count, const GLfloat *v);
    void setUniform1iv(Context *context, UniformLocation location, GLsizei count, const GLint *v);
    void setUniform2iv(UniformLocation location, GLsizei count, const GLint *v);
    void setUniform3iv(UniformLocation location, GLsizei count, const GLint *v);
    void setUniform4iv(UniformLocation location, GLsizei count, const GLint *v);
    void setUniform1uiv(UniformLocation location, GLsizei count, const GLuint *v);
    void setUniform2uiv(UniformLocation location, GLsizei count, const GLuint *v);
    void setUniform3uiv(UniformLocation location, GLsizei count, const GLuint *v);
    void setUniform4uiv(UniformLocation location, GLsizei count, const GLuint *v);
    void setUniformMatrix2fv(UniformLocation location,
                             GLsizei count,
                             GLboolean transpose,
                             const GLfloat *value);
    void setUniformMatrix3fv(UniformLocation location,
                             GLsizei count,
                             GLboolean transpose,
                             const GLfloat *value);
    void setUniformMatrix4fv(UniformLocation location,
                             GLsizei count,
                             GLboolean transpose,
                             const GLfloat *value);
    void setUniformMatrix2x3fv(UniformLocation location,
                               GLsizei count,
                               GLboolean transpose,
                               const GLfloat *value);
    void setUniformMatrix3x2fv(UniformLocation location,
                               GLsizei count,
                               GLboolean transpose,
                               const GLfloat *value);
    void setUniformMatrix2x4fv(UniformLocation location,
                               GLsizei count,
                               GLboolean transpose,
                               const GLfloat *value);
    void setUniformMatrix4x2fv(UniformLocation location,
                               GLsizei count,
                               GLboolean transpose,
                               const GLfloat *value);
    void setUniformMatrix3x4fv(UniformLocation location,
                               GLsizei count,
                               GLboolean transpose,
                               const GLfloat *value);
    void setUniformMatrix4x3fv(UniformLocation location,
                               GLsizei count,
                               GLboolean transpose,
                               const GLfloat *value);

    void getUniformfv(const Context *context, UniformLocation location, GLfloat *params) const;
    void getUniformiv(const Context *context, UniformLocation location, GLint *params) const;
    void getUniformuiv(const Context *context, UniformLocation location, GLuint *params) const;

    void setDrawIDUniform(GLint drawid);
    void setBaseVertexUniform(GLint baseVertex);
    void setBaseInstanceUniform(GLuint baseInstance);

    ProgramUniformBlockMask getUniformBufferBlocksMappedToBinding(size_t uniformBufferIndex)
    {
        return mUniformBufferBindingToUniformBlocks[uniformBufferIndex];
    }

    const ProgramUniformBlockArray<GLuint> &getUniformBlockIndexToBufferBindingForCapture() const
    {
        return mUniformBlockIndexToBufferBinding;
    }

    const ShaderMap<SharedProgramExecutable> &getPPOProgramExecutables() const
    {
        return mPPOProgramExecutables;
    }

    bool IsPPO() const { return mIsPPO; }

    // Post-link task helpers
    const std::vector<std::shared_ptr<rx::LinkSubTask>> &getPostLinkSubTasks() const
    {
        return mPostLinkSubTasks;
    }

    const std::vector<std::shared_ptr<angle::WaitableEvent>> &getPostLinkSubTaskWaitableEvents()
        const
    {
        return mPostLinkSubTaskWaitableEvents;
    }

    void onPostLinkTasksComplete() const
    {
        mPostLinkSubTasks.clear();
        mPostLinkSubTaskWaitableEvents.clear();
    }

    void waitForPostLinkTasks(const Context *context);

    void updateActiveUniformBufferBlocks();
    void updateActiveStorageBufferBlocks();

  private:
    friend class Program;
    friend class ProgramPipeline;
    friend class ProgramState;
    friend class ProgramPipelineState;

    void reset();

    void updateActiveImages(const ProgramExecutable &executable);

    bool linkMergedVaryings(const Caps &caps,
                            const Limitations &limitations,
                            const Version &clientVersion,
                            bool webglCompatibility,
                            const ProgramMergedVaryings &mergedVaryings,
                            const LinkingVariables &linkingVariables,
                            ProgramVaryingPacking *varyingPacking);

    bool linkValidateTransformFeedback(const Caps &caps,
                                       const Version &clientVersion,
                                       const ProgramMergedVaryings &varyings,
                                       ShaderType stage);

    void gatherTransformFeedbackVaryings(const ProgramMergedVaryings &varyings, ShaderType stage);

    void updateTransformFeedbackStrides();

    bool validateSamplersImpl(const Caps &caps) const;

    bool linkValidateOutputVariables(const Caps &caps,
                                     const Version &version,
                                     GLuint combinedImageUniformsCount,
                                     GLuint combinedShaderStorageBlocksCount,
                                     int fragmentShaderVersion,
                                     const ProgramAliasedBindings &fragmentOutputLocations,
                                     const ProgramAliasedBindings &fragmentOutputIndices);

    bool gatherOutputTypes();

    void linkSamplerAndImageBindings(GLuint *combinedImageUniformsCount);
    bool linkAtomicCounterBuffers(const Caps &caps);

    void getResourceName(const std::string name,
                         GLsizei bufSize,
                         GLsizei *length,
                         GLchar *dest) const;
    bool shouldIgnoreUniform(UniformLocation location) const;
    GLuint getSamplerUniformBinding(const VariableLocation &uniformLocation) const;
    GLuint getImageUniformBinding(const VariableLocation &uniformLocation) const;

    void initInterfaceBlockBindings();
    void setUniformValuesFromBindingQualifiers();

    // Both these function update the cached uniform values and return a modified "count"
    // so that the uniform update doesn't overflow the uniform.
    template <typename T>
    GLsizei clampUniformCount(const VariableLocation &locationInfo,
                              GLsizei count,
                              int vectorSize,
                              const T *v);
    template <size_t cols, size_t rows, typename T>
    GLsizei clampMatrixUniformCount(UniformLocation location,
                                    GLsizei count,
                                    GLboolean transpose,
                                    const T *v);

    void updateSamplerUniform(Context *context,
                              const VariableLocation &locationInfo,
                              GLsizei clampedCount,
                              const GLint *v);

    // Scans the sampler bindings for type conflicts with sampler 'textureUnitIndex'.
    void setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex);

    template <typename DestT>
    void getUniformInternal(const Context *context,
                            DestT *dataOut,
                            UniformLocation location,
                            GLenum nativeType,
                            int components) const;

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

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

    rx::ProgramExecutableImpl *mImplementation;

    // A reference to the owning object's (Program or ProgramPipeline) info log.  It's kept here for
    // convenience as numerous functions reference it.
    InfoLog *mInfoLog;

    ANGLE_ENABLE_STRUCT_PADDING_WARNINGS
    struct PODStruct
    {
        // 8 bytes each
        angle::BitSet<MAX_VERTEX_ATTRIBS> activeAttribLocationsMask;
        ComponentTypeMask attributesTypeMask;
        // attributesMask is identical to mActiveAttribLocationsMask with built-in attributes
        // removed.
        AttributesMask attributesMask;
        ComponentTypeMask drawBufferTypeMask;

        // 4 bytes each
        uint32_t maxActiveAttribLocation;
        // KHR_blend_equation_advanced supported equation list
        BlendEquationBitSet advancedBlendEquations;

        // 1 byte each
        ShaderBitSet linkedShaderStages;
        DrawBufferMask activeOutputVariablesMask;
        DrawBufferMask activeSecondaryOutputVariablesMask;
        uint8_t hasClipDistance : 1;
        uint8_t hasDiscard : 1;
        uint8_t hasYUVOutput : 1;
        uint8_t hasDepthInputAttachment : 1;
        uint8_t hasStencilInputAttachment : 1;
        uint8_t enablesPerSampleShading : 1;
        uint8_t canDrawWith : 1;
        uint8_t isSeparable : 1;

        // 12 bytes
        sh::WorkGroupSize computeShaderLocalSize;

        // 8 bytes each
        RangeUI defaultUniformRange;
        RangeUI samplerUniformRange;
        RangeUI imageUniformRange;
        RangeUI atomicCounterUniformRange;

        // 1 byte.  Bitset of which input attachments have been declared
        DrawBufferMask fragmentInoutIndices;

        // 1 byte
        uint8_t hasFragCoord : 1;
        uint8_t pad : 7;

        // GL_EXT_geometry_shader.
        PrimitiveMode geometryShaderInputPrimitiveType;
        PrimitiveMode geometryShaderOutputPrimitiveType;
        int32_t geometryShaderInvocations;
        int32_t geometryShaderMaxVertices;
        GLenum transformFeedbackBufferMode;

        // GL_OVR_multiview
        int32_t numViews;

        // GL_ANGLE_multi_draw
        int32_t drawIDLocation;

        // GL_ANGLE_base_vertex_base_instance_shader_builtin
        int32_t baseVertexLocation;
        int32_t baseInstanceLocation;

        // GL_EXT_tessellation_shader
        int32_t tessControlShaderVertices;
        GLenum tessGenMode;
        GLenum tessGenSpacing;
        GLenum tessGenVertexOrder;
        GLenum tessGenPointMode;

        // 24 bytes
        ShaderMap<int> linkedShaderVersions;

        // 4 bytes
        uint32_t padding;
    } mPod;
    ANGLE_DISABLE_STRUCT_PADDING_WARNINGS

    // Cached mask of active samplers and sampler types.
    ActiveTextureMask mActiveSamplersMask;
    ActiveTextureArray<uint32_t> mActiveSamplerRefCounts;
    ActiveTextureArray<TextureType> mActiveSamplerTypes;
    ActiveTextureMask mActiveSamplerYUV;
    ActiveTextureArray<SamplerFormat> mActiveSamplerFormats;
    ActiveTextureArray<ShaderBitSet> mActiveSamplerShaderBits;

    // Cached mask of active images.
    ActiveTextureMask mActiveImagesMask;
    ActiveTextureArray<ShaderBitSet> mActiveImageShaderBits;

    // Cached mask of active uniform and storage buffer blocks
    ProgramUniformBlockMask mActiveUniformBufferBlocks;
    ProgramStorageBlockMask mActiveStorageBufferBlocks;

    // Names and mapped names of output variables that are arrays include [0] in the end, similarly
    // to uniforms.
    std::vector<ProgramOutput> mOutputVariables;
    std::vector<VariableLocation> mOutputLocations;
    // EXT_blend_func_extended secondary outputs (ones with index 1)
    std::vector<VariableLocation> mSecondaryOutputLocations;
    // Vertex attributes, Fragment input varyings, etc.
    std::vector<ProgramInput> mProgramInputs;
    std::vector<TransformFeedbackVarying> mLinkedTransformFeedbackVaryings;
    // Duplicate of ProgramState::mTransformFeedbackVaryingNames.  This is cached here because the
    // xfb names may change, relink may fail, yet program pipeline link should be able to function
    // with the last installed executable.  In truth, program pipeline link should have been able to
    // hoist transform feedback varyings directly from the executable, among most other things, but
    // that is currently not done.
    //
    // This array is not serialized, it's already done by the program, and will be duplicated during
    // deserialization.
    std::vector<std::string> mTransformFeedbackVaryingNames;
    // The size of the data written to each transform feedback buffer per vertex.
    std::vector<GLsizei> mTransformFeedbackStrides;
    // Uniforms are sorted in order:
    //  1. Non-opaque uniforms
    //  2. Sampler uniforms
    //  3. Image uniforms
    //  4. Atomic counter uniforms
    //  5. Uniform block uniforms
    // This makes opaque uniform validation easier, since we don't need a separate list.
    // For generating the entries and naming them we follow the spec: GLES 3.1 November 2016 section
    // 7.3.1.1 Naming Active Resources. There's a separate entry for each struct member and each
    // inner array of an array of arrays. Names and mapped names of uniforms that are arrays include
    // [0] in the end. This makes implementation of queries simpler.
    std::vector<LinkedUniform> mUniforms;
    std::vector<std::string> mUniformNames;
    // Only used by GL and D3D backend
    std::vector<std::string> mUniformMappedNames;
    std::vector<InterfaceBlock> mUniformBlocks;
    std::vector<VariableLocation> mUniformLocations;

    std::vector<AtomicCounterBuffer> mAtomicCounterBuffers;
    std::vector<InterfaceBlock> mShaderStorageBlocks;
    std::vector<BufferVariable> mBufferVariables;

    // An array of the samplers that are used by the program
    std::vector<SamplerBinding> mSamplerBindings;
    // List of all textures bound to all samplers. Each SamplerBinding will point to a subset in
    // this vector.
    std::vector<GLuint> mSamplerBoundTextureUnits;

    // An array of the images that are used by the program
    std::vector<ImageBinding> mImageBindings;

    // ANGLE_shader_pixel_local_storage: A mapping from binding index to the PLS uniform format at
    // that index.
    std::vector<ShPixelLocalStorageLayout> mPixelLocalStorageLayouts;

    ShaderMap<std::vector<sh::ShaderVariable>> mLinkedOutputVaryings;
    ShaderMap<std::vector<sh::ShaderVariable>> mLinkedInputVaryings;
    ShaderMap<std::vector<sh::ShaderVariable>> mLinkedUniforms;
    ShaderMap<std::vector<sh::InterfaceBlock>> mLinkedUniformBlocks;

    // Cached value of base vertex and base instance
    // need to reset them to zero if using non base vertex or base instance draw calls.
    GLint mCachedBaseVertex;
    GLuint mCachedBaseInstance;

    // GLES allows uniform block indices in the program to be remapped to arbitrary buffer bindings
    // through calls to glUniformBlockBinding.  (Desktop GL also includes
    // glShaderStorageBlockBinding, which does not exist in GLES).
    // This is not a part of the link results, and must be reset on glProgramBinary, so it's not
    // serialized.
    // A map from the program uniform block index to the buffer binding it is mapped to.
    ProgramUniformBlockArray<GLuint> mUniformBlockIndexToBufferBinding;
    // The reverse of the above map, i.e. from buffer bindings to the uniform blocks that are mapped
    // to it.  For example, if the program's uniform blocks 1, 3 and 4 are mapped to buffer binding
    // 2, then mUniformBufferBindingToUniformBlocks[2] will be {1, 3, 4}.
    //
    // This is used to efficiently mark uniform blocks dirty when a buffer bound to a binding has
    // been modified.
    UniformBufferBindingArray<ProgramUniformBlockMask> mUniformBufferBindingToUniformBlocks;

    // PPO only: installed executables from the programs.  Note that these may be different from the
    // programs' current executables, because they may have been unsuccessfully relinked.
    ShaderMap<SharedProgramExecutable> mPPOProgramExecutables;
    // Flag for an easy check for PPO without inspecting mPPOProgramExecutables
    bool mIsPPO;

    bool mBinaryRetrieveableHint;

    // Cache for sampler validation
    mutable Optional<bool> mCachedValidateSamplersResult;

    // Post-link subtask and wait events
    // These tasks are not waited on in |resolveLink|, but instead they are free to
    // run until first usage of the program (or relink).  This is used by the backends (currently
    // only Vulkan) to run post-link optimization tasks which don't affect the link results.
    mutable std::vector<std::shared_ptr<rx::LinkSubTask>> mPostLinkSubTasks;
    mutable std::vector<std::shared_ptr<angle::WaitableEvent>> mPostLinkSubTaskWaitableEvents;
};

void InstallExecutable(const Context *context,
                       const SharedProgramExecutable &toInstall,
                       SharedProgramExecutable *executable);
void UninstallExecutable(const Context *context, SharedProgramExecutable *executable);
}  // namespace gl

#endif  // LIBANGLE_PROGRAMEXECUTABLE_H_
