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

// Program.cpp: Implements the gl::Program class. Implements GL program objects
// and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28.

#include "libANGLE/Program.h"

#include <algorithm>
#include <utility>

#include "common/angle_version_info.h"
#include "common/bitset_utils.h"
#include "common/debug.h"
#include "common/platform.h"
#include "common/platform_helpers.h"
#include "common/string_utils.h"
#include "common/utilities.h"
#include "compiler/translator/blocklayout.h"
#include "libANGLE/Context.h"
#include "libANGLE/ErrorStrings.h"
#include "libANGLE/MemoryProgramCache.h"
#include "libANGLE/ProgramLinkedResources.h"
#include "libANGLE/ResourceManager.h"
#include "libANGLE/Uniform.h"
#include "libANGLE/VaryingPacking.h"
#include "libANGLE/Version.h"
#include "libANGLE/capture/FrameCapture.h"
#include "libANGLE/features.h"
#include "libANGLE/histogram_macros.h"
#include "libANGLE/queryconversions.h"
#include "libANGLE/renderer/ContextImpl.h"
#include "libANGLE/renderer/GLImplFactory.h"
#include "libANGLE/renderer/ProgramImpl.h"
#include "libANGLE/trace.h"
#include "platform/PlatformMethods.h"
#include "platform/autogen/FrontendFeatures_autogen.h"

namespace gl
{

namespace
{
void InitUniformBlockLinker(const ProgramState &state, UniformBlockLinker *blockLinker)
{
    for (ShaderType shaderType : AllShaderTypes())
    {
        const SharedCompiledShaderState &shader = state.getAttachedShader(shaderType);
        if (shader)
        {
            blockLinker->addShaderBlocks(shaderType, &shader->uniformBlocks);
        }
    }
}

void InitShaderStorageBlockLinker(const ProgramState &state, ShaderStorageBlockLinker *blockLinker)
{
    for (ShaderType shaderType : AllShaderTypes())
    {
        const SharedCompiledShaderState &shader = state.getAttachedShader(shaderType);
        if (shader)
        {
            blockLinker->addShaderBlocks(shaderType, &shader->shaderStorageBlocks);
        }
    }
}

// Provides a mechanism to access the result of asynchronous linking.
class LinkEvent : angle::NonCopyable
{
  public:
    virtual ~LinkEvent() {}

    // Please be aware that these methods may be called under a gl::Context other
    // than the one where the LinkEvent was created.
    //
    // Waits until the linking is actually done. Returns true if the linking
    // succeeded, false otherwise.
    virtual angle::Result wait(const gl::Context *context) = 0;
    // Peeks whether the linking is still ongoing.
    virtual bool isLinking() = 0;
    // See MainLinkLoadTask::retrieveOptionalSubTasks
    virtual void retrieveOptionalSubTasks(
        std::vector<std::shared_ptr<rx::LinkSubTask>> *subTasksOut,
        std::vector<std::shared_ptr<angle::WaitableEvent>> *subTaskEventsOut)
    {}
};

// Wraps an already done linking.
class LinkEventDone final : public LinkEvent
{
  public:
    LinkEventDone(angle::Result result) : mResult(result) {}
    angle::Result wait(const gl::Context *context) override { return mResult; }
    bool isLinking() override { return false; }

