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

#ifdef UNSAFE_BUFFERS_BUILD
#    pragma allow_unsafe_buffers
#endif

#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 Context *context) = 0;
    // Peeks whether the linking is still ongoing.
    virtual bool isLinking() = 0;
};

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

  private:
    angle::Result mResult;
};

void ScheduleSubTasks(const std::shared_ptr<angle::WorkerThreadPool> &workerThreadPool,
                      std::vector<std::shared_ptr<rx::LinkSubTask>> &tasks,
                      std::vector<std::shared_ptr<angle::WaitableEvent>> *eventsOut)
{
    eventsOut->reserve(tasks.size());
    for (const std::shared_ptr<rx::LinkSubTask> &subTask : tasks)
    {
        eventsOut->push_back(workerThreadPool->postWorkerTask(subTask));
    }
}
}  // 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(std::string message)
{
    ensureInitialized();

    while (1)
    {
        size_t found = message.find(g_fakepath);
        if (found == std::string::npos)
        {
            break;
        }
        message.erase(found, strlen(g_fakepath));
    }

    if (!message.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))
    {
        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));

        for (const std::shared_ptr<rx::LinkSubTask> &task : mSubTasks)
        {
            ANGLE_TRY(task->getResult(context, infoLog));
        }

        return angle::Result::Continue;
    }

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

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

  protected:
    void scheduleSubTasks(std::vector<std::shared_ptr<rx::LinkSubTask>> &&linkSubTasks,
                          std::vector<std::shared_ptr<rx::LinkSubTask>> &&postLinkSubTasks)
    {
        // Only one of linkSubTasks or postLinkSubTasks should have tasks.  This is because
        // currently, there is no support for ordering them.
        ASSERT(linkSubTasks.empty() || postLinkSubTasks.empty());

        // Schedule link subtasks
        mSubTasks = std::move(linkSubTasks);
        ScheduleSubTasks(mSubTaskWorkerPool, mSubTasks, &mSubTaskWaitableEvents);

        // Schedule post-link subtasks
        mState.mExecutable->mPostLinkSubTasks = std::move(postLinkSubTasks);
        ScheduleSubTasks(mSubTaskWorkerPool, mState.mExecutable->mPostLinkSubTasks,
                         &mState.mExecutable->mPostLinkSubTaskWaitableEvents);

        // No further use for worker pool.  Release it earlier than the destructor (to avoid
        // situations such as http://anglebug.com/42267099)
        mSubTaskWorkerPool.reset();
    }

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

    // Subtask and wait events
    std::vector<std::shared_ptr<rx::LinkSubTask>> mSubTasks;
    std::vector<std::shared_ptr<angle::WaitableEvent>> mSubTaskWaitableEvents;

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

  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>> linkSubTasks;
    std::vector<std::shared_ptr<rx::LinkSubTask>> postLinkSubTasks;
    mLinkTask->link(*mResources, mergedVaryings, &linkSubTasks, &postLinkSubTasks);

    // 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(linkSubTasks), std::move(postLinkSubTasks));

    return angle::Result::Continue;
}

angle::Result Program::MainLoadTask::loadImpl()
{
    std::vector<std::shared_ptr<rx::LinkSubTask>> linkSubTasks;
    std::vector<std::shared_ptr<rx::LinkSubTask>> postLinkSubTasks;
    mLinkTask->load(&linkSubTasks, &postLinkSubTasks);

    // Schedule the subtasks
    scheduleSubTasks(std::move(linkSubTasks), std::move(postLinkSubTasks));

    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),
      mIsBinaryCached(true),
      mLinked(false),
      mProgramHash{0},
      mRefCount(0),
      mResourceManager(manager),
      mHandle(handle),
      mAttachedShaders{}
{
    ASSERT(mProgram);

    unlink();
}

Program::~Program()
{
    ASSERT(!mProgram);
}

