//
// Copyright 2015 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.
//

// ProgramGL.cpp: Implements the class methods for ProgramGL.

#include "libANGLE/renderer/gl/ProgramGL.h"

#include "common/angleutils.h"
#include "common/bitset_utils.h"
#include "common/debug.h"
#include "common/string_utils.h"
#include "common/utilities.h"
#include "libANGLE/Context.h"
#include "libANGLE/ProgramLinkedResources.h"
#include "libANGLE/Uniform.h"
#include "libANGLE/WorkerThread.h"
#include "libANGLE/queryconversions.h"
#include "libANGLE/renderer/gl/ContextGL.h"
#include "libANGLE/renderer/gl/FunctionsGL.h"
#include "libANGLE/renderer/gl/RendererGL.h"
#include "libANGLE/renderer/gl/ShaderGL.h"
#include "libANGLE/renderer/gl/StateManagerGL.h"
#include "libANGLE/trace.h"
#include "platform/FeaturesGL.h"
#include "platform/PlatformMethods.h"

namespace rx
{

ProgramGL::ProgramGL(const gl::ProgramState &data,
                     const FunctionsGL *functions,
                     const angle::FeaturesGL &features,
                     StateManagerGL *stateManager,
                     const std::shared_ptr<RendererGL> &renderer)
    : ProgramImpl(data),
      mFunctions(functions),
      mFeatures(features),
      mStateManager(stateManager),
      mMultiviewBaseViewLayerIndexUniformLocation(-1),
      mProgramID(0),
      mRenderer(renderer),
      mLinkedInParallel(false)
{
    ASSERT(mFunctions);
    ASSERT(mStateManager);

    mProgramID = mFunctions->createProgram();
}

ProgramGL::~ProgramGL()
{
    mFunctions->deleteProgram(mProgramID);
    mProgramID = 0;
}

std::unique_ptr<LinkEvent> ProgramGL::load(const gl::Context *context,
                                           gl::BinaryInputStream *stream,
                                           gl::InfoLog &infoLog)
{
    ANGLE_TRACE_EVENT0("gpu.angle", "ProgramGL::load");
    preLink();

    // Read the binary format, size and blob
    GLenum binaryFormat   = stream->readInt<GLenum>();
    GLint binaryLength    = stream->readInt<GLint>();
    const uint8_t *binary = stream->data() + stream->offset();
    stream->skip(binaryLength);

    // Load the binary
    mFunctions->programBinary(mProgramID, binaryFormat, binary, binaryLength);

    // Verify that the program linked
    if (!checkLinkStatus(infoLog))
    {
        return std::make_unique<LinkEventDone>(angle::Result::Incomplete);
    }

    postLink();
    reapplyUBOBindingsIfNeeded(context);

    return std::make_unique<LinkEventDone>(angle::Result::Continue);
}

void ProgramGL::save(const gl::Context *context, gl::BinaryOutputStream *stream)
{
    GLint binaryLength = 0;
    mFunctions->getProgramiv(mProgramID, GL_PROGRAM_BINARY_LENGTH, &binaryLength);

    std::vector<uint8_t> binary(std::max(binaryLength, 1));
    GLenum binaryFormat = GL_NONE;
    mFunctions->getProgramBinary(mProgramID, binaryLength, &binaryLength, &binaryFormat,
                                 binary.data());

    stream->writeInt(binaryFormat);
    stream->writeInt(binaryLength);
    stream->writeBytes(binary.data(), binaryLength);

    reapplyUBOBindingsIfNeeded(context);
}

void ProgramGL::reapplyUBOBindingsIfNeeded(const gl::Context *context)
{
    // Re-apply UBO bindings to work around driver bugs.
    const angle::FeaturesGL &features = GetImplAs<ContextGL>(context)->getFeaturesGL();
    if (features.reapplyUBOBindingsAfterUsingBinaryProgram.enabled)
    {
        const auto &blocks = mState.getUniformBlocks();
        for (size_t blockIndex : mState.getActiveUniformBlockBindingsMask())
        {
            setUniformBlockBinding(static_cast<GLuint>(blockIndex), blocks[blockIndex].binding);
        }
    }
}

void ProgramGL::setBinaryRetrievableHint(bool retrievable)
{
    // glProgramParameteri isn't always available on ES backends.
    if (mFunctions->programParameteri)
    {
        mFunctions->programParameteri(mProgramID, GL_PROGRAM_BINARY_RETRIEVABLE_HINT,
                                      retrievable ? GL_TRUE : GL_FALSE);
    }
}

void ProgramGL::setSeparable(bool separable)
{
    mFunctions->programParameteri(mProgramID, GL_PROGRAM_SEPARABLE, separable ? GL_TRUE : GL_FALSE);
}

using LinkImplFunctor = std::function<bool(std::string &)>;
class ProgramGL::LinkTask final : public angle::Closure
{
  public:
    LinkTask(LinkImplFunctor &&functor) : mLinkImplFunctor(functor), mFallbackToMainContext(false)
    {}

    void operator()() override
    {
        ANGLE_TRACE_EVENT0("gpu.angle", "ProgramGL::LinkTask::run");
        mFallbackToMainContext = mLinkImplFunctor(mInfoLog);
    }

    bool fallbackToMainContext() { return mFallbackToMainContext; }
    const std::string &getInfoLog() { return mInfoLog; }