  private:
    angle::Result mResult;
};
}  // anonymous namespace

const char *GetLinkMismatchErrorString(LinkMismatchError linkError)
{
    switch (linkError)
    {
        case LinkMismatchError::TYPE_MISMATCH:
            return "Type";
        case LinkMismatchError::ARRAYNESS_MISMATCH:
            return "Array-ness";
        case LinkMismatchError::ARRAY_SIZE_MISMATCH:
            return "Array size";
        case LinkMismatchError::PRECISION_MISMATCH:
            return "Precision";
        case LinkMismatchError::STRUCT_NAME_MISMATCH:
            return "Structure name";
        case LinkMismatchError::FIELD_NUMBER_MISMATCH:
            return "Field number";
        case LinkMismatchError::FIELD_NAME_MISMATCH:
            return "Field name";

        case LinkMismatchError::INTERPOLATION_TYPE_MISMATCH:
            return "Interpolation type";
        case LinkMismatchError::INVARIANCE_MISMATCH:
            return "Invariance";

        case LinkMismatchError::BINDING_MISMATCH:
            return "Binding layout qualifier";
        case LinkMismatchError::LOCATION_MISMATCH:
            return "Location layout qualifier";
        case LinkMismatchError::OFFSET_MISMATCH:
            return "Offset layout qualifier";
        case LinkMismatchError::INSTANCE_NAME_MISMATCH:
            return "Instance name qualifier";
        case LinkMismatchError::FORMAT_MISMATCH:
            return "Format qualifier";

        case LinkMismatchError::LAYOUT_QUALIFIER_MISMATCH:
            return "Layout qualifier";
        case LinkMismatchError::MATRIX_PACKING_MISMATCH:
            return "Matrix Packing";

        case LinkMismatchError::FIELD_LOCATION_MISMATCH:
            return "Field location";
        case LinkMismatchError::FIELD_STRUCT_NAME_MISMATCH:
            return "Field structure name";
        default:
            UNREACHABLE();
            return "";
    }
}

template <typename T>
void UpdateInterfaceVariable(std::vector<T> *block, const sh::ShaderVariable &var)
{
    if (!var.isStruct())
    {
        block->emplace_back(var);
        block->back().resetEffectiveLocation();
    }

    for (const sh::ShaderVariable &field : var.fields)
    {
        ASSERT(!var.name.empty() || var.isShaderIOBlock);

        // Shader I/O block naming is similar to UBOs and SSBOs:
        //
        //     in Block
        //     {
        //         type field;  // produces "field"
        //     };
        //
        //     in Block2
        //     {
        //         type field;  // produces "Block2.field"
        //     } block2;
        //
        const std::string &baseName = var.isShaderIOBlock ? var.structOrBlockName : var.name;
        const std::string prefix    = var.name.empty() ? "" : baseName + ".";

        if (!field.isStruct())
        {
            sh::ShaderVariable fieldCopy = field;
            fieldCopy.updateEffectiveLocation(var);
            fieldCopy.name = prefix + field.name;
            block->emplace_back(fieldCopy);
        }

        for (const sh::ShaderVariable &nested : field.fields)
        {
            sh::ShaderVariable nestedCopy = nested;
            nestedCopy.updateEffectiveLocation(field);
            nestedCopy.name = prefix + field.name + "." + nested.name;
            block->emplace_back(nestedCopy);
        }
    }
}

// Saves the linking context for later use in resolveLink().
struct Program::LinkingState
{
    LinkingVariables linkingVariables;
    ProgramLinkedResources resources;
    std::unique_ptr<LinkEvent> linkEvent;
    bool linkingFromBinary;
};

const char *const g_fakepath = "C:\\fakepath";

// InfoLog implementation.
InfoLog::InfoLog() : mLazyStream(nullptr) {}

InfoLog::~InfoLog() {}

size_t InfoLog::getLength() const
{
    if (!mLazyStream)
    {
        return 0;
    }

    const std::string &logString = mLazyStream->str();
    return logString.empty() ? 0 : logString.length() + 1;
}

void InfoLog::getLog(GLsizei bufSize, GLsizei *length, char *infoLog) const
{
    size_t index = 0;

    if (bufSize > 0)
    {
        const std::string logString(str());

        if (!logString.empty())
        {
            index = std::min(static_cast<size_t>(bufSize) - 1, logString.length());
            memcpy(infoLog, logString.c_str(), index);
        }

        infoLog[index] = '\0';
    }

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

// append a sanitized message to the program info log.
// The D3D compiler includes a fake file path in some of the warning or error
// messages, so lets remove all occurrences of this fake file path from the log.
void InfoLog::appendSanitized(const char *message)
{
    ensureInitialized();

    std::string msg(message);

    size_t found;
    do
    {
        found = msg.find(g_fakepath);
        if (found != std::string::npos)
        {
            msg.erase(found, strlen(g_fakepath));
        }
    } while (found != std::string::npos);

    if (!msg.empty())
    {
        *mLazyStream << message << std::endl;
    }
}

void InfoLog::reset()
{
    if (mLazyStream)
    {
        mLazyStream.reset(nullptr);
    }
}

bool InfoLog::empty() const
{
    if (!mLazyStream)
    {
        return true;
    }

    return mLazyStream->rdbuf()->in_avail() == 0;
}

void LogLinkMismatch(InfoLog &infoLog,
                     const std::string &variableName,
                     const char *variableType,
                     LinkMismatchError linkError,
                     const std::string &mismatchedStructOrBlockFieldName,
                     ShaderType shaderType1,
                     ShaderType shaderType2)
{
    std::ostringstream stream;
    stream << GetLinkMismatchErrorString(linkError) << "s of " << variableType << " '"
           << variableName;

    if (!mismatchedStructOrBlockFieldName.empty())
    {
        stream << "' member '" << variableName << "." << mismatchedStructOrBlockFieldName;
    }

    stream << "' differ between " << GetShaderTypeString(shaderType1) << " and "
           << GetShaderTypeString(shaderType2) << " shaders.";

    infoLog << stream.str();
}

bool IsActiveInterfaceBlock(const sh::InterfaceBlock &interfaceBlock)
{
    // Only 'packed' blocks are allowed to be considered inactive.
    return interfaceBlock.active || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED;
}

// VariableLocation implementation.
VariableLocation::VariableLocation() : index(kUnused), arrayIndex(0), ignored(false) {}

VariableLocation::VariableLocation(unsigned int arrayIndexIn, unsigned int index)
    : index(index), ignored(false)
{
    ASSERT(arrayIndex != GL_INVALID_INDEX);
    SetBitField(arrayIndex, arrayIndexIn);
}

// ProgramBindings implementation.
ProgramBindings::ProgramBindings() {}

ProgramBindings::~ProgramBindings() {}

void ProgramBindings::bindLocation(GLuint index, const std::string &name)
{
    mBindings[name] = index;
}

int ProgramBindings::getBindingByName(const std::string &name) const
{
    auto iter = mBindings.find(name);
    return (iter != mBindings.end()) ? iter->second : -1;
}

template <typename T>
int ProgramBindings::getBinding(const T &variable) const
{
    return getBindingByName(variable.name);
}

ProgramBindings::const_iterator ProgramBindings::begin() const
{
    return mBindings.begin();
}

ProgramBindings::const_iterator ProgramBindings::end() const
{
    return mBindings.end();
}

std::map<std::string, GLuint> ProgramBindings::getStableIterationMap() const
{
    return std::map<std::string, GLuint>(mBindings.begin(), mBindings.end());
}

// ProgramAliasedBindings implementation.
ProgramAliasedBindings::ProgramAliasedBindings() {}

ProgramAliasedBindings::~ProgramAliasedBindings() {}

void ProgramAliasedBindings::bindLocation(GLuint index, const std::string &name)
{
    mBindings[name] = ProgramBinding(index);

    // EXT_blend_func_extended spec: "If it specifies the base name of an array,
    // it identifies the resources associated with the first element of the array."
    //
    // Normalize array bindings so that "name" and "name[0]" map to the same entry.
    // If this binding is of the form "name[0]", then mark the "name" binding as
    // aliased but do not update it yet in case "name" is not actually an array.
    size_t nameLengthWithoutArrayIndex;
    unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
    if (arrayIndex == 0)
    {
        std::string baseName = name.substr(0u, nameLengthWithoutArrayIndex);
        auto iter            = mBindings.find(baseName);
        if (iter != mBindings.end())
        {
            iter->second.aliased = true;
        }
    }
}

int ProgramAliasedBindings::getBindingByName(const std::string &name) const
{
    auto iter = mBindings.find(name);
    return (iter != mBindings.end()) ? iter->second.location : -1;
}

int ProgramAliasedBindings::getBindingByLocation(GLuint location) const
{
    for (const auto &iter : mBindings)
    {
        if (iter.second.location == location)
        {
            return iter.second.location;
        }
    }
    return -1;
}

template <typename T>
int ProgramAliasedBindings::getBinding(const T &variable) const
{
    const std::string &name = variable.name;

    // Check with the normalized array name if applicable.
    if (variable.isArray())
    {
        size_t nameLengthWithoutArrayIndex;
        unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
        if (arrayIndex == 0)
        {
            std::string baseName = name.substr(0u, nameLengthWithoutArrayIndex);
            auto iter            = mBindings.find(baseName);
            // If "name" exists and is not aliased, that means it was modified more
            // recently than its "name[0]" form and should be used instead of that.
            if (iter != mBindings.end() && !iter->second.aliased)
            {
                return iter->second.location;
            }
        }
        else if (arrayIndex == GL_INVALID_INDEX)
        {
            auto iter = mBindings.find(variable.name);
            // If "name" exists and is not aliased, that means it was modified more
            // recently than its "name[0]" form and should be used instead of that.
            if (iter != mBindings.end() && !iter->second.aliased)
            {
                return iter->second.location;
            }
            // The base name was aliased, so use the name with the array notation.
            return getBindingByName(name + "[0]");
        }
    }

    return getBindingByName(name);
}
template int ProgramAliasedBindings::getBinding<UsedUniform>(const UsedUniform &variable) const;
template int ProgramAliasedBindings::getBinding<ProgramOutput>(const ProgramOutput &variable) const;
template int ProgramAliasedBindings::getBinding<sh::ShaderVariable>(
    const sh::ShaderVariable &variable) const;

ProgramAliasedBindings::const_iterator ProgramAliasedBindings::begin() const
{
    return mBindings.begin();
}

ProgramAliasedBindings::const_iterator ProgramAliasedBindings::end() const
{
    return mBindings.end();
}

std::map<std::string, ProgramBinding> ProgramAliasedBindings::getStableIterationMap() const
{
    return std::map<std::string, ProgramBinding>(mBindings.begin(), mBindings.end());
}

// ProgramState implementation.
ProgramState::ProgramState(rx::GLImplFactory *factory)
    : mLabel(),
      mAttachedShaders{},
      mTransformFeedbackBufferMode(GL_INTERLEAVED_ATTRIBS),
      mBinaryRetrieveableHint(false),
      mSeparable(false),
      mExecutable(new ProgramExecutable(factory, &mInfoLog))
{}

ProgramState::~ProgramState()
{
    ASSERT(!hasAnyAttachedShader());
}

const std::string &ProgramState::getLabel()
{
    return mLabel;
}

SharedCompiledShaderState ProgramState::getAttachedShader(ShaderType shaderType) const
{
    ASSERT(shaderType != ShaderType::InvalidEnum);
    return mAttachedShaders[shaderType];
}

bool ProgramState::hasAnyAttachedShader() const
{
    for (const SharedCompiledShaderState &shader : mAttachedShaders)
    {
        if (shader)
        {
            return true;
        }
    }
    return false;
}

ShaderType ProgramState::getAttachedTransformFeedbackStage() const
{
    if (mAttachedShaders[ShaderType::Geometry])
    {
        return ShaderType::Geometry;
    }
    if (mAttachedShaders[ShaderType::TessEvaluation])
    {
        return ShaderType::TessEvaluation;
    }
    return ShaderType::Vertex;
}

// The common portion of parallel link and load jobs
class Program::MainLinkLoadTask : public angle::Closure
{
  public:
    MainLinkLoadTask(const std::shared_ptr<angle::WorkerThreadPool> &subTaskWorkerPool,
                     ProgramState *state,
                     std::shared_ptr<rx::LinkTask> &&linkTask)
        : mSubTaskWorkerPool(subTaskWorkerPool),
          mState(*state),
          mLinkTask(std::move(linkTask)),
          mAreSubTasksOptional(false)
    {
        ASSERT(subTaskWorkerPool.get());
    }
    ~MainLinkLoadTask() override = default;

    angle::Result getResult(const Context *context)
    {
        InfoLog &infoLog = mState.getExecutable().getInfoLog();

        ANGLE_TRY(mResult);
        ANGLE_TRY(mLinkTask->getResult(context, infoLog));

        // Don't wait for optional subtasks
        if (!mAreSubTasksOptional)
        {
            for (const std::shared_ptr<rx::LinkSubTask> &task : mSubTasks)
            {
                ANGLE_TRY(task->getResult(context, infoLog));
            }
        }

        return angle::Result::Continue;
    }

    void waitSubTasks()
    {
        if (!mAreSubTasksOptional)
        {
            angle::WaitableEvent::WaitMany(&mSubTaskWaitableEvents);
        }
    }

    bool areSubTasksLinking()
    {
        if (mLinkTask->isLinkingInternally())
        {
            return true;
        }
        return !mAreSubTasksOptional && !angle::WaitableEvent::AllReady(&mSubTaskWaitableEvents);
    }

    void retrieveOptionalSubTasks(
        std::vector<std::shared_ptr<rx::LinkSubTask>> *subTasksOut,
        std::vector<std::shared_ptr<angle::WaitableEvent>> *subTaskEventsOut)
    {
        ASSERT(subTasksOut->empty());
        ASSERT(subTaskEventsOut->empty());

        if (mAreSubTasksOptional)
        {
            *subTasksOut      = std::move(mSubTasks);
            *subTaskEventsOut = std::move(mSubTaskWaitableEvents);
        }
    }

  protected:
    void scheduleSubTasks(std::vector<std::shared_ptr<rx::LinkSubTask>> &&subTasks)
    {
        mSubTasks = std::move(subTasks);

        mSubTaskWaitableEvents.reserve(mSubTasks.size());
        for (const std::shared_ptr<rx::LinkSubTask> &subTask : mSubTasks)
        {
            mSubTaskWaitableEvents.push_back(mSubTaskWorkerPool->postWorkerTask(subTask));
        }
    }

    std::shared_ptr<angle::WorkerThreadPool> mSubTaskWorkerPool;
    ProgramState &mState;
    std::shared_ptr<rx::LinkTask> mLinkTask;

    // Subtask wait events
    std::vector<std::shared_ptr<rx::LinkSubTask>> mSubTasks;
    std::vector<std::shared_ptr<angle::WaitableEvent>> mSubTaskWaitableEvents;
    // If optional, the subtasks 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.
    bool mAreSubTasksOptional;

    // The result of the front-end portion of the link.  The backend's result is retrieved via
    // mLinkTask->getResult().  The subtask results are retrieved via mSubTasks similarly.
    angle::Result mResult;
};

class Program::MainLinkTask final : public Program::MainLinkLoadTask
{
  public:
    MainLinkTask(const std::shared_ptr<angle::WorkerThreadPool> &subTaskWorkerPool,
                 const Caps &caps,
                 const Limitations &limitations,
                 const Version &clientVersion,
                 bool isWebGL,
                 Program *program,
                 ProgramState *state,
                 LinkingVariables *linkingVariables,
                 ProgramLinkedResources *resources,
                 std::shared_ptr<rx::LinkTask> &&linkTask)
        : MainLinkLoadTask(subTaskWorkerPool, state, std::move(linkTask)),
          mCaps(caps),
          mLimitations(limitations),
          mClientVersion(clientVersion),
          mIsWebGL(isWebGL),
          mProgram(program),
          mLinkingVariables(linkingVariables),
          mResources(resources)
    {}
    ~MainLinkTask() override = default;

    void operator()() override { mResult = linkImpl(); }

  private:
    angle::Result linkImpl();

    // State needed for link
    const Caps &mCaps;
    const Limitations &mLimitations;
    const Version mClientVersion;
    const bool mIsWebGL;
    Program *mProgram;
    LinkingVariables *mLinkingVariables;
    ProgramLinkedResources *mResources;
};

class Program::MainLoadTask final : public Program::MainLinkLoadTask
{
  public:
    MainLoadTask(const std::shared_ptr<angle::WorkerThreadPool> &subTaskWorkerPool,
                 Program *program,
                 ProgramState *state,
                 std::shared_ptr<rx::LinkTask> &&loadTask)
        : MainLinkLoadTask(subTaskWorkerPool, state, std::move(loadTask))
    {}
    ~MainLoadTask() override = default;

    void operator()() override { mResult = loadImpl(); }

  private:
    angle::Result loadImpl();
};

class Program::MainLinkLoadEvent final : public LinkEvent
{
  public:
    MainLinkLoadEvent(const std::shared_ptr<MainLinkLoadTask> &linkTask,
                      const std::shared_ptr<angle::WaitableEvent> &waitEvent)
        : mLinkTask(linkTask), mWaitableEvent(waitEvent)
    {}
    ~MainLinkLoadEvent() override {}

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

        mWaitableEvent->wait();
        mLinkTask->waitSubTasks();

        return mLinkTask->getResult(context);
    }
    bool isLinking() override
    {
        return !mWaitableEvent->isReady() || mLinkTask->areSubTasksLinking();
    }

    void retrieveOptionalSubTasks(
        std::vector<std::shared_ptr<rx::LinkSubTask>> *subTasksOut,
        std::vector<std::shared_ptr<angle::WaitableEvent>> *subTaskEventsOut) override
    {
        mLinkTask->retrieveOptionalSubTasks(subTasksOut, subTaskEventsOut);
    }

  private:
    std::shared_ptr<MainLinkLoadTask> mLinkTask;
    std::shared_ptr<angle::WaitableEvent> mWaitableEvent;
};

angle::Result Program::MainLinkTask::linkImpl()
{
    ProgramMergedVaryings mergedVaryings;

    // Do the front-end portion of the link.
    ANGLE_TRY(mProgram->linkJobImpl(mCaps, mLimitations, mClientVersion, mIsWebGL,
                                    mLinkingVariables, mResources, &mergedVaryings));

    // Next, do the backend portion of the link.  If there are any subtasks to be scheduled, they
    // are collected now.
    std::vector<std::shared_ptr<rx::LinkSubTask>> subTasks =
        mLinkTask->link(*mResources, mergedVaryings, &mAreSubTasksOptional);

    // Must be after backend's link to avoid misleading the linker about input/output variables.
    mState.updateProgramInterfaceInputs();
    mState.updateProgramInterfaceOutputs();

    // Schedule the subtasks
    scheduleSubTasks(std::move(subTasks));

    return angle::Result::Continue;
}

angle::Result Program::MainLoadTask::loadImpl()
{
    std::vector<std::shared_ptr<rx::LinkSubTask>> subTasks = mLinkTask->load(&mAreSubTasksOptional);

    // Schedule the subtasks
    scheduleSubTasks(std::move(subTasks));

    return angle::Result::Continue;
}

Program::Program(rx::GLImplFactory *factory, ShaderProgramManager *manager, ShaderProgramID handle)
    : mSerial(factory->generateSerial()),
      mState(factory),
      mProgram(factory->createProgram(mState)),
      mValidated(false),
      mDeleteStatus(false),
      mLinked(false),
      mProgramHash{0},
      mRefCount(0),
      mResourceManager(manager),
      mHandle(handle),
      mAttachedShaders{}
{
    ASSERT(mProgram);

    unlink();
}

Program::~Program()
{
    ASSERT(!mProgram);
    ASSERT(mOptionalLinkTasks.empty());
    ASSERT(mOptionalLinkTaskWaitableEvents.empty());
}

void Program::onDestroy(const Context *context)
{
    resolveLink(context);
    waitForOptionalLinkTasks(context);

    for (ShaderType shaderType : AllShaderTypes())
    {
        Shader *shader = getAttachedShader(shaderType);
        if (shader != nullptr)
        {
            shader->release(context);
        }
        mState.mShaderCompileJobs[shaderType].reset();
        mState.mAttachedShaders[shaderType].reset();
        mAttachedShaders[shaderType] = nullptr;
    }

    mProgram->destroy(context);
    UninstallExecutable(context, &mState.mExecutable);

    ASSERT(!mState.hasAnyAttachedShader());
    SafeDelete(mProgram);

    delete this;
}
ShaderProgramID Program::id() const
{
    return mHandle;
}

angle::Result Program::setLabel(const Context *context, const std::string &label)
{
    ASSERT(!mLinkingState);
    mState.mLabel = label;

    if (mProgram)
    {
        return mProgram->onLabelUpdate(context);
    }
    return angle::Result::Continue;
}

const std::string &Program::getLabel() const
{
    ASSERT(!mLinkingState);
    return mState.mLabel;
}

void Program::attachShader(const Context *context, Shader *shader)
{
    resolveLink(context);
    onLinkInputChange(context);

    ShaderType shaderType = shader->getType();
    ASSERT(shaderType != ShaderType::InvalidEnum);

    shader->addRef();
    mAttachedShaders[shaderType] = shader;
}

void Program::detachShader(const Context *context, Shader *shader)
{
    resolveLink(context);
    onLinkInputChange(context);

    ShaderType shaderType = shader->getType();
    ASSERT(shaderType != ShaderType::InvalidEnum);

    ASSERT(mAttachedShaders[shaderType] == shader);
    shader->release(context);
    mAttachedShaders[shaderType] = nullptr;
    mState.mShaderCompileJobs[shaderType].reset();
    mState.mAttachedShaders[shaderType].reset();
}

int Program::getAttachedShadersCount() const
{
    ASSERT(!mLinkingState);
    int numAttachedShaders = 0;
    for (const Shader *shader : mAttachedShaders)
    {
        if (shader != nullptr)
        {
            ++numAttachedShaders;
        }
    }

    return numAttachedShaders;
}

Shader *Program::getAttachedShader(ShaderType shaderType) const
{
    return mAttachedShaders[shaderType];
}

void Program::bindAttributeLocation(const Context *context, GLuint index, const char *name)
{
    onLinkInputChange(context);

    ASSERT(!mLinkingState);
    mState.mAttributeBindings.bindLocation(index, name);
}

void Program::bindUniformLocation(const Context *context,
                                  UniformLocation location,
                                  const char *name)
{
    onLinkInputChange(context);

    ASSERT(!mLinkingState);
    mState.mUniformLocationBindings.bindLocation(location.value, name);
}

void Program::bindFragmentOutputLocation(const Context *context, GLuint index, const char *name)
{
    onLinkInputChange(context);

    ASSERT(!mLinkingState);
    mState.mFragmentOutputLocations.bindLocation(index, name);
}

void Program::bindFragmentOutputIndex(const Context *context, GLuint index, const char *name)
{
    onLinkInputChange(context);

    ASSERT(!mLinkingState);
    mState.mFragmentOutputIndexes.bindLocation(index, name);
}

void Program::makeNewExecutable(const Context *context)
{
    ASSERT(!mLinkingState);
    waitForOptionalLinkTasks(context);

    // Unlink the program, but do not clear the validation-related caching yet, since we can still
    // use the previously linked program if linking the shaders fails.
    mLinked = false;

    mLinkingState = std::make_unique<LinkingState>();

    // By default, set the link event as failing.  If link succeeds, it will be replaced by the
    // appropriate event.
    mLinkingState->linkEvent = std::make_unique<LinkEventDone>(angle::Result::Stop);

    InstallExecutable(
        context,
        std::make_shared<ProgramExecutable>(context->getImplementation(), &mState.mInfoLog),
        &mState.mExecutable);
    onStateChange(angle::SubjectMessage::ProgramUnlinked);
}

angle::Result Program::link(const Context *context, angle::JobResultExpectancy resultExpectancy)
{
    auto *platform   = ANGLEPlatformCurrent();
    double startTime = platform->currentTime(platform);

    // Create a new executable to hold the result of the link.  The previous executable may still be
    // referenced by the contexts the program is current on, and any program pipelines it may be
    // used in.  Once link succeeds, the users of the program are notified to update their
    // executables.
    makeNewExecutable(context);

    // For every attached shader, get the compile job and compiled state.  This is done at link time
    // (instead of earlier, such as attachShader time), because the shader could get recompiled
    // between attach and link.
    //
    // Additionally, make sure the backend is also able to cache the compiled state of its own
    // ShaderImpl objects.
    ShaderMap<rx::ShaderImpl *> shaderImpls = {};
    for (ShaderType shaderType : AllShaderTypes())
    {
        Shader *shader = mAttachedShaders[shaderType];
        SharedCompileJob compileJob;
        SharedCompiledShaderState shaderCompiledState;
        if (shader != nullptr)
        {
            compileJob              = shader->getCompileJob(&shaderCompiledState);
            shaderImpls[shaderType] = shader->getImplementation();
        }
        mState.mShaderCompileJobs[shaderType] = std::move(compileJob);
        mState.mAttachedShaders[shaderType]   = std::move(shaderCompiledState);
    }
    mProgram->prepareForLink(shaderImpls);

    const angle::FrontendFeatures &frontendFeatures = context->getFrontendFeatures();
    if (frontendFeatures.dumpShaderSource.enabled)
    {
        dumpProgramInfo(context);
    }

    // Make sure the executable state is in sync with the program.
    //
    // The transform feedback buffer mode is duplicated in the executable as is the only link-input
    // that is also needed at draw time.
    //
    // The transform feedback varying names are duplicated because the program pipeline link is not
    // currently able to use the link result of the program directly (and redoes the link, using
    // these names).
    //
    // The isSeparable state is duplicated for convenience; it is used when setting sampler/image
    // uniforms.
    mState.mExecutable->mPod.transformFeedbackBufferMode = mState.mTransformFeedbackBufferMode;
    mState.mExecutable->mTransformFeedbackVaryingNames   = mState.mTransformFeedbackVaryingNames;
    mState.mExecutable->mPod.isSeparable                 = mState.mSeparable;

    mState.mInfoLog.reset();

    mProgramHash              = {0};
    MemoryProgramCache *cache = context->getMemoryProgramCache();

    // TODO: http://anglebug.com/4530: Enable program caching for separable programs
    if (cache && !isSeparable())
    {
        std::lock_guard<std::mutex> cacheLock(context->getProgramCacheMutex());
        bool success = false;
        ANGLE_TRY(cache->getProgram(context, this, &mProgramHash, &success));

        if (success)
        {
            // No need to care about the compile jobs any more.
            mState.mShaderCompileJobs = {};

            std::scoped_lock lock(mHistogramMutex);
            // Succeeded in loading the binaries in the front-end, back end may still be loading
            // asynchronously
            double delta = platform->currentTime(platform) - startTime;
            int us       = static_cast<int>(delta * 1000'000.0);
            ANGLE_HISTOGRAM_COUNTS("GPU.ANGLE.ProgramCache.ProgramCacheHitTimeUS", us);
            return angle::Result::Continue;
        }
    }

    const Caps &caps               = context->getCaps();
    const Limitations &limitations = context->getLimitations();
    const Version &clientVersion   = context->getClientVersion();
    const bool isWebGL             = context->isWebGL();

    // Ask the backend to prepare the link task.
    std::shared_ptr<rx::LinkTask> linkTask;
    ANGLE_TRY(mProgram->link(context, &linkTask));

    std::unique_ptr<LinkingState> linkingState = std::make_unique<LinkingState>();

    // Prepare the main link job
    std::shared_ptr<MainLinkLoadTask> mainLinkTask(new MainLinkTask(
        context->getLinkSubTaskThreadPool(), caps, limitations, clientVersion, isWebGL, this,
        &mState, &linkingState->linkingVariables, &linkingState->resources, std::move(linkTask)));

    // While the subtasks are currently always thread-safe, the main task is not safe on all
    // backends.  A front-end feature selects whether the single-threaded pool must be used.
    const angle::JobThreadSafety threadSafety =
        context->getFrontendFeatures().linkJobIsThreadSafe.enabled ? angle::JobThreadSafety::Safe
                                                                   : angle::JobThreadSafety::Unsafe;
    std::shared_ptr<angle::WaitableEvent> mainLinkEvent =
        context->postCompileLinkTask(mainLinkTask, threadSafety, resultExpectancy);

    mLinkingState                    = std::move(linkingState);
    mLinkingState->linkingFromBinary = false;
    mLinkingState->linkEvent = std::make_unique<MainLinkLoadEvent>(mainLinkTask, mainLinkEvent);

    return angle::Result::Continue;
}

angle::Result Program::linkJobImpl(const Caps &caps,
                                   const Limitations &limitations,
                                   const Version &clientVersion,
                                   bool isWebGL,
                                   LinkingVariables *linkingVariables,
                                   ProgramLinkedResources *resources,
                                   ProgramMergedVaryings *mergedVaryingsOut)
{
    // Cache load failed, fall through to normal linking.
    unlink();

    // Validate we have properly attached shaders after checking the cache.  Since the input to the
    // shaders is part of the cache key, if there was a cache hit, the shaders would have linked
    // correctly.
    if (!linkValidateShaders())
    {
        return angle::Result::Stop;
    }

    linkShaders();

    linkingVariables->initForProgram(mState);
    resources->init(&mState.mExecutable->mUniformBlocks, &mState.mExecutable->mUniforms,
                    &mState.mExecutable->mUniformNames, &mState.mExecutable->mUniformMappedNames,
                    &mState.mExecutable->mShaderStorageBlocks,
                    &mState.mExecutable->mBufferVariables,
                    &mState.mExecutable->mAtomicCounterBuffers);

    updateLinkedShaderStages();

    InitUniformBlockLinker(mState, &resources->uniformBlockLinker);
    InitShaderStorageBlockLinker(mState, &resources->shaderStorageBlockLinker);

    if (mState.mAttachedShaders[ShaderType::Compute])
    {
        GLuint combinedImageUniforms = 0;
        if (!linkUniforms(caps, clientVersion, &resources->unusedUniforms, &combinedImageUniforms))
        {
            return angle::Result::Stop;
        }

        GLuint combinedShaderStorageBlocks = 0u;
        if (!LinkValidateProgramInterfaceBlocks(
                caps, clientVersion, isWebGL, mState.mExecutable->getLinkedShaderStages(),
                *resources, mState.mInfoLog, &combinedShaderStorageBlocks))
        {
            return angle::Result::Stop;
        }

        // [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 (combinedImageUniforms + combinedShaderStorageBlocks >
            static_cast<GLuint>(caps.maxCombinedShaderOutputResources))
        {
            mState.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 angle::Result::Stop;
        }
    }
    else
    {
        if (!linkAttributes(caps, limitations, isWebGL))
        {
            return angle::Result::Stop;
        }

        if (!linkVaryings())
        {
            return angle::Result::Stop;
        }

        GLuint combinedImageUniforms = 0;
        if (!linkUniforms(caps, clientVersion, &resources->unusedUniforms, &combinedImageUniforms))
        {
            return angle::Result::Stop;
        }

        GLuint combinedShaderStorageBlocks = 0u;
        if (!LinkValidateProgramInterfaceBlocks(
                caps, clientVersion, isWebGL, mState.mExecutable->getLinkedShaderStages(),
                *resources, mState.mInfoLog, &combinedShaderStorageBlocks))
        {
            return angle::Result::Stop;
        }

        if (!LinkValidateProgramGlobalNames(mState.mInfoLog, getExecutable(), *linkingVariables))
        {
            return angle::Result::Stop;
        }

        const SharedCompiledShaderState &vertexShader = mState.mAttachedShaders[ShaderType::Vertex];
        if (vertexShader)
        {
            mState.mExecutable->mPod.numViews        = vertexShader->numViews;
            mState.mExecutable->mPod.hasClipDistance = vertexShader->hasClipDistance;
            mState.mExecutable->mPod.specConstUsageBits |= vertexShader->specConstUsageBits;
        }

        const SharedCompiledShaderState &fragmentShader =
            mState.mAttachedShaders[ShaderType::Fragment];
        if (fragmentShader)
        {
            ASSERT(mState.mExecutable->mOutputVariables.empty());
            mState.mExecutable->mOutputVariables.reserve(
                fragmentShader->activeOutputVariables.size());
            for (const sh::ShaderVariable &shaderVariable : fragmentShader->activeOutputVariables)
            {
                mState.mExecutable->mOutputVariables.emplace_back(shaderVariable);
            }
            if (!mState.mExecutable->linkValidateOutputVariables(
                    caps, clientVersion, combinedImageUniforms, combinedShaderStorageBlocks,
                    fragmentShader->shaderVersion, mState.mFragmentOutputLocations,
                    mState.mFragmentOutputIndexes))
            {
                return angle::Result::Stop;
            }

            mState.mExecutable->mPod.hasDiscard = fragmentShader->hasDiscard;
            mState.mExecutable->mPod.enablesPerSampleShading =
                fragmentShader->enablesPerSampleShading;
            mState.mExecutable->mPod.advancedBlendEquations =
                fragmentShader->advancedBlendEquations;
            mState.mExecutable->mPod.specConstUsageBits |= fragmentShader->specConstUsageBits;
        }

        *mergedVaryingsOut = GetMergedVaryingsFromLinkingVariables(*linkingVariables);
        if (!mState.mExecutable->linkMergedVaryings(caps, limitations, clientVersion, isWebGL,
                                                    *mergedVaryingsOut, *linkingVariables,
                                                    &resources->varyingPacking))
        {
            return angle::Result::Stop;
        }
    }

    mState.mExecutable->saveLinkedStateInfo(mState);

    return angle::Result::Continue;
}

bool Program::isLinking() const
{
    return mLinkingState.get() && mLinkingState->linkEvent && mLinkingState->linkEvent->isLinking();
}

void Program::resolveLinkImpl(const Context *context)
{
    ASSERT(mLinkingState.get());

    angle::Result result = mLinkingState->linkEvent->wait(context);

    mLinkingState->linkEvent->retrieveOptionalSubTasks(&mOptionalLinkTasks,
                                                       &mOptionalLinkTaskWaitableEvents);

    mLinked                                    = result == angle::Result::Continue;
    std::unique_ptr<LinkingState> linkingState = std::move(mLinkingState);
    if (!mLinked)
    {
        // If the link fails, the spec allows program queries to either return empty results (all
        // zeros) or whatever parts of the link happened to have been done before the failure:
        //
        // > Implementations may return information on variables and interface blocks that would
        // > have been active had the program been linked successfully.  In cases where the link
        // > failed because the program required too many resources, these commands may help
        // > applications determine why limits were exceeded. However, the information returned in
        // > this case is implementation-dependent and may be incomplete.
        //
        // The above means that it's ok for ANGLE to reset the executable here, but it *may* be
        // helpful to applications if it doesn't.  We do reset it however, the info log should
        // already have enough debug information for the application.
        mState.mExecutable->reset();
        return;
    }

    // According to GLES 3.0/3.1 spec for LinkProgram and UseProgram,
    // Only successfully linked program can replace the executables.
    ASSERT(mLinked);

    // Mark implementation-specific unreferenced uniforms as ignored.
    std::vector<ImageBinding> *imageBindings = getExecutable().getImageBindings();
    mProgram->markUnusedUniformLocations(&mState.mExecutable->mUniformLocations,
                                         &mState.mExecutable->mSamplerBindings, imageBindings);

    // Must be called after markUnusedUniformLocations.
    postResolveLink(context);

    // Notify observers that a new linked executable is available.  If this program is current on a
    // context, the executable is reinstalled.  If it is attached to a PPO, it is installed there
    // and the PPO is marked as needing to be linked again.
    onStateChange(angle::SubjectMessage::ProgramRelinked);

    // Cache the program if:
    //
    // - Not loading from binary, in which case the program is already in the cache.
    // - There are no pending subtasks.  If there are any, waitForOptionalLinkTasks will do this
    //   instead.
    //   * Note that serialize() calls waitForOptionalLinkTasks, so caching the binary here
    //     effectively forces a wait for the subtasks.
    //
    if (!linkingState->linkingFromBinary && mOptionalLinkTasks.empty())
    {
        cacheProgramBinary(context);
    }
}

void Program::waitForOptionalLinkTasks(const Context *context)
{
    if (mOptionalLinkTasks.empty())
    {
        return;
    }

    // Wait for all optional tasks to finish
    angle::WaitableEvent::WaitMany(&mOptionalLinkTaskWaitableEvents);

    // Get results and clean up
    for (const std::shared_ptr<rx::LinkSubTask> &task : mOptionalLinkTasks)
    {
        // As these tasks are optional, their results are ignored.  Failure is harmless, but more
        // importantly the error (effectively due to a link event) may not be allowed through the
        // entry point that results in this call.
        InfoLog infoLog;
        angle::Result result = task->getResult(context, infoLog);
        if (result != angle::Result::Continue)
        {
            WARN() << "Optional link task unexpectedly failed";
            WARN() << "Performance may degrade, or device may soon be lost";
        }
    }

    mOptionalLinkTasks.clear();
    mOptionalLinkTaskWaitableEvents.clear();

    // Now that the subtasks are done, cache the binary (this was deferred in resolveLinkImpl).
    cacheProgramBinary(context);
}

void Program::updateLinkedShaderStages()
{
    mState.mExecutable->resetLinkedShaderStages();

    for (ShaderType shaderType : AllShaderTypes())
    {
        if (mState.mAttachedShaders[shaderType])
        {
            mState.mExecutable->setLinkedShaderStages(shaderType);
        }
    }
}

void ProgramState::updateActiveSamplers()
{
    mExecutable->mActiveSamplerRefCounts.fill(0);
    mExecutable->updateActiveSamplers(*mExecutable);
}

void ProgramState::updateProgramInterfaceInputs()
{
    const ShaderType firstAttachedShaderType = mExecutable->getFirstLinkedShaderStageType();

    if (firstAttachedShaderType == ShaderType::Vertex)
    {
        // Vertex attributes are already what we need, so nothing to do
        return;
    }

    const SharedCompiledShaderState &shader = getAttachedShader(firstAttachedShaderType);
    ASSERT(shader);

    // Copy over each input varying, since the Shader could go away
    if (shader->shaderType == ShaderType::Compute)
    {
        for (const sh::ShaderVariable &attribute : shader->allAttributes)
        {
            // Compute Shaders have the following built-in input variables.
            //
            // in uvec3 gl_NumWorkGroups;
            // in uvec3 gl_WorkGroupID;
            // in uvec3 gl_LocalInvocationID;
            // in uvec3 gl_GlobalInvocationID;
            // in uint  gl_LocalInvocationIndex;
            // They are all vecs or uints, so no special handling is required.
            mExecutable->mProgramInputs.emplace_back(attribute);
        }
    }
    else
    {
        for (const sh::ShaderVariable &varying : shader->inputVaryings)
        {
            UpdateInterfaceVariable(&mExecutable->mProgramInputs, varying);
        }
    }
}

void ProgramState::updateProgramInterfaceOutputs()
{
    const ShaderType lastAttachedShaderType = mExecutable->getLastLinkedShaderStageType();

    if (lastAttachedShaderType == ShaderType::Fragment)
    {
        // Fragment outputs are already what we need, so nothing to do
        return;
    }
    if (lastAttachedShaderType == ShaderType::Compute)
    {
        // If the program only contains a Compute Shader, then there are no user-defined outputs.
        return;
    }

    const SharedCompiledShaderState &shader = getAttachedShader(lastAttachedShaderType);
    ASSERT(shader);

    // Copy over each output varying, since the Shader could go away
    for (const sh::ShaderVariable &varying : shader->outputVaryings)
    {
        UpdateInterfaceVariable(&mExecutable->mOutputVariables, varying);
    }
}

// Returns the program object to an unlinked state, before re-linking, or at destruction
void Program::unlink()
{
    // There is always a new executable created on link, so the executable is already in a clean
    // state.

    mValidated = false;
}

angle::Result Program::setBinary(const Context *context,
                                 GLenum binaryFormat,
                                 const void *binary,
                                 GLsizei length)
{
    ASSERT(binaryFormat == GL_PROGRAM_BINARY_ANGLE);

    makeNewExecutable(context);

    bool success = false;
    return loadBinary(context, binary, length, &success);
}

angle::Result Program::loadBinary(const Context *context,
                                  const void *binary,
                                  GLsizei length,
                                  bool *successOut)
{
    ASSERT(mLinkingState);
    unlink();

    BinaryInputStream stream(binary, length);
    if (!deserialize(context, stream))
    {
        return angle::Result::Continue;
    }
    // Currently we require the full shader text to compute the program hash.
    // We could also store the binary in the internal program cache.

    for (size_t uniformBlockIndex = 0;
         uniformBlockIndex < mState.mExecutable->getUniformBlocks().size(); ++uniformBlockIndex)
    {
        // After deserializing, we need to set every block dirty
        mState.mExecutable->mDirtyBits.set(uniformBlockIndex);
    }

    // If load does not succeed, we know for sure that the binary is not compatible with the
    // backend.  The loaded binary could have been read from the on-disk shader cache and be
    // corrupted or serialized with different revision and subsystem id than the currently loaded
    // backend.  Returning to the caller results in link happening using the original shader
    // sources.
    std::shared_ptr<rx::LinkTask> loadTask;
    ANGLE_TRY(mProgram->load(context, &stream, &loadTask, successOut));
    if (!*successOut)
    {
        return angle::Result::Continue;
    }

    std::unique_ptr<LinkEvent> loadEvent;
    if (loadTask)
    {
        std::shared_ptr<MainLinkLoadTask> mainLoadTask(new MainLoadTask(
            context->getLinkSubTaskThreadPool(), this, &mState, std::move(loadTask)));

        std::shared_ptr<angle::WaitableEvent> mainLoadEvent =
            context->getShaderCompileThreadPool()->postWorkerTask(mainLoadTask);
        loadEvent = std::make_unique<MainLinkLoadEvent>(mainLoadTask, mainLoadEvent);
    }
    else
    {
        loadEvent = std::make_unique<LinkEventDone>(angle::Result::Continue);
    }

    mLinkingState->linkingFromBinary = true;
    mLinkingState->linkEvent         = std::move(loadEvent);

    *successOut = true;

    return angle::Result::Continue;
}

angle::Result Program::getBinary(Context *context,
                                 GLenum *binaryFormat,
                                 void *binary,
                                 GLsizei bufSize,
                                 GLsizei *length)
{
    ASSERT(!mLinkingState);
    if (binaryFormat)
    {
        *binaryFormat = GL_PROGRAM_BINARY_ANGLE;
    }

    angle::MemoryBuffer memoryBuf;
    ANGLE_TRY(serialize(context, &memoryBuf));

    GLsizei streamLength       = static_cast<GLsizei>(memoryBuf.size());
    const uint8_t *streamState = memoryBuf.data();

    if (streamLength > bufSize)
    {
        if (length)
        {
            *length = 0;
        }

        // TODO: This should be moved to the validation layer but computing the size of the binary
        // before saving it causes the save to happen twice.  It may be possible to write the binary
        // to a separate buffer, validate sizes and then copy it.
        ANGLE_CHECK(context, false, "Insufficient buffer size", GL_INVALID_OPERATION);
    }

    if (binary)
    {
        char *ptr = reinterpret_cast<char *>(binary);

        memcpy(ptr, streamState, streamLength);
        ptr += streamLength;

        ASSERT(ptr - streamLength == binary);
    }

    if (length)
    {
        *length = streamLength;
    }

    return angle::Result::Continue;
}

GLint Program::getBinaryLength(Context *context)
{
    ASSERT(!mLinkingState);
    if (!mLinked)
    {
        return 0;
    }

    GLint length;
    angle::Result result =
        getBinary(context, nullptr, nullptr, std::numeric_limits<GLint>::max(), &length);
    if (result != angle::Result::Continue)
    {
        return 0;
    }

    return length;
}

void Program::setBinaryRetrievableHint(bool retrievable)
{
    ASSERT(!mLinkingState);
    // TODO(jmadill) : replace with dirty bits
    mProgram->setBinaryRetrievableHint(retrievable);
    mState.mBinaryRetrieveableHint = retrievable;
}

bool Program::getBinaryRetrievableHint() const
{
    ASSERT(!mLinkingState);
    return mState.mBinaryRetrieveableHint;
}

int Program::getInfoLogLength() const
{
    return static_cast<int>(mState.mInfoLog.getLength());
}

void Program::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const
{
    return mState.mInfoLog.getLog(bufSize, length, infoLog);
}

void Program::setSeparable(const Context *context, bool separable)
{
    ASSERT(!mLinkingState);
    onLinkInputChange(context);

    if (isSeparable() != separable)
    {
        mProgram->setSeparable(separable);
        mState.mSeparable = separable;
    }
}

void Program::deleteSelf(const Context *context)
{
    ASSERT(mRefCount == 0 && mDeleteStatus);
    mResourceManager->deleteProgram(context, mHandle);
}

unsigned int Program::getRefCount() const
{
    return mRefCount;
}

void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, ShaderProgramID *shaders) const
{
    int total = 0;

    for (const Shader *shader : mAttachedShaders)
    {
        if (shader != nullptr && total < maxCount)
        {
            shaders[total] = shader->getHandle();
            ++total;
        }
    }

    if (count)
    {
        *count = total;
    }
}