void Program::onDestroy(const Context *context)
{
    resolveLink(context);
    waitForPostLinkTasks(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);

    mBinary.clear();

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

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

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

void Program::detachShader(const Context *context, Shader *shader)
{
    resolveLink(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)
{
    ASSERT(!mLinkingState);
    mState.mAttributeBindings.bindLocation(index, name);
}

void Program::bindUniformLocation(const Context *context,
                                  UniformLocation location,
                                  const char *name)
{
    ASSERT(!mLinkingState);
    mState.mUniformLocationBindings.bindLocation(location.value, name);
}

void Program::bindFragmentOutputLocation(const Context *context, GLuint index, const char *name)
{
    ASSERT(!mLinkingState);
    mState.mFragmentOutputLocations.bindLocation(index, name);
}

void Program::bindFragmentOutputIndex(const Context *context, GLuint index, const char *name)
{
    ASSERT(!mLinkingState);
    mState.mFragmentOutputIndexes.bindLocation(index, name);
}

void Program::makeNewExecutable(const Context *context)
{
    ASSERT(!mLinkingState);
    waitForPostLinkTasks(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);

    // If caching is disabled, consider it cached!
    mIsBinaryCached = context->getFrontendFeatures().disableProgramCaching.enabled;

    // Start with a clean slate every time a new executable is installed.  Note that the executable
    // binary is not mutable; once linked it remains constant.  When the program changes, a new
    // executable is installed in this function.
    mBinary.clear();
}

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

void Program::syncExecutableOnSuccessfulLink()
{
    // Sync GL_PROGRAM_BINARY_RETRIEVABLE_HINT to the effective value when linking successfully.
    mState.mExecutable->mBinaryRetrieveableHint = mState.mBinaryRetrieveableHint;
}

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->getFrontendFeatures().disableProgramCaching.enabled)
                                    ? nullptr
                                    : context->getMemoryProgramCache();

    // TODO: http://anglebug.com/42263141: Enable program caching for separable programs
    if (cache && !isSeparable())
    {
        std::lock_guard<angle::SimpleMutex> cacheLock(context->getProgramCacheMutex());
        egl::CacheGetResult result = egl::CacheGetResult::NotFound;
        ANGLE_TRY(cache->getProgram(context, this, &mProgramHash, &result));

        switch (result)
        {
            case egl::CacheGetResult::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;
            }
            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, &mState.mExecutable->mPixelLocalStorageFormats);

    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.hasDepthInputAttachment =
                fragmentShader->metadataFlags.test(sh::MetadataFlags::HasDepthInputAttachment);
            mState.mExecutable->mPod.hasStencilInputAttachment =
                fragmentShader->metadataFlags.test(sh::MetadataFlags::HasStencilInputAttachment);
            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();
}

bool Program::isBinaryReady(const Context *context)
{
    if (mState.mExecutable->mPostLinkSubTasks.empty())
    {
        // Ensure the program binary is cached, even if the backend waits for post-link tasks
        // without the knowledge of the front-end.
        cacheProgramBinaryIfNotAlready(context);
        return true;
    }

    const bool allPostLinkTasksComplete =
        angle::WaitableEvent::AllReady(&mState.mExecutable->getPostLinkSubTaskWaitableEvents());

    // Once the binary is ready, the |glGetProgramBinary| call will result in
    // |waitForPostLinkTasks| which in turn may internally cache the binary.  However, for the sake
    // of blob cache tests, call |waitForPostLinkTasks| anyway if tasks are already complete.
    if (allPostLinkTasksComplete)
    {
        waitForPostLinkTasks(context);
    }

    return allPostLinkTasksComplete;
}

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

    angle::Result result                       = mLinkingState->linkEvent->wait(context);
    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);

    syncExecutableOnSuccessfulLink();

    // In case of a successful link, it is no longer required for the attached shaders to hold on to
    // the memory they have used. Therefore, the shader compilations are resolved to save memory.
    for (Shader *shader : mAttachedShaders)
    {
        if (shader != nullptr)
        {
            shader->resolveCompile(context);
        }
    }

    // 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 post link tasks. If there are any, waitForPostLinkTasks will do this
    //   instead.
    //   * Note that serialize() calls waitForPostLinkTasks, so caching the binary here
    //     effectively forces a wait for the post-link tasks.
    //
    if (!linkingState->linkingFromBinary && mState.mExecutable->mPostLinkSubTasks.empty())
    {
        cacheProgramBinaryIfNotAlready(context);
    }
}

void Program::waitForPostLinkTasks(const Context *context)
{
    // No-op if no tasks.
    mState.mExecutable->waitForPostLinkTasks(context);

    // Now that the subtasks are done, cache the binary (this was deferred in resolveLinkImpl).
    cacheProgramBinaryIfNotAlready(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);

    // Don't attempt to cache the binary that's just loaded
    mIsBinaryCached = true;

    *resultOut = egl::CacheGetResult::Success;

    return angle::Result::Continue;
}