  private:
    LinkImplFunctor mLinkImplFunctor;
    bool mFallbackToMainContext;
    std::string mInfoLog;
};

using PostLinkImplFunctor = std::function<angle::Result(bool, const std::string &)>;

// The event for a parallelized linking using the native driver extension.
class ProgramGL::LinkEventNativeParallel final : public LinkEvent
{
  public:
    LinkEventNativeParallel(PostLinkImplFunctor &&functor,
                            const FunctionsGL *functions,
                            GLuint programID)
        : mPostLinkImplFunctor(functor), mFunctions(functions), mProgramID(programID)
    {}

    angle::Result wait(const gl::Context *context) override
    {
        ANGLE_TRACE_EVENT0("gpu.angle", "ProgramGL::LinkEventNativeParallel::wait");

        GLint linkStatus = GL_FALSE;
        mFunctions->getProgramiv(mProgramID, GL_LINK_STATUS, &linkStatus);
        if (linkStatus == GL_TRUE)
        {
            return mPostLinkImplFunctor(false, std::string());
        }
        return angle::Result::Incomplete;
    }

    bool isLinking() override
    {
        GLint completionStatus = GL_FALSE;
        mFunctions->getProgramiv(mProgramID, GL_COMPLETION_STATUS, &completionStatus);
        return completionStatus == GL_FALSE;
    }

  private:
    PostLinkImplFunctor mPostLinkImplFunctor;
    const FunctionsGL *mFunctions;
    GLuint mProgramID;
};

// The event for a parallelized linking using the worker thread pool.
class ProgramGL::LinkEventGL final : public LinkEvent
{
  public:
    LinkEventGL(std::shared_ptr<angle::WorkerThreadPool> workerPool,
                std::shared_ptr<ProgramGL::LinkTask> linkTask,
                PostLinkImplFunctor &&functor)
        : mLinkTask(linkTask),
          mWaitableEvent(std::shared_ptr<angle::WaitableEvent>(
              angle::WorkerThreadPool::PostWorkerTask(workerPool, mLinkTask))),
          mPostLinkImplFunctor(functor)
    {}

    angle::Result wait(const gl::Context *context) override
    {
        ANGLE_TRACE_EVENT0("gpu.angle", "ProgramGL::LinkEventGL::wait");

        mWaitableEvent->wait();
        return mPostLinkImplFunctor(mLinkTask->fallbackToMainContext(), mLinkTask->getInfoLog());
    }

    bool isLinking() override { return !mWaitableEvent->isReady(); }