void Program::flagForDeletion()
{
    ASSERT(!mLinkingState);
    mDeleteStatus = true;
}

bool Program::isFlaggedForDeletion() const
{
    ASSERT(!mLinkingState);
    return mDeleteStatus;
}

void Program::validate(const Caps &caps)
{
    ASSERT(!mLinkingState);
    mState.mInfoLog.reset();

    if (mLinked)
    {
        mValidated = ConvertToBool(mProgram->validate(caps));
    }
    else
    {
        mState.mInfoLog << "Program has not been successfully linked.";
    }
}

bool Program::isValidated() const
{
    ASSERT(!mLinkingState);
    return mValidated;
}

void Program::bindUniformBlock(UniformBlockIndex uniformBlockIndex, GLuint uniformBlockBinding)
{
    ASSERT(!mLinkingState);

    if (mState.mExecutable->mPod.activeUniformBlockBindings[uniformBlockIndex.value])
    {
        GLuint previousBinding =
            mState.mExecutable->mUniformBlocks[uniformBlockIndex.value].pod.binding;
        if (previousBinding >= mUniformBlockBindingMasks.size())
        {
            mUniformBlockBindingMasks.resize(previousBinding + 1, UniformBlockBindingMask());
        }
        mUniformBlockBindingMasks[previousBinding].reset(uniformBlockIndex.value);
    }

    mState.mExecutable->mUniformBlocks[uniformBlockIndex.value].setBinding(uniformBlockBinding);
    if (uniformBlockBinding >= mUniformBlockBindingMasks.size())
    {
        mUniformBlockBindingMasks.resize(uniformBlockBinding + 1, UniformBlockBindingMask());
    }
    mUniformBlockBindingMasks[uniformBlockBinding].set(uniformBlockIndex.value);
    mState.mExecutable->mPod.activeUniformBlockBindings.set(uniformBlockIndex.value,
                                                            uniformBlockBinding != 0);

    onUniformBufferStateChange(
        gl::ProgramExecutable::DirtyBitType::DIRTY_BIT_UNIFORM_BLOCK_BINDING_0 +
        uniformBlockIndex.value);
}