angle::Result Program::getBinary(Context *context,
                                 GLenum *binaryFormat,
                                 void *binary,
                                 GLsizei bufSize,
                                 GLsizei *length)
{
    if (!mState.mExecutable->mBinaryRetrieveableHint)
    {
        ANGLE_PERF_WARNING(
            context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
            "Saving program binary without GL_PROGRAM_BINARY_RETRIEVABLE_HINT is suboptimal.");
    }

    ASSERT(!mLinkingState);
    if (binaryFormat)
    {
        *binaryFormat = GL_PROGRAM_BINARY_ANGLE;
    }

    // Serialize the program only if not already done.
    if (mBinary.empty())
    {
        ANGLE_TRY(serialize(context));
    }

    GLsizei streamLength       = static_cast<GLsizei>(mBinary.size());
    const uint8_t *streamState = mBinary.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, err::kInsufficientBufferSize, GL_INVALID_OPERATION);
    }

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

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

        ASSERT(ptr - streamLength == binary);

        // Once the binary is retrieved, assume the application will never need the binary and
        // release the memory.  Note that implicit caching to blob cache is disabled when the
        // GL_PROGRAM_BINARY_RETRIEVABLE_HINT is set.  If that hint is not set, serialization is
        // done twice, which is what the perf warning above is about!
        mBinary.clear();
    }

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

    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
{
    ASSERT(shaders != nullptr);

    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)
    {
        // According GLES 3.2 11.1.3.11 Validation:
        // ValidateProgram will check for all the conditions described in this section:
        // Now only check this condition:
        // Any two active samplers in the set of active program objects are of different
        // types, but refer to the same texture image unit.
        // TODO should check other conditions in future.
        if (getExecutable().validateSamplers(caps) == false)
        {
            mValidated = false;
            mState.mInfoLog << err::kTextureTypeConflict;
            return;
        }
        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);

    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/42262233 and http://anglebug.com/42262234
    // 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: number of uniform locations = "
                << locationSize << ", max uniform locations = " << caps.maxUniformLocations;
            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::serialize(const Context *context)
{
    // In typical applications, the binary should already be empty here.  However, in unusual
    // situations this may not be true.  In particular, if the application doesn't set
    // GL_PROGRAM_BINARY_RETRIEVABLE_HINT, gets the program length but doesn't get the binary, the
    // cached binary remains until the program is destroyed or the program is bound (both causing
    // |waitForPostLinkTasks()| to cache the program in the blob cache).
    if (!mBinary.empty())
    {
        return angle::Result::Continue;
    }

    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().getMajor());
        stream.writeInt(context->getClientVersion().getMinor());
    }
    else
    {
        stream.writeInt(2);
        stream.writeInt(0);
    }

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

    stream.writeInt(mState.mExecutable->mTransformFeedbackVaryingNames.size());
    for (const std::string &name : mState.mExecutable->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());
            }
        }
    }

    mProgram->save(context, &stream);
    ASSERT(mState.mExecutable->mPostLinkSubTasks.empty());

    if (!mBinary.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(mBinary.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;
    }

    const uint32_t majorVersion = stream.readInt<int>();
    const uint32_t minorVersion = stream.readInt<int>();
    if (majorVersion != context->getClientVersion().getMajor() ||
        minorVersion != context->getClientVersion().getMinor())
    {
        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();

    // Update active uniform and storage buffer block indices mask
    mState.mExecutable->updateActiveUniformBufferBlocks();
    mState.mExecutable->updateActiveStorageBufferBlocks();

    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::cacheProgramBinaryIfNotAlready(const Context *context)
{
    // If program caching is disabled, we already consider the binary cached.
    ASSERT(!context->getFrontendFeatures().disableProgramCaching.enabled || mIsBinaryCached);
    if (!mLinked || mIsBinaryCached || mState.mExecutable->mBinaryRetrieveableHint)
    {
        // Program caching is disabled, the program is yet to be linked, it's already cached, or the
        // application has specified that it prefers to cache the program binary itself.
        return;
    }

    // No post-link tasks should be pending.
    ASSERT(mState.mExecutable->mPostLinkSubTasks.empty());

    // Save to the program cache.
    std::lock_guard<angle::SimpleMutex> cacheLock(context->getProgramCacheMutex());
    MemoryProgramCache *cache = context->getMemoryProgramCache();
    // TODO: http://anglebug.com/42263141: Enable program caching for separable programs
    if (cache && !isSeparable() &&
        (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.");
        }

        // Drop the binary; the application didn't specify that it wants to retrieve the binary.  If
        // it did, we wouldn't be implicitly caching it.
        mBinary.clear();
    }

    mIsBinaryCached = true;
}

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);
    INFO() << "Dumped program: " << path;
}
}  // namespace gl