  private:
    std::shared_ptr<ProgramGL::LinkTask> mLinkTask;
    std::shared_ptr<angle::WaitableEvent> mWaitableEvent;
    PostLinkImplFunctor mPostLinkImplFunctor;
};

std::unique_ptr<LinkEvent> ProgramGL::link(const gl::Context *context,
                                           const gl::ProgramLinkedResources &resources,
                                           gl::InfoLog &infoLog,
                                           const gl::ProgramMergedVaryings & /*mergedVaryings*/)
{
    ANGLE_TRACE_EVENT0("gpu.angle", "ProgramGL::link");

    preLink();

    if (mState.getAttachedShader(gl::ShaderType::Compute))
    {
        const ShaderGL *computeShaderGL =
            GetImplAs<ShaderGL>(mState.getAttachedShader(gl::ShaderType::Compute));

        mFunctions->attachShader(mProgramID, computeShaderGL->getShaderID());
    }
    else
    {
        // Set the transform feedback state
        std::vector<std::string> transformFeedbackVaryingMappedNames;
        for (const auto &tfVarying : mState.getTransformFeedbackVaryingNames())
        {
            gl::ShaderType tfShaderType =
                mState.getExecutable().hasLinkedShaderStage(gl::ShaderType::Geometry)
                    ? gl::ShaderType::Geometry
                    : gl::ShaderType::Vertex;
            std::string tfVaryingMappedName =
                mState.getAttachedShader(tfShaderType)
                    ->getTransformFeedbackVaryingMappedName(tfVarying);
            transformFeedbackVaryingMappedNames.push_back(tfVaryingMappedName);
        }

        if (transformFeedbackVaryingMappedNames.empty())
        {
            if (mFunctions->transformFeedbackVaryings)
            {
                mFunctions->transformFeedbackVaryings(mProgramID, 0, nullptr,
                                                      mState.getTransformFeedbackBufferMode());
            }
        }
        else
        {
            ASSERT(mFunctions->transformFeedbackVaryings);
            std::vector<const GLchar *> transformFeedbackVaryings;
            for (const auto &varying : transformFeedbackVaryingMappedNames)
            {
                transformFeedbackVaryings.push_back(varying.c_str());
            }
            mFunctions->transformFeedbackVaryings(
                mProgramID, static_cast<GLsizei>(transformFeedbackVaryingMappedNames.size()),
                &transformFeedbackVaryings[0], mState.getTransformFeedbackBufferMode());
        }

        for (const gl::ShaderType shaderType : gl::kAllGraphicsShaderTypes)
        {
            const ShaderGL *shaderGL =
                rx::SafeGetImplAs<ShaderGL, gl::Shader>(mState.getAttachedShader(shaderType));
            if (shaderGL)
            {
                mFunctions->attachShader(mProgramID, shaderGL->getShaderID());
            }
        }

        // Bind attribute locations to match the GL layer.
        for (const sh::ShaderVariable &attribute : mState.getProgramInputs())
        {
            if (!attribute.active || attribute.isBuiltIn())
            {
                continue;
            }

            mFunctions->bindAttribLocation(mProgramID, attribute.location,
                                           attribute.mappedName.c_str());
        }

        // Bind the secondary fragment color outputs defined in EXT_blend_func_extended. We only use
        // the API to bind fragment output locations in case EXT_blend_func_extended is enabled.
        // Otherwise shader-assigned locations will work.
        if (context->getExtensions().blendFuncExtendedEXT)
        {
            gl::Shader *fragmentShader = mState.getAttachedShader(gl::ShaderType::Fragment);
            if (fragmentShader && fragmentShader->getShaderVersion() == 100)
            {
                // TODO(http://anglebug.com/2833): The bind done below is only valid in case the
                // compiler transforms the shader outputs to the angle/webgl prefixed ones. If we
                // added support for running EXT_blend_func_extended on top of GLES, some changes
                // would be required:
                //  - If we're backed by GLES 2.0, we shouldn't do the bind because it's not needed.
                //  - If we're backed by GLES 3.0+, it's a bit unclear what should happen. Currently
                //    the compiler doesn't support transforming GLSL ES 1.00 shaders to GLSL ES 3.00
                //    shaders in general, but support for that might be required. Or we might be
                //    able to skip the bind in case the compiler outputs GLSL ES 1.00.
                const auto &shaderOutputs =
                    mState.getAttachedShader(gl::ShaderType::Fragment)->getActiveOutputVariables();
                for (const auto &output : shaderOutputs)
                {
                    // TODO(http://anglebug.com/1085) This could be cleaner if the transformed names
                    // would be set correctly in ShaderVariable::mappedName. This would require some
                    // refactoring in the translator. Adding a mapped name dictionary for builtins
                    // into the symbol table would be one fairly clean way to do it.
                    if (output.name == "gl_SecondaryFragColorEXT")
                    {
                        mFunctions->bindFragDataLocationIndexed(mProgramID, 0, 0,
                                                                "webgl_FragColor");
                        mFunctions->bindFragDataLocationIndexed(mProgramID, 0, 1,
                                                                "webgl_SecondaryFragColor");
                    }
                    else if (output.name == "gl_SecondaryFragDataEXT")
                    {
                        // Basically we should have a loop here going over the output
                        // array binding "webgl_FragData[i]" and "webgl_SecondaryFragData[i]" array
                        // indices to the correct color buffers and color indices.
                        // However I'm not sure if this construct is legal or not, neither ARB or
                        // EXT version of the spec mention this. They only mention that
                        // automatically assigned array locations for ESSL 3.00 output arrays need
                        // to have contiguous locations.
                        //
                        // In practice it seems that binding array members works on some drivers and
                        // fails on others. One option could be to modify the shader translator to
                        // expand the arrays into individual output variables instead of using an
                        // array.
                        //
                        // For now we're going to have a limitation of assuming that
                        // GL_MAX_DUAL_SOURCE_DRAW_BUFFERS is *always* 1 and then only bind the
                        // basename of the variable ignoring any indices. This appears to work
                        // uniformly.
                        ASSERT(output.isArray() && output.getOutermostArraySize() == 1);

                        mFunctions->bindFragDataLocationIndexed(mProgramID, 0, 0, "webgl_FragData");
                        mFunctions->bindFragDataLocationIndexed(mProgramID, 0, 1,
                                                                "webgl_SecondaryFragData");
                    }
                }
            }
            else
            {
                // ESSL 3.00 and up.
                const auto &outputLocations          = mState.getOutputLocations();
                const auto &secondaryOutputLocations = mState.getSecondaryOutputLocations();
                for (size_t outputLocationIndex = 0u; outputLocationIndex < outputLocations.size();
                     ++outputLocationIndex)
                {
                    const gl::VariableLocation &outputLocation =
                        outputLocations[outputLocationIndex];
                    if (outputLocation.arrayIndex == 0 && outputLocation.used() &&
                        !outputLocation.ignored)
                    {
                        const sh::ShaderVariable &outputVar =
                            mState.getOutputVariables()[outputLocation.index];
                        if (outputVar.location == -1 || outputVar.index == -1)
                        {
                            // We only need to assign the location and index via the API in case the
                            // variable doesn't have a shader-assigned location and index. If a
                            // variable doesn't have its location set in the shader it doesn't have
                            // the index set either.
                            ASSERT(outputVar.index == -1);
                            mFunctions->bindFragDataLocationIndexed(
                                mProgramID, static_cast<int>(outputLocationIndex), 0,
                                outputVar.mappedName.c_str());
                        }
                    }
                }
                for (size_t outputLocationIndex = 0u;
                     outputLocationIndex < secondaryOutputLocations.size(); ++outputLocationIndex)
                {
                    const gl::VariableLocation &outputLocation =
                        secondaryOutputLocations[outputLocationIndex];
                    if (outputLocation.arrayIndex == 0 && outputLocation.used() &&
                        !outputLocation.ignored)
                    {
                        const sh::ShaderVariable &outputVar =
                            mState.getOutputVariables()[outputLocation.index];
                        if (outputVar.location == -1 || outputVar.index == -1)
                        {
                            // We only need to assign the location and index via the API in case the
                            // variable doesn't have a shader-assigned location and index.  If a
                            // variable doesn't have its location set in the shader it doesn't have
                            // the index set either.
                            ASSERT(outputVar.index == -1);
                            mFunctions->bindFragDataLocationIndexed(
                                mProgramID, static_cast<int>(outputLocationIndex), 1,
                                outputVar.mappedName.c_str());
                        }
                    }
                }
            }
        }
    }
    auto workerPool = context->getWorkerThreadPool();
    auto linkTask   = std::make_shared<LinkTask>([this](std::string &infoLog) {
        std::string workerInfoLog;
        ScopedWorkerContextGL worker(mRenderer.get(), &workerInfoLog);
        if (!worker())
        {
#if !defined(NDEBUG)
            infoLog += "bindWorkerContext failed.\n" + workerInfoLog;
#endif
            // Fallback to the main context.
            return true;
        }

        mFunctions->linkProgram(mProgramID);

        // Make sure the driver actually does the link job.
        GLint linkStatus = GL_FALSE;
        mFunctions->getProgramiv(mProgramID, GL_LINK_STATUS, &linkStatus);

        return false;
    });

    auto postLinkImplTask = [this, &infoLog, &resources](bool fallbackToMainContext,
                                                         const std::string &workerInfoLog) {
        infoLog << workerInfoLog;
        if (fallbackToMainContext)
        {
            mFunctions->linkProgram(mProgramID);
        }

        if (mState.getAttachedShader(gl::ShaderType::Compute))
        {
            const ShaderGL *computeShaderGL =
                GetImplAs<ShaderGL>(mState.getAttachedShader(gl::ShaderType::Compute));

            mFunctions->detachShader(mProgramID, computeShaderGL->getShaderID());
        }
        else
        {
            for (const gl::ShaderType shaderType : gl::kAllGraphicsShaderTypes)
            {
                const ShaderGL *shaderGL =
                    rx::SafeGetImplAs<ShaderGL>(mState.getAttachedShader(shaderType));
                if (shaderGL)
                {
                    mFunctions->detachShader(mProgramID, shaderGL->getShaderID());
                }
            }
        }
        // Verify the link
        if (!checkLinkStatus(infoLog))
        {
            return angle::Result::Incomplete;
        }

        if (mFeatures.alwaysCallUseProgramAfterLink.enabled)
        {
            mStateManager->forceUseProgram(mProgramID);
        }

        linkResources(resources);
        postLink();

        return angle::Result::Continue;
    };

    if (mRenderer->hasNativeParallelCompile())
    {
        mFunctions->linkProgram(mProgramID);

        return std::make_unique<LinkEventNativeParallel>(postLinkImplTask, mFunctions, mProgramID);
    }
    else if (workerPool->isAsync() &&
             (!mFeatures.dontRelinkProgramsInParallel.enabled || !mLinkedInParallel))
    {
        mLinkedInParallel = true;
        return std::make_unique<LinkEventGL>(workerPool, linkTask, postLinkImplTask);
    }
    else
    {
        return std::make_unique<LinkEventDone>(postLinkImplTask(true, std::string()));
    }
}

GLboolean ProgramGL::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLog*/)
{
    // TODO(jmadill): implement validate
    return true;
}