void Program::setTransformFeedbackVaryings(const Context *context,
                                           GLsizei count,
                                           const GLchar *const *varyings,
                                           GLenum bufferMode)
{
    ASSERT(!mLinkingState);
    onLinkInputChange(context);

    mState.mTransformFeedbackVaryingNames.resize(count);
    for (GLsizei i = 0; i < count; i++)
    {
        mState.mTransformFeedbackVaryingNames[i] = varyings[i];
    }

    mState.mTransformFeedbackBufferMode = bufferMode;
}

bool Program::linkValidateShaders()
{
    // Wait for attached shaders to finish compilation.  At this point, they need to be checked
    // whether they successfully compiled.  This information is cached so that all compile jobs can
    // be waited on and their corresponding objects released before the actual check.
    //
    // Note that this function is called from the link job, and is therefore not protected by any
    // locks.
    ShaderBitSet successfullyCompiledShaders;
    for (ShaderType shaderType : AllShaderTypes())
    {
        const SharedCompileJob &compileJob = mState.mShaderCompileJobs[shaderType];
        if (compileJob)
        {
            const bool success = WaitCompileJobUnlocked(compileJob);
            successfullyCompiledShaders.set(shaderType, success);
        }
    }
    mState.mShaderCompileJobs = {};

    const ShaderMap<SharedCompiledShaderState> &shaders = mState.mAttachedShaders;

    bool isComputeShaderAttached  = shaders[ShaderType::Compute].get() != nullptr;
    bool isGraphicsShaderAttached = shaders[ShaderType::Vertex].get() != nullptr ||
                                    shaders[ShaderType::TessControl].get() != nullptr ||
                                    shaders[ShaderType::TessEvaluation].get() != nullptr ||
                                    shaders[ShaderType::Geometry].get() != nullptr ||
                                    shaders[ShaderType::Fragment].get() != nullptr;
    // Check whether we both have a compute and non-compute shaders attached.
    // If there are of both types attached, then linking should fail.
    // OpenGL ES 3.10, 7.3 Program Objects, under LinkProgram
    if (isComputeShaderAttached && isGraphicsShaderAttached)
    {
        mState.mInfoLog << "Both compute and graphics shaders are attached to the same program.";
        return false;
    }

    Optional<int> version;
    for (ShaderType shaderType : kAllGraphicsShaderTypes)
    {
        const SharedCompiledShaderState &shader = shaders[shaderType];
        ASSERT(!shader || shader->shaderType == shaderType);

        if (!shader)
        {
            continue;
        }

        if (!successfullyCompiledShaders.test(shaderType))
        {
            mState.mInfoLog << ShaderTypeToString(shaderType) << " shader is not compiled.";
            return false;
        }

        if (!version.valid())
        {
            version = shader->shaderVersion;
        }
        else if (version != shader->shaderVersion)
        {
            mState.mInfoLog << ShaderTypeToString(shaderType)
                            << " shader version does not match other shader versions.";
            return false;
        }
    }

    if (isComputeShaderAttached)
    {
        ASSERT(shaders[ShaderType::Compute]->shaderType == ShaderType::Compute);

        // GLSL ES 3.10, 4.4.1.1 Compute Shader Inputs
        // If the work group size is not specified, a link time error should occur.
        if (!shaders[ShaderType::Compute]->localSize.isDeclared())
        {
            mState.mInfoLog << "Work group size is not specified.";
            return false;
        }
    }
    else
    {
        if (!isGraphicsShaderAttached)
        {
            mState.mInfoLog << "No compiled shaders.";
            return false;
        }

        bool hasVertex   = shaders[ShaderType::Vertex].get() != nullptr;
        bool hasFragment = shaders[ShaderType::Fragment].get() != nullptr;
        if (!isSeparable() && (!hasVertex || !hasFragment))
        {
            mState.mInfoLog
                << "The program must contain objects to form both a vertex and fragment shader.";
            return false;
        }

        bool hasTessControl    = shaders[ShaderType::TessControl].get() != nullptr;
        bool hasTessEvaluation = shaders[ShaderType::TessEvaluation].get() != nullptr;
        if (!isSeparable() && (hasTessControl != hasTessEvaluation))
        {
            mState.mInfoLog
                << "Tessellation control and evaluation shaders must be specified together.";
            return false;
        }

        const SharedCompiledShaderState &geometryShader = shaders[ShaderType::Geometry];
        if (geometryShader)
        {
            // [GL_EXT_geometry_shader] Chapter 7
            // Linking can fail for a variety of reasons as specified in the OpenGL ES Shading
            // Language Specification, as well as any of the following reasons:
            // * One or more of the shader objects attached to <program> are not compiled
            //   successfully.
            // * The shaders do not use the same shader language version.
            // * <program> contains objects to form a geometry shader, and
            //   - <program> is not separable and contains no objects to form a vertex shader; or
            //   - the input primitive type, output primitive type, or maximum output vertex count
            //     is not specified in the compiled geometry shader object.
            Optional<PrimitiveMode> inputPrimitive =
                geometryShader->geometryShaderInputPrimitiveType;
            if (!inputPrimitive.valid())
            {
                mState.mInfoLog << "Input primitive type is not specified in the geometry shader.";
                return false;
            }

            Optional<PrimitiveMode> outputPrimitive =
                geometryShader->geometryShaderOutputPrimitiveType;
            if (!outputPrimitive.valid())
            {
                mState.mInfoLog << "Output primitive type is not specified in the geometry shader.";
                return false;
            }

            Optional<GLint> maxVertices = geometryShader->geometryShaderMaxVertices;
            if (!maxVertices.valid())
            {
                mState.mInfoLog << "'max_vertices' is not specified in the geometry shader.";
                return false;
            }
        }

        const SharedCompiledShaderState &tessControlShader = shaders[ShaderType::TessControl];
        if (tessControlShader)
        {
            int tcsShaderVertices = tessControlShader->tessControlShaderVertices;
            if (tcsShaderVertices == 0)
            {
                // In tessellation control shader, output vertices should be specified at least
                // once.
                // > GLSL ES Version 3.20.6 spec:
                // > 4.4.2. Output Layout Qualifiers
                // > Tessellation Control Outputs
                // > ...
                // > There must be at least one layout qualifier specifying an output patch vertex
                // > count in any program containing a tessellation control shader.
                mState.mInfoLog << "In Tessellation Control Shader, at least one layout qualifier "
                                   "specifying an output patch vertex count must exist.";
                return false;
            }
        }

        const SharedCompiledShaderState &tessEvaluationShader = shaders[ShaderType::TessEvaluation];
        if (tessEvaluationShader)
        {
            GLenum tesPrimitiveMode = tessEvaluationShader->tessGenMode;
            if (tesPrimitiveMode == 0)
            {
                // In tessellation evaluation shader, a primitive mode should be specified at least
                // once.
                // > GLSL ES Version 3.20.6 spec:
                // > 4.4.1. Input Layout Qualifiers
                // > Tessellation Evaluation Inputs
                // > ...
                // > The tessellation evaluation shader object in a program must declare a primitive
                // > mode in its input layout. Declaring vertex spacing, ordering, or point mode
                // > identifiers is optional.
                mState.mInfoLog
                    << "The Tessellation Evaluation Shader object in a program must declare a "
                       "primitive mode in its input layout.";
                return false;
            }
        }
    }

    return true;
}

