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

void Program::setupExecutableForLink(const Context *context)
{
    // 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();
}

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

    setupExecutableForLink(context);

    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());
        egl::CacheGetResult result = egl::CacheGetResult::NotFound;
        ANGLE_TRY(cache->getProgram(context, this, &mProgramHash, &result));

        switch (result)
        {
            case egl::CacheGetResult::GetSuccess:
            {
                // 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;
            }
            case egl::CacheGetResult::Rejected:
                // If the program binary was found but rejected, the program executable may be in an
                // inconsistent half-loaded state.  In that case, start over.
                mLinkingState.reset();
                setupExecutableForLink(context);
                break;
            case egl::CacheGetResult::NotFound:
            default:
                break;
        }
    }

    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->metadataFlags.test(sh::MetadataFlags::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->metadataFlags.test(sh::MetadataFlags::HasDiscard);
            mState.mExecutable->mPod.enablesPerSampleShading =
                fragmentShader->metadataFlags.test(sh::MetadataFlags::EnablesPerSampleShading);
            mState.mExecutable->mPod.advancedBlendEquations =
                fragmentShader->advancedBlendEquations;
            mState.mExecutable->mPod.specConstUsageBits |= fragmentShader->specConstUsageBits;

            for (uint32_t index = 0; index < IMPLEMENTATION_MAX_DRAW_BUFFERS; ++index)
            {
                const sh::MetadataFlags flag = static_cast<sh::MetadataFlags>(
                    static_cast<uint32_t>(sh::MetadataFlags::HasInputAttachment0) + index);
                if (fragmentShader->metadataFlags.test(flag))
                {
                    mState.mExecutable->mPod.fragmentInoutIndices.set(index);
                }
            }
        }

        *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);

    egl::CacheGetResult result = egl::CacheGetResult::NotFound;
    return loadBinary(context, binary, length, &result);
}

angle::Result Program::loadBinary(const Context *context,
                                  const void *binary,
                                  GLsizei length,
                                  egl::CacheGetResult *resultOut)
{
    *resultOut = egl::CacheGetResult::Rejected;

    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.

    // Initialize the uniform block -> buffer index map based on serialized data.
    mState.mExecutable->initInterfaceBlockBindings();

    // 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, resultOut));
    if (*resultOut == egl::CacheGetResult::Rejected)
    {
        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);

    *resultOut = egl::CacheGetResult::GetSuccess;

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

    mState.mExecutable->remapUniformBlockBinding(uniformBlockIndex, uniformBlockBinding);

    mProgram->onUniformBlockBinding(uniformBlockIndex);

    onStateChange(
        angle::ProgramUniformBlockBindingUpdatedMessageFromIndex(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.
            if (!geometryShader->hasValidGeometryShaderInputPrimitiveType())
            {
                mState.mInfoLog << "Input primitive type is not specified in the geometry shader.";
                return false;
            }

            if (!geometryShader->hasValidGeometryShaderOutputPrimitiveType())
            {
                mState.mInfoLog << "Output primitive type is not specified in the geometry shader.";
                return false;
            }

            if (!geometryShader->hasValidGeometryShaderMaxVertices())
            {
                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)
        {
            mState.mExecutable->mPod.geometryShaderInputPrimitiveType =
                geometryShader->geometryShaderInputPrimitiveType;
            mState.mExecutable->mPod.geometryShaderOutputPrimitiveType =
                geometryShader->geometryShaderOutputPrimitiveType;
            mState.mExecutable->mPod.geometryShaderMaxVertices =
                geometryShader->geometryShaderMaxVertices;
            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;
}

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 angle::Result::Continue;
}

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)
{
    mState.updateActiveSamplers();
    mState.mExecutable->mActiveImageShaderBits.fill({});
    mState.mExecutable->updateActiveImages(getExecutable());

    mState.mExecutable->initInterfaceBlockBindings();
    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