void ProgramGL::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
{
    if (mFunctions->programUniform1fv != nullptr)
    {
        mFunctions->programUniform1fv(mProgramID, uniLoc(location), count, v);
    }
    else
    {
        mStateManager->useProgram(mProgramID);
        mFunctions->uniform1fv(uniLoc(location), count, v);
    }
}

void ProgramGL::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
{
    if (mFunctions->programUniform2fv != nullptr)
    {
        mFunctions->programUniform2fv(mProgramID, uniLoc(location), count, v);
    }
    else
    {
        mStateManager->useProgram(mProgramID);
        mFunctions->uniform2fv(uniLoc(location), count, v);
    }
}

void ProgramGL::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
{
    if (mFunctions->programUniform3fv != nullptr)
    {
        mFunctions->programUniform3fv(mProgramID, uniLoc(location), count, v);
    }
    else
    {
        mStateManager->useProgram(mProgramID);
        mFunctions->uniform3fv(uniLoc(location), count, v);
    }
}

void ProgramGL::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
{
    if (mFunctions->programUniform4fv != nullptr)
    {
        mFunctions->programUniform4fv(mProgramID, uniLoc(location), count, v);
    }
    else
    {
        mStateManager->useProgram(mProgramID);
        mFunctions->uniform4fv(uniLoc(location), count, v);
    }
}

void ProgramGL::setUniform1iv(GLint location, GLsizei count, const GLint *v)
{
    if (mFunctions->programUniform1iv != nullptr)
    {
        mFunctions->programUniform1iv(mProgramID, uniLoc(location), count, v);
    }
    else
    {
        mStateManager->useProgram(mProgramID);
        mFunctions->uniform1iv(uniLoc(location), count, v);
    }
}

void ProgramGL::setUniform2iv(GLint location, GLsizei count, const GLint *v)
{
    if (mFunctions->programUniform2iv != nullptr)
    {
        mFunctions->programUniform2iv(mProgramID, uniLoc(location), count, v);
    }
    else
    {
        mStateManager->useProgram(mProgramID);
        mFunctions->uniform2iv(uniLoc(location), count, v);
    }
}