// Assumes linkValidateShaders() has validated the shaders and caches some values from the shaders.
void Program::linkShaders()
{
    const ShaderMap<SharedCompiledShaderState> &shaders = mState.mAttachedShaders;

    const bool isComputeShaderAttached = shaders[ShaderType::Compute].get() != nullptr;

    if (isComputeShaderAttached)
    {
        mState.mExecutable->mPod.computeShaderLocalSize = shaders[ShaderType::Compute]->localSize;
    }
    else
    {
        const SharedCompiledShaderState &geometryShader = shaders[ShaderType::Geometry];
        if (geometryShader)
        {
            Optional<PrimitiveMode> inputPrimitive =
                geometryShader->geometryShaderInputPrimitiveType;
            Optional<PrimitiveMode> outputPrimitive =
                geometryShader->geometryShaderOutputPrimitiveType;
            Optional<GLint> maxVertices = geometryShader->geometryShaderMaxVertices;

            mState.mExecutable->mPod.geometryShaderInputPrimitiveType  = inputPrimitive.value();
            mState.mExecutable->mPod.geometryShaderOutputPrimitiveType = outputPrimitive.value();
            mState.mExecutable->mPod.geometryShaderMaxVertices         = maxVertices.value();
            mState.mExecutable->mPod.geometryShaderInvocations =
                geometryShader->geometryShaderInvocations;
        }

        const SharedCompiledShaderState &tessControlShader = shaders[ShaderType::TessControl];
        if (tessControlShader)
        {
            int tcsShaderVertices = tessControlShader->tessControlShaderVertices;
            mState.mExecutable->mPod.tessControlShaderVertices = tcsShaderVertices;
        }

        const SharedCompiledShaderState &tessEvaluationShader = shaders[ShaderType::TessEvaluation];
        if (tessEvaluationShader)
        {
            GLenum tesPrimitiveMode = tessEvaluationShader->tessGenMode;

            mState.mExecutable->mPod.tessGenMode        = tesPrimitiveMode;
            mState.mExecutable->mPod.tessGenSpacing     = tessEvaluationShader->tessGenSpacing;
            mState.mExecutable->mPod.tessGenVertexOrder = tessEvaluationShader->tessGenVertexOrder;
            mState.mExecutable->mPod.tessGenPointMode   = tessEvaluationShader->tessGenPointMode;
        }
    }
}

bool Program::linkVaryings()
{
    ShaderType previousShaderType = ShaderType::InvalidEnum;
    for (ShaderType shaderType : kAllGraphicsShaderTypes)
    {
        const SharedCompiledShaderState &currentShader = mState.mAttachedShaders[shaderType];
        if (!currentShader)
        {
            continue;
        }

        if (previousShaderType != ShaderType::InvalidEnum)
        {
            const SharedCompiledShaderState &previousShader =
                mState.mAttachedShaders[previousShaderType];
            const std::vector<sh::ShaderVariable> &outputVaryings = previousShader->outputVaryings;

            if (!LinkValidateShaderInterfaceMatching(
                    outputVaryings, currentShader->inputVaryings, previousShaderType,
                    currentShader->shaderType, previousShader->shaderVersion,
                    currentShader->shaderVersion, isSeparable(), mState.mInfoLog))
            {
                return false;
            }
        }
        previousShaderType = currentShader->shaderType;
    }

    // TODO: http://anglebug.com/3571 and http://anglebug.com/3572
    // Need to move logic of validating builtin varyings inside the for-loop above.
    // This is because the built-in symbols `gl_ClipDistance` and `gl_CullDistance`
    // can be redeclared in Geometry or Tessellation shaders as well.
    const SharedCompiledShaderState &vertexShader   = mState.mAttachedShaders[ShaderType::Vertex];
    const SharedCompiledShaderState &fragmentShader = mState.mAttachedShaders[ShaderType::Fragment];
    if (vertexShader && fragmentShader &&
        !LinkValidateBuiltInVaryings(vertexShader->outputVaryings, fragmentShader->inputVaryings,
                                     vertexShader->shaderType, fragmentShader->shaderType,
                                     vertexShader->shaderVersion, fragmentShader->shaderVersion,
                                     mState.mInfoLog))
    {
        return false;
    }

    return true;
}