void ProgramGL::setUniform3iv(GLint location, GLsizei count, const GLint *v)
{
    if (mFunctions->programUniform3iv != nullptr)
    {
        mFunctions->programUniform3iv(mProgramID, uniLoc(location), count, v);
    }
    else
    {
        mStateManager->useProgram(mProgramID);
        mFunctions->uniform3iv(uniLoc(location), count, v);
    }
}

void ProgramGL::setUniform4iv(GLint location, GLsizei count, const GLint *v)
{
    if (mFunctions->programUniform4iv != nullptr)
    {
        mFunctions->programUniform4iv(mProgramID, uniLoc(location), count, v);
    }
    else
    {
        mStateManager->useProgram(mProgramID);
        mFunctions->uniform4iv(uniLoc(location), count, v);
    }
}

void ProgramGL::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
{
    if (mFunctions->programUniform1uiv != nullptr)
    {
        mFunctions->programUniform1uiv(mProgramID, uniLoc(location), count, v);
    }
    else
    {
        mStateManager->useProgram(mProgramID);
        mFunctions->uniform1uiv(uniLoc(location), count, v);
    }
}

void ProgramGL::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
{
    if (mFunctions->programUniform2uiv != nullptr)
    {
        mFunctions->programUniform2uiv(mProgramID, uniLoc(location), count, v);
    }
    else
    {
        mStateManager->useProgram(mProgramID);
        mFunctions->uniform2uiv(uniLoc(location), count, v);
    }
}

void ProgramGL::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
{
    if (mFunctions->programUniform3uiv != nullptr)
    {
        mFunctions->programUniform3uiv(mProgramID, uniLoc(location), count, v);
    }
    else
    {
        mStateManager->useProgram(mProgramID);
        mFunctions->uniform3uiv(uniLoc(location), count, v);
    }
}

void ProgramGL::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
{
    if (mFunctions->programUniform4uiv != nullptr)
    {
        mFunctions->programUniform4uiv(mProgramID, uniLoc(location), count, v);
    }
    else
    {
        mStateManager->useProgram(mProgramID);
        mFunctions->uniform4uiv(uniLoc(location), count, v);
    }
}

void ProgramGL::setUniformMatrix2fv(GLint location,
                                    GLsizei count,
                                    GLboolean transpose,
                                    const GLfloat *value)
{
    if (mFunctions->programUniformMatrix2fv != nullptr)
    {
        mFunctions->programUniformMatrix2fv(mProgramID, uniLoc(location), count, transpose, value);
    }
    else
    {
        mStateManager->useProgram(mProgramID);
        mFunctions->uniformMatrix2fv(uniLoc(location), count, transpose, value);
    }
}

void ProgramGL::setUniformMatrix3fv(GLint location,
                                    GLsizei count,
                                    GLboolean transpose,
                                    const GLfloat *value)
{
    if (mFunctions->programUniformMatrix3fv != nullptr)
    {
        mFunctions->programUniformMatrix3fv(mProgramID, uniLoc(location), count, transpose, value);
    }
    else
    {
        mStateManager->useProgram(mProgramID);
        mFunctions->uniformMatrix3fv(uniLoc(location), count, transpose, value);
    }
}

void ProgramGL::setUniformMatrix4fv(GLint location,
                                    GLsizei count,
                                    GLboolean transpose,
                                    const GLfloat *value)
{
    if (mFunctions->programUniformMatrix4fv != nullptr)
    {
        mFunctions->programUniformMatrix4fv(mProgramID, uniLoc(location), count, transpose, value);
    }
    else
    {
        mStateManager->useProgram(mProgramID);
        mFunctions->uniformMatrix4fv(uniLoc(location), count, transpose, value);
    }
}

void ProgramGL::setUniformMatrix2x3fv(GLint location,
                                      GLsizei count,
                                      GLboolean transpose,
                                      const GLfloat *value)
{
    if (mFunctions->programUniformMatrix2x3fv != nullptr)
    {
        mFunctions->programUniformMatrix2x3fv(mProgramID, uniLoc(location), count, transpose,
                                              value);
    }
    else
    {
        mStateManager->useProgram(mProgramID);
        mFunctions->uniformMatrix2x3fv(uniLoc(location), count, transpose, value);
    }
}

void ProgramGL::setUniformMatrix3x2fv(GLint location,
                                      GLsizei count,
                                      GLboolean transpose,
                                      const GLfloat *value)
{
    if (mFunctions->programUniformMatrix3x2fv != nullptr)
    {
        mFunctions->programUniformMatrix3x2fv(mProgramID, uniLoc(location), count, transpose,
                                              value);
    }
    else
    {
        mStateManager->useProgram(mProgramID);
        mFunctions->uniformMatrix3x2fv(uniLoc(location), count, transpose, value);
    }
}

void ProgramGL::setUniformMatrix2x4fv(GLint location,
                                      GLsizei count,
                                      GLboolean transpose,
                                      const GLfloat *value)
{
    if (mFunctions->programUniformMatrix2x4fv != nullptr)
    {
        mFunctions->programUniformMatrix2x4fv(mProgramID, uniLoc(location), count, transpose,
                                              value);
    }
    else
    {
        mStateManager->useProgram(mProgramID);
        mFunctions->uniformMatrix2x4fv(uniLoc(location), count, transpose, value);
    }
}