bool Program::linkUniforms(const Caps &caps,
                           const Version &clientVersion,
                           std::vector<UnusedUniform> *unusedUniformsOutOrNull,
                           GLuint *combinedImageUniformsOut)
{
    // Initialize executable shader map.
    ShaderMap<std::vector<sh::ShaderVariable>> shaderUniforms;
    for (const SharedCompiledShaderState &shader : mState.mAttachedShaders)
    {
        if (shader)
        {
            shaderUniforms[shader->shaderType] = shader->uniforms;
        }
    }

    if (!mState.mExecutable->linkUniforms(caps, shaderUniforms, mState.mUniformLocationBindings,
                                          combinedImageUniformsOut, unusedUniformsOutOrNull))
    {
        return false;
    }

    if (clientVersion >= Version(3, 1))
    {
        GLint locationSize = static_cast<GLint>(mState.mExecutable->getUniformLocations().size());

        if (locationSize > caps.maxUniformLocations)
        {
            mState.mInfoLog << "Exceeded maximum uniform location size";
            return false;
        }
    }

    return true;
}

// Assigns locations to all attributes (except built-ins) from the bindings and program locations.
bool Program::linkAttributes(const Caps &caps,
                             const Limitations &limitations,
                             bool webglCompatibility)
{
    int shaderVersion          = -1;
    unsigned int usedLocations = 0;

    const SharedCompiledShaderState &vertexShader = mState.getAttachedShader(ShaderType::Vertex);

    if (!vertexShader)
    {
        // No vertex shader, so no attributes, so nothing to do
        return true;
    }

    // In GLSL ES 3.00.6, aliasing checks should be done with all declared attributes -
    // see GLSL ES 3.00.6 section 12.46. Inactive attributes will be pruned after
    // aliasing checks.
    // In GLSL ES 1.00.17 we only do aliasing checks for active attributes.
    shaderVersion = vertexShader->shaderVersion;
    const std::vector<sh::ShaderVariable> &shaderAttributes =
        shaderVersion >= 300 ? vertexShader->allAttributes : vertexShader->activeAttributes;

    ASSERT(mState.mExecutable->mProgramInputs.empty());
    mState.mExecutable->mProgramInputs.reserve(shaderAttributes.size());

    GLuint maxAttribs = static_cast<GLuint>(caps.maxVertexAttributes);
    std::vector<ProgramInput *> usedAttribMap(maxAttribs, nullptr);

    for (const sh::ShaderVariable &shaderAttribute : shaderAttributes)
    {
        // GLSL ES 3.10 January 2016 section 4.3.4: Vertex shader inputs can't be arrays or
        // structures, so we don't need to worry about adjusting their names or generating entries
        // for each member/element (unlike uniforms for example).
        ASSERT(!shaderAttribute.isArray() && !shaderAttribute.isStruct());

        mState.mExecutable->mProgramInputs.emplace_back(shaderAttribute);

        // Assign locations to attributes that have a binding location and check for attribute
        // aliasing.
        ProgramInput &attribute = mState.mExecutable->mProgramInputs.back();
        int bindingLocation     = mState.mAttributeBindings.getBinding(attribute);
        if (attribute.getLocation() == -1 && bindingLocation != -1)
        {
            attribute.setLocation(bindingLocation);
        }

        if (attribute.getLocation() != -1)
        {
            // Location is set by glBindAttribLocation or by location layout qualifier
            const int regs = VariableRegisterCount(attribute.getType());

            if (static_cast<GLuint>(regs + attribute.getLocation()) > maxAttribs)
            {
                mState.mInfoLog << "Attribute (" << attribute.name << ") at location "
                                << attribute.getLocation() << " is too big to fit";

                return false;
            }

            for (int reg = 0; reg < regs; reg++)
            {
                const int regLocation         = attribute.getLocation() + reg;
                ProgramInput *linkedAttribute = usedAttribMap[regLocation];

                // In GLSL ES 3.00.6 and in WebGL, attribute aliasing produces a link error.
                // In non-WebGL GLSL ES 1.00.17, attribute aliasing is allowed with some
                // restrictions - see GLSL ES 1.00.17 section 2.10.4, but ANGLE currently has a bug.
                // In D3D 9 and 11, aliasing is not supported, so check a limitation.
                if (linkedAttribute)
                {
                    if (shaderVersion >= 300 || webglCompatibility ||
                        limitations.noVertexAttributeAliasing)
                    {
                        mState.mInfoLog << "Attribute '" << attribute.name
                                        << "' aliases attribute '" << linkedAttribute->name
                                        << "' at location " << regLocation;
                        return false;
                    }
                }
                else
                {
                    usedAttribMap[regLocation] = &attribute;
                }

                usedLocations |= 1 << regLocation;
            }
        }
    }

    // Assign locations to attributes that don't have a binding location.
    for (ProgramInput &attribute : mState.mExecutable->mProgramInputs)
    {
        // Not set by glBindAttribLocation or by location layout qualifier
        if (attribute.getLocation() == -1)
        {
            int regs           = VariableRegisterCount(attribute.getType());
            int availableIndex = AllocateFirstFreeBits(&usedLocations, regs, maxAttribs);

            if (availableIndex == -1 || static_cast<GLuint>(availableIndex + regs) > maxAttribs)
            {
                mState.mInfoLog << "Too many attributes (" << attribute.name << ")";
                return false;
            }

            attribute.setLocation(availableIndex);
        }
    }

    ASSERT(mState.mExecutable->mPod.attributesTypeMask.none());
    ASSERT(mState.mExecutable->mPod.attributesMask.none());

    // Prune inactive attributes. This step is only needed on shaderVersion >= 300 since on earlier
    // shader versions we're only processing active attributes to begin with.
    if (shaderVersion >= 300)
    {
        for (auto attributeIter = mState.mExecutable->getProgramInputs().begin();
             attributeIter != mState.mExecutable->getProgramInputs().end();)
        {
            if (attributeIter->isActive())
            {
                ++attributeIter;
            }
            else
            {
                attributeIter = mState.mExecutable->mProgramInputs.erase(attributeIter);
            }
        }
    }

    for (const ProgramInput &attribute : mState.mExecutable->getProgramInputs())
    {
        ASSERT(attribute.isActive());
        ASSERT(attribute.getLocation() != -1);
        unsigned int regs = static_cast<unsigned int>(VariableRegisterCount(attribute.getType()));

        unsigned int location = static_cast<unsigned int>(attribute.getLocation());
        for (unsigned int r = 0; r < regs; r++)
        {
            // Built-in active program inputs don't have a bound attribute.
            if (!attribute.isBuiltIn())
            {
                mState.mExecutable->mPod.activeAttribLocationsMask.set(location);
                mState.mExecutable->mPod.maxActiveAttribLocation =
                    std::max(mState.mExecutable->mPod.maxActiveAttribLocation, location + 1);

                ComponentType componentType =
                    GLenumToComponentType(VariableComponentType(attribute.getType()));

                SetComponentTypeMask(componentType, location,
                                     &mState.mExecutable->mPod.attributesTypeMask);
                mState.mExecutable->mPod.attributesMask.set(location);

                location++;
            }
        }
    }

    return true;
}