void ProgramGL::setUniformMatrix4x2fv(GLint location,
                                      GLsizei count,
                                      GLboolean transpose,
                                      const GLfloat *value)
{
    if (mFunctions->programUniformMatrix4x2fv != nullptr)
    {
        mFunctions->programUniformMatrix4x2fv(mProgramID, uniLoc(location), count, transpose,
                                              value);
    }
    else
    {
        mStateManager->useProgram(mProgramID);
        mFunctions->uniformMatrix4x2fv(uniLoc(location), count, transpose, value);
    }
}

void ProgramGL::setUniformMatrix3x4fv(GLint location,
                                      GLsizei count,
                                      GLboolean transpose,
                                      const GLfloat *value)
{
    if (mFunctions->programUniformMatrix3x4fv != nullptr)
    {
        mFunctions->programUniformMatrix3x4fv(mProgramID, uniLoc(location), count, transpose,
                                              value);
    }
    else
    {
        mStateManager->useProgram(mProgramID);
        mFunctions->uniformMatrix3x4fv(uniLoc(location), count, transpose, value);
    }
}

void ProgramGL::setUniformMatrix4x3fv(GLint location,
                                      GLsizei count,
                                      GLboolean transpose,
                                      const GLfloat *value)
{
    if (mFunctions->programUniformMatrix4x3fv != nullptr)
    {
        mFunctions->programUniformMatrix4x3fv(mProgramID, uniLoc(location), count, transpose,
                                              value);
    }
    else
    {
        mStateManager->useProgram(mProgramID);
        mFunctions->uniformMatrix4x3fv(uniLoc(location), count, transpose, value);
    }
}

void ProgramGL::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
{
    // Lazy init
    if (mUniformBlockRealLocationMap.empty())
    {
        mUniformBlockRealLocationMap.reserve(mState.getUniformBlocks().size());
        for (const gl::InterfaceBlock &uniformBlock : mState.getUniformBlocks())
        {
            const std::string &mappedNameWithIndex = uniformBlock.mappedNameWithArrayIndex();
            GLuint blockIndex =
                mFunctions->getUniformBlockIndex(mProgramID, mappedNameWithIndex.c_str());
            mUniformBlockRealLocationMap.push_back(blockIndex);
        }
    }

    GLuint realBlockIndex = mUniformBlockRealLocationMap[uniformBlockIndex];
    if (realBlockIndex != GL_INVALID_INDEX)
    {
        mFunctions->uniformBlockBinding(mProgramID, realBlockIndex, uniformBlockBinding);
    }
}

bool ProgramGL::getUniformBlockSize(const std::string & /* blockName */,
                                    const std::string &blockMappedName,
                                    size_t *sizeOut) const
{
    ASSERT(mProgramID != 0u);

    GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, blockMappedName.c_str());
    if (blockIndex == GL_INVALID_INDEX)
    {
        *sizeOut = 0;
        return false;
    }

    GLint dataSize = 0;
    mFunctions->getActiveUniformBlockiv(mProgramID, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE,
                                        &dataSize);
    *sizeOut = static_cast<size_t>(dataSize);
    return true;
}

bool ProgramGL::getUniformBlockMemberInfo(const std::string & /* memberUniformName */,
                                          const std::string &memberUniformMappedName,
                                          sh::BlockMemberInfo *memberInfoOut) const
{
    GLuint uniformIndex;
    const GLchar *memberNameGLStr = memberUniformMappedName.c_str();
    mFunctions->getUniformIndices(mProgramID, 1, &memberNameGLStr, &uniformIndex);

    if (uniformIndex == GL_INVALID_INDEX)
    {
        *memberInfoOut = sh::kDefaultBlockMemberInfo;
        return false;
    }

    mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_OFFSET,
                                    &memberInfoOut->offset);
    mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_ARRAY_STRIDE,
                                    &memberInfoOut->arrayStride);
    mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_MATRIX_STRIDE,
                                    &memberInfoOut->matrixStride);

    // TODO(jmadill): possibly determine this at the gl::Program level.
    GLint isRowMajorMatrix = 0;
    mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_IS_ROW_MAJOR,
                                    &isRowMajorMatrix);
    memberInfoOut->isRowMajorMatrix = gl::ConvertToBool(isRowMajorMatrix);
    return true;
}

bool ProgramGL::getShaderStorageBlockMemberInfo(const std::string & /* memberName */,
                                                const std::string &memberUniformMappedName,
                                                sh::BlockMemberInfo *memberInfoOut) const
{
    const GLchar *memberNameGLStr = memberUniformMappedName.c_str();
    GLuint index =
        mFunctions->getProgramResourceIndex(mProgramID, GL_BUFFER_VARIABLE, memberNameGLStr);

    if (index == GL_INVALID_INDEX)
    {
        *memberInfoOut = sh::kDefaultBlockMemberInfo;
        return false;
    }

    constexpr int kPropCount             = 5;
    std::array<GLenum, kPropCount> props = {
        {GL_ARRAY_STRIDE, GL_IS_ROW_MAJOR, GL_MATRIX_STRIDE, GL_OFFSET, GL_TOP_LEVEL_ARRAY_STRIDE}};
    std::array<GLint, kPropCount> params;
    GLsizei length;
    mFunctions->getProgramResourceiv(mProgramID, GL_BUFFER_VARIABLE, index, kPropCount,
                                     props.data(), kPropCount, &length, params.data());
    ASSERT(kPropCount == length);
    memberInfoOut->arrayStride         = params[0];
    memberInfoOut->isRowMajorMatrix    = params[1] != 0;
    memberInfoOut->matrixStride        = params[2];
    memberInfoOut->offset              = params[3];
    memberInfoOut->topLevelArrayStride = params[4];

    return true;
}