void Program::initInterfaceBlockBindings()
{
    // Set initial bindings from shader.
    for (size_t blockIndex = 0; blockIndex < mState.mExecutable->getUniformBlocks().size();
         blockIndex++)
    {
        InterfaceBlock &uniformBlock = mState.mExecutable->mUniformBlocks[blockIndex];
        bindUniformBlock({static_cast<uint32_t>(blockIndex)}, uniformBlock.pod.binding);
    }
}

angle::Result Program::syncState(const Context *context)
{
    ASSERT(!mLinkingState);
    // Wait for the link tasks.  This is because these optimization passes are not currently
    // thread-safe with draw's usage of the executable.
    waitForOptionalLinkTasks(context);
    return mProgram->syncState(context);
}

angle::Result Program::serialize(const Context *context, angle::MemoryBuffer *binaryOut)
{
    BinaryOutputStream stream;

    stream.writeBytes(
        reinterpret_cast<const unsigned char *>(angle::GetANGLEShaderProgramVersion()),
        angle::GetANGLEShaderProgramVersionHashSize());

    stream.writeBool(angle::Is64Bit());

    stream.writeInt(angle::GetANGLESHVersion());

    stream.writeString(context->getRendererString());

    // nullptr context is supported when computing binary length.
    if (context)
    {
        stream.writeInt(context->getClientVersion().major);
        stream.writeInt(context->getClientVersion().minor);
    }
    else
    {
        stream.writeInt(2);
        stream.writeInt(0);
    }

    // mSeparable must be before mExecutable->save(), since it uses the value.
    stream.writeBool(mState.mSeparable);
    stream.writeInt(mState.mTransformFeedbackBufferMode);

    stream.writeInt(mState.mTransformFeedbackVaryingNames.size());
    for (const std::string &name : mState.mTransformFeedbackVaryingNames)
    {
        stream.writeString(name);
    }

    mState.mExecutable->save(&stream);

    // Warn the app layer if saving a binary with unsupported transform feedback.
    if (!mState.mExecutable->getLinkedTransformFeedbackVaryings().empty() &&
        context->getFrontendFeatures().disableProgramCachingForTransformFeedback.enabled)
    {
        ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
                           "Saving program binary with transform feedback, which is not supported "
                           "on this driver.");
    }

    if (context->getShareGroup()->getFrameCaptureShared()->enabled())
    {
        // Serialize the source for each stage for re-use during capture
        for (ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
        {
            Shader *shader = getAttachedShader(shaderType);
            if (shader)
            {
                stream.writeString(shader->getSourceString());
            }
            else
            {
                // If we don't have an attached shader, which would occur if this program was
                // created via glProgramBinary, pull from our cached copy
                const angle::ProgramSources &cachedLinkedSources =
                    context->getShareGroup()->getFrameCaptureShared()->getProgramSources(id());
                const std::string &cachedSourceString = cachedLinkedSources[shaderType];
                ASSERT(!cachedSourceString.empty());
                stream.writeString(cachedSourceString.c_str());
            }
        }
    }

    // Need to wait for optional tasks because they may be writing to caches that |serialize| would
    // read from.  In the Vulkan backend, that would be the VkPipelineCache contents.
    waitForOptionalLinkTasks(context);

    mProgram->save(context, &stream);

    ASSERT(binaryOut);
    if (!binaryOut->resize(stream.length()))
    {
        ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
                           "Failed to allocate enough memory to serialize a program. (%zu bytes)",
                           stream.length());
        return angle::Result::Stop;
    }
    memcpy(binaryOut->data(), stream.data(), stream.length());
    return angle::Result::Continue;
}

bool Program::deserialize(const Context *context, BinaryInputStream &stream)
{
    std::vector<uint8_t> angleShaderProgramVersionString(
        angle::GetANGLEShaderProgramVersionHashSize(), 0);
    stream.readBytes(angleShaderProgramVersionString.data(),
                     angleShaderProgramVersionString.size());
    if (memcmp(angleShaderProgramVersionString.data(), angle::GetANGLEShaderProgramVersion(),
               angleShaderProgramVersionString.size()) != 0)
    {
        mState.mInfoLog << "Invalid program binary version.";
        return false;
    }

    bool binaryIs64Bit = stream.readBool();
    if (binaryIs64Bit != angle::Is64Bit())
    {
        mState.mInfoLog << "cannot load program binaries across CPU architectures.";
        return false;
    }

    int angleSHVersion = stream.readInt<int>();
    if (angleSHVersion != angle::GetANGLESHVersion())
    {
        mState.mInfoLog << "cannot load program binaries across different angle sh version.";
        return false;
    }

    std::string rendererString = stream.readString();
    if (rendererString != context->getRendererString())
    {
        mState.mInfoLog << "Cannot load program binary due to changed renderer string.";
        return false;
    }

    int majorVersion = stream.readInt<int>();
    int minorVersion = stream.readInt<int>();
    if (majorVersion != context->getClientMajorVersion() ||
        minorVersion != context->getClientMinorVersion())
    {
        mState.mInfoLog << "Cannot load program binaries across different ES context versions.";
        return false;
    }

    mState.mSeparable                   = stream.readBool();
    mState.mTransformFeedbackBufferMode = stream.readInt<GLenum>();

    mState.mTransformFeedbackVaryingNames.resize(stream.readInt<size_t>());
    for (std::string &name : mState.mTransformFeedbackVaryingNames)
    {
        name = stream.readString();
    }

    // mSeparable must be before mExecutable->load(), since it uses the value.  This state is
    // duplicated in the executable for convenience.
    mState.mExecutable->mPod.isSeparable = mState.mSeparable;
    mState.mExecutable->load(&stream);

    static_assert(static_cast<unsigned long>(ShaderType::EnumCount) <= sizeof(unsigned long) * 8,
                  "Too many shader types");

    // Reject programs that use transform feedback varyings if the hardware cannot support them.
    if (mState.mExecutable->getLinkedTransformFeedbackVaryings().size() > 0 &&
        context->getFrontendFeatures().disableProgramCachingForTransformFeedback.enabled)
    {
        mState.mInfoLog << "Current driver does not support transform feedback in binary programs.";
        return false;
    }

    if (!mState.mAttachedShaders[ShaderType::Compute])
    {
        mState.mExecutable->updateTransformFeedbackStrides();
        mState.mExecutable->mTransformFeedbackVaryingNames = mState.mTransformFeedbackVaryingNames;
    }

    if (context->getShareGroup()->getFrameCaptureShared()->enabled())
    {
        // Extract the source for each stage from the program binary
        angle::ProgramSources sources;

        for (ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
        {
            std::string shaderSource = stream.readString();
            ASSERT(shaderSource.length() > 0);
            sources[shaderType] = std::move(shaderSource);
        }

        // Store it for use during mid-execution capture
        context->getShareGroup()->getFrameCaptureShared()->setProgramSources(id(),
                                                                             std::move(sources));
    }

    return true;
}

void Program::postResolveLink(const Context *context)
{
    initInterfaceBlockBindings();

    mState.updateActiveSamplers();
    mState.mExecutable->mActiveImageShaderBits.fill({});
    mState.mExecutable->updateActiveImages(getExecutable());

    mState.mExecutable->setUniformValuesFromBindingQualifiers();

    if (context->getExtensions().multiDrawANGLE)
    {
        mState.mExecutable->mPod.drawIDLocation =
            mState.mExecutable->getUniformLocation("gl_DrawID").value;
    }

    if (context->getExtensions().baseVertexBaseInstanceShaderBuiltinANGLE)
    {
        mState.mExecutable->mPod.baseVertexLocation =
            mState.mExecutable->getUniformLocation("gl_BaseVertex").value;
        mState.mExecutable->mPod.baseInstanceLocation =
            mState.mExecutable->getUniformLocation("gl_BaseInstance").value;
    }
}

void Program::cacheProgramBinary(const gl::Context *context)
{
    // Save to the program cache.
    std::lock_guard<std::mutex> cacheLock(context->getProgramCacheMutex());
    MemoryProgramCache *cache = context->getMemoryProgramCache();
    // TODO: http://anglebug.com/4530: Enable program caching for separable programs
    if (cache && !isSeparable() && !context->getFrontendFeatures().disableProgramCaching.enabled &&
        (mState.mExecutable->mLinkedTransformFeedbackVaryings.empty() ||
         !context->getFrontendFeatures().disableProgramCachingForTransformFeedback.enabled))
    {
        if (cache->putProgram(mProgramHash, context, this) == angle::Result::Stop)
        {
            // Don't fail linking if putting the program binary into the cache fails, the program is
            // still usable.
            ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
                               "Failed to save linked program to memory program cache.");
        }
    }
}

void Program::dumpProgramInfo(const Context *context) const
{
    std::stringstream dumpStream;
    for (ShaderType shaderType : angle::AllEnums<ShaderType>())
    {
        Shader *shader = getAttachedShader(shaderType);
        if (shader)
        {
            dumpStream << shader->getType() << ": "
                       << GetShaderDumpFileName(shader->getSourceHash()) << std::endl;
        }
    }

    std::string dump = dumpStream.str();
    size_t dumpHash  = std::hash<std::string>{}(dump);

    std::stringstream pathStream;
    std::string shaderDumpDir = GetShaderDumpFileDirectory();
    if (!shaderDumpDir.empty())
    {
        pathStream << shaderDumpDir << "/";
    }
    pathStream << dumpHash << ".program";
    std::string path = pathStream.str();

    writeFile(path.c_str(), dump.c_str(), dump.length());
    INFO() << "Dumped program: " << path;
}

}  // namespace gl