bool ProgramGL::getShaderStorageBlockSize(const std::string &name,
                                          const std::string &mappedName,
                                          size_t *sizeOut) const
{
    const GLchar *nameGLStr = mappedName.c_str();
    GLuint index =
        mFunctions->getProgramResourceIndex(mProgramID, GL_SHADER_STORAGE_BLOCK, nameGLStr);

    if (index == GL_INVALID_INDEX)
    {
        *sizeOut = 0;
        return false;
    }

    GLenum prop    = GL_BUFFER_DATA_SIZE;
    GLsizei length = 0;
    GLint dataSize = 0;
    mFunctions->getProgramResourceiv(mProgramID, GL_SHADER_STORAGE_BLOCK, index, 1, &prop, 1,
                                     &length, &dataSize);
    *sizeOut = static_cast<size_t>(dataSize);
    return true;
}

void ProgramGL::getAtomicCounterBufferSizeMap(std::map<int, unsigned int> *sizeMapOut) const
{
    if (mFunctions->getProgramInterfaceiv == nullptr)
    {
        return;
    }

    int resourceCount = 0;
    mFunctions->getProgramInterfaceiv(mProgramID, GL_ATOMIC_COUNTER_BUFFER, GL_ACTIVE_RESOURCES,
                                      &resourceCount);

    for (int index = 0; index < resourceCount; index++)
    {
        constexpr int kPropCount             = 2;
        std::array<GLenum, kPropCount> props = {{GL_BUFFER_BINDING, GL_BUFFER_DATA_SIZE}};
        std::array<GLint, kPropCount> params;
        GLsizei length;
        mFunctions->getProgramResourceiv(mProgramID, GL_ATOMIC_COUNTER_BUFFER, index, kPropCount,
                                         props.data(), kPropCount, &length, params.data());
        ASSERT(kPropCount == length);
        int bufferBinding           = params[0];
        unsigned int bufferDataSize = params[1];
        sizeMapOut->insert(std::pair<int, unsigned int>(bufferBinding, bufferDataSize));
    }
}

void ProgramGL::preLink()
{
    // Reset the program state
    mUniformRealLocationMap.clear();
    mUniformBlockRealLocationMap.clear();

    mMultiviewBaseViewLayerIndexUniformLocation = -1;
}

bool ProgramGL::checkLinkStatus(gl::InfoLog &infoLog)
{
    GLint linkStatus = GL_FALSE;
    mFunctions->getProgramiv(mProgramID, GL_LINK_STATUS, &linkStatus);
    if (linkStatus == GL_FALSE)
    {
        // Linking or program binary loading failed, put the error into the info log.
        GLint infoLogLength = 0;
        mFunctions->getProgramiv(mProgramID, GL_INFO_LOG_LENGTH, &infoLogLength);

        // Info log length includes the null terminator, so 1 means that the info log is an empty
        // string.
        if (infoLogLength > 1)
        {
            std::vector<char> buf(infoLogLength);
            mFunctions->getProgramInfoLog(mProgramID, infoLogLength, nullptr, &buf[0]);

            infoLog << buf.data();

            WARN() << "Program link or binary loading failed: " << buf.data();
        }
        else
        {
            WARN() << "Program link or binary loading failed with no info log.";
        }

        // This may happen under normal circumstances if we're loading program binaries and the
        // driver or hardware has changed.
        ASSERT(mProgramID != 0);
        return false;
    }

    return true;
}

void ProgramGL::postLink()
{
    // Query the uniform information
    ASSERT(mUniformRealLocationMap.empty());
    const auto &uniformLocations = mState.getUniformLocations();
    const auto &uniforms         = mState.getUniforms();
    mUniformRealLocationMap.resize(uniformLocations.size(), GL_INVALID_INDEX);
    for (size_t uniformLocation = 0; uniformLocation < uniformLocations.size(); uniformLocation++)
    {
        const auto &entry = uniformLocations[uniformLocation];
        if (!entry.used())
        {
            continue;
        }

        // From the GLES 3.0.5 spec:
        // "Locations for sequential array indices are not required to be sequential."
        const gl::LinkedUniform &uniform = uniforms[entry.index];
        std::stringstream fullNameStr;
        if (uniform.isArray())
        {
            ASSERT(angle::EndsWith(uniform.mappedName, "[0]"));
            fullNameStr << uniform.mappedName.substr(0, uniform.mappedName.length() - 3);
            fullNameStr << "[" << entry.arrayIndex << "]";
        }
        else
        {
            fullNameStr << uniform.mappedName;
        }
        const std::string &fullName = fullNameStr.str();

        GLint realLocation = mFunctions->getUniformLocation(mProgramID, fullName.c_str());
        mUniformRealLocationMap[uniformLocation] = realLocation;
    }

    if (mState.usesMultiview())
    {
        mMultiviewBaseViewLayerIndexUniformLocation =
            mFunctions->getUniformLocation(mProgramID, "multiviewBaseViewLayerIndex");
        ASSERT(mMultiviewBaseViewLayerIndexUniformLocation != -1);
    }
}

void ProgramGL::enableSideBySideRenderingPath() const
{
    ASSERT(mState.usesMultiview());
    ASSERT(mMultiviewBaseViewLayerIndexUniformLocation != -1);

    ASSERT(mFunctions->programUniform1i != nullptr);
    mFunctions->programUniform1i(mProgramID, mMultiviewBaseViewLayerIndexUniformLocation, -1);
}

void ProgramGL::enableLayeredRenderingPath(int baseViewIndex) const
{
    ASSERT(mState.usesMultiview());
    ASSERT(mMultiviewBaseViewLayerIndexUniformLocation != -1);

    ASSERT(mFunctions->programUniform1i != nullptr);
    mFunctions->programUniform1i(mProgramID, mMultiviewBaseViewLayerIndexUniformLocation,
                                 baseViewIndex);
}

void ProgramGL::getUniformfv(const gl::Context *context, GLint location, GLfloat *params) const
{
    mFunctions->getUniformfv(mProgramID, uniLoc(location), params);
}

void ProgramGL::getUniformiv(const gl::Context *context, GLint location, GLint *params) const
{
    mFunctions->getUniformiv(mProgramID, uniLoc(location), params);
}

void ProgramGL::getUniformuiv(const gl::Context *context, GLint location, GLuint *params) const
{
    mFunctions->getUniformuiv(mProgramID, uniLoc(location), params);
}

void ProgramGL::markUnusedUniformLocations(std::vector<gl::VariableLocation> *uniformLocations,
                                           std::vector<gl::SamplerBinding> *samplerBindings,
                                           std::vector<gl::ImageBinding> *imageBindings)
{
    GLint maxLocation = static_cast<GLint>(uniformLocations->size());
    for (GLint location = 0; location < maxLocation; ++location)
    {
        if (uniLoc(location) == -1)
        {
            auto &locationRef = (*uniformLocations)[location];
            if (mState.isSamplerUniformIndex(locationRef.index))
            {
                GLuint samplerIndex = mState.getSamplerIndexFromUniformIndex(locationRef.index);
                gl::SamplerBinding &samplerBinding = (*samplerBindings)[samplerIndex];
                if (locationRef.arrayIndex < samplerBinding.boundTextureUnits.size())
                {
                    // Crop unused sampler bindings in the sampler array.
                    samplerBinding.boundTextureUnits.resize(locationRef.arrayIndex);
                }
            }
            else if (mState.isImageUniformIndex(locationRef.index))
            {
                GLuint imageIndex = mState.getImageIndexFromUniformIndex(locationRef.index);
                gl::ImageBinding &imageBinding = (*imageBindings)[imageIndex];
                if (locationRef.arrayIndex < imageBinding.boundImageUnits.size())
                {
                    // Crop unused image bindings in the image array.
                    imageBinding.boundImageUnits.resize(locationRef.arrayIndex);
                }
            }
            // If the location has been previously bound by a glBindUniformLocation call, it should
            // be marked as ignored. Otherwise it's unused.
            if (mState.getUniformLocationBindings().getBindingByLocation(location) != -1)
            {
                locationRef.markIgnored();
            }
            else
            {
                locationRef.markUnused();
            }
        }
    }
}

void ProgramGL::linkResources(const gl::ProgramLinkedResources &resources)
{
    // Gather interface block info.
    auto getUniformBlockSize = [this](const std::string &name, const std::string &mappedName,
                                      size_t *sizeOut) {
        return this->getUniformBlockSize(name, mappedName, sizeOut);
    };

    auto getUniformBlockMemberInfo = [this](const std::string &name, const std::string &mappedName,
                                            sh::BlockMemberInfo *infoOut) {
        return this->getUniformBlockMemberInfo(name, mappedName, infoOut);
    };

    resources.uniformBlockLinker.linkBlocks(getUniformBlockSize, getUniformBlockMemberInfo);

    auto getShaderStorageBlockSize = [this](const std::string &name, const std::string &mappedName,
                                            size_t *sizeOut) {
        return this->getShaderStorageBlockSize(name, mappedName, sizeOut);
    };

    auto getShaderStorageBlockMemberInfo = [this](const std::string &name,
                                                  const std::string &mappedName,
                                                  sh::BlockMemberInfo *infoOut) {
        return this->getShaderStorageBlockMemberInfo(name, mappedName, infoOut);
    };
    resources.shaderStorageBlockLinker.linkBlocks(getShaderStorageBlockSize,
                                                  getShaderStorageBlockMemberInfo);

    // Gather atomic counter buffer info.
    std::map<int, unsigned int> sizeMap;
    getAtomicCounterBufferSizeMap(&sizeMap);
    resources.atomicCounterBufferLinker.link(sizeMap);
}

angle::Result ProgramGL::syncState(const gl::Context *context,
                                   const gl::Program::DirtyBits &dirtyBits)
{
    for (size_t dirtyBit : dirtyBits)
    {
        ASSERT(dirtyBit <= gl::Program::DIRTY_BIT_UNIFORM_BLOCK_BINDING_MAX);
        GLuint binding = static_cast<GLuint>(dirtyBit);
        setUniformBlockBinding(binding, mState.getUniformBlockBinding(binding));
    }
    return angle::Result::Continue;
}
}  // namespace rx
