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

// ProgramPipeline.cpp: Implements the gl::ProgramPipeline class.
// Implements GL program pipeline objects and related functionality.
// [OpenGL ES 3.1] section 7.4 page 105.

#include "libANGLE/ProgramPipeline.h"

#include <algorithm>

#include "libANGLE/Context.h"
#include "libANGLE/Program.h"
#include "libANGLE/angletypes.h"
#include "libANGLE/renderer/ContextImpl.h"
#include "libANGLE/renderer/ProgramPipelineImpl.h"

namespace gl
{

ProgramPipelineState::ProgramPipelineState(rx::GLImplFactory *factory)
    : mLabel(),
      mActiveShaderProgram(nullptr),
      mValid(false),
      mExecutable(makeNewExecutable(factory, {})),
      mIsLinked(false)
{
    for (const ShaderType shaderType : AllShaderTypes())
    {
        mPrograms[shaderType] = nullptr;
    }
}

ProgramPipelineState::~ProgramPipelineState() {}

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

void ProgramPipelineState::activeShaderProgram(Program *shaderProgram)
{
    mActiveShaderProgram = shaderProgram;
}

SharedProgramExecutable ProgramPipelineState::makeNewExecutable(
    rx::GLImplFactory *factory,
    ShaderMap<SharedProgramExecutable> &&ppoProgramExecutables)
{
    SharedProgramExecutable newExecutable = std::make_shared<ProgramExecutable>(factory, &mInfoLog);
    newExecutable->mIsPPO                 = true;
    newExecutable->mPPOProgramExecutables = std::move(ppoProgramExecutables);
    return newExecutable;
}

void ProgramPipelineState::useProgramStage(const Context *context,
                                           const ShaderType shaderType,
                                           Program *shaderProgram,
                                           angle::ObserverBinding *programObserverBinding,
                                           angle::ObserverBinding *programExecutableObserverBinding)
{
    Program *oldProgram = mPrograms[shaderType];
    if (oldProgram)
    {
        oldProgram->release(context);
    }

    // If program refers to a program object with a valid shader attached for the indicated shader
    // stage, glUseProgramStages installs the executable code for that stage in the indicated
    // program pipeline object pipeline.
    if (shaderProgram && (shaderProgram->id().value != 0) &&
        shaderProgram->getExecutable().hasLinkedShaderStage(shaderType))
    {
        mPrograms[shaderType] = shaderProgram;
        // Install the program executable, if not already
        if (shaderProgram->getSharedExecutable().get() !=
            mExecutable->mPPOProgramExecutables[shaderType].get())
        {
            InstallExecutable(context, shaderProgram->getSharedExecutable(),
                              &mExecutable->mPPOProgramExecutables[shaderType]);
        }
        shaderProgram->addRef();
    }
    else
    {
        // If program is zero, or refers to a program object with no valid shader executable for the
        // given stage, it is as if the pipeline object has no programmable stage configured for the
        // indicated shader stage.
        mPrograms[shaderType] = nullptr;
        UninstallExecutable(context, &mExecutable->mPPOProgramExecutables[shaderType]);
    }

    programObserverBinding->bind(mPrograms[shaderType]);
    programExecutableObserverBinding->bind(mExecutable->mPPOProgramExecutables[shaderType].get());
}

void ProgramPipelineState::useProgramStages(
    const Context *context,
    const ShaderBitSet &shaderTypes,
    Program *shaderProgram,
    std::vector<angle::ObserverBinding> *programObserverBindings,
    std::vector<angle::ObserverBinding> *programExecutableObserverBindings)
{
    for (ShaderType shaderType : shaderTypes)
    {
        useProgramStage(context, shaderType, shaderProgram,
                        &programObserverBindings->at(static_cast<size_t>(shaderType)),
                        &programExecutableObserverBindings->at(static_cast<size_t>(shaderType)));
    }
}

bool ProgramPipelineState::usesShaderProgram(ShaderProgramID programId) const
{
    for (const Program *program : mPrograms)
    {
        if (program && (program->id() == programId))
        {
            return true;
        }
    }

    return false;
}

void ProgramPipelineState::updateExecutableTextures()
{
    for (const ShaderType shaderType : mExecutable->getLinkedShaderStages())
    {
        const SharedProgramExecutable &programExecutable = getShaderProgramExecutable(shaderType);
        ASSERT(programExecutable);
        mExecutable->setActiveTextureMask(mExecutable->getActiveSamplersMask() |
                                          programExecutable->getActiveSamplersMask());
        mExecutable->setActiveImagesMask(mExecutable->getActiveImagesMask() |
                                         programExecutable->getActiveImagesMask());
        // Updates mActiveSamplerRefCounts, mActiveSamplerTypes, and mActiveSamplerFormats
        mExecutable->updateActiveSamplers(*programExecutable);
    }
}

void ProgramPipelineState::updateExecutableSpecConstUsageBits()
{
    rx::SpecConstUsageBits specConstUsageBits;
    for (const ShaderType shaderType : mExecutable->getLinkedShaderStages())
    {
        const SharedProgramExecutable &programExecutable = getShaderProgramExecutable(shaderType);
        ASSERT(programExecutable);
        specConstUsageBits |= programExecutable->getSpecConstUsageBits();
    }
    mExecutable->mPod.specConstUsageBits = specConstUsageBits;
}

ProgramPipeline::ProgramPipeline(rx::GLImplFactory *factory, ProgramPipelineID handle)
    : RefCountObject(factory->generateSerial(), handle),
      mProgramPipelineImpl(factory->createProgramPipeline(mState)),
      mState(factory)
{
    ASSERT(mProgramPipelineImpl);

    for (const ShaderType shaderType : AllShaderTypes())
    {
        mProgramObserverBindings.emplace_back(this, static_cast<angle::SubjectIndex>(shaderType));
        mProgramExecutableObserverBindings.emplace_back(
            this, static_cast<angle::SubjectIndex>(shaderType));
    }
}

ProgramPipeline::~ProgramPipeline()
{
    mProgramPipelineImpl.reset(nullptr);
}

void ProgramPipeline::onDestroy(const Context *context)
{
    for (Program *program : mState.mPrograms)
    {
        if (program)
        {
            ASSERT(program->getRefCount());
            program->release(context);
        }
    }

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

    mState.destroyDiscardedExecutables(context);
}

void ProgramPipelineState::destroyDiscardedExecutables(const Context *context)
{
    for (SharedProgramExecutable &executable : mProgramExecutablesToDiscard)
    {
        UninstallExecutable(context, &executable);
    }
    mProgramExecutablesToDiscard.clear();
}

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

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

const std::string &ProgramPipeline::getLabel() const
{
    return mState.mLabel;
}

rx::ProgramPipelineImpl *ProgramPipeline::getImplementation() const
{
    return mProgramPipelineImpl.get();
}

void ProgramPipeline::activeShaderProgram(Program *shaderProgram)
{
    mState.activeShaderProgram(shaderProgram);
}

angle::Result ProgramPipeline::useProgramStages(const Context *context,
                                                GLbitfield stages,
                                                Program *shaderProgram)
{
    ShaderBitSet shaderTypes;
    if (stages != GL_ALL_SHADER_BITS)
    {
        ASSERT(stages < 256u);
        for (size_t singleShaderBit : angle::BitSet<8>(stages))
        {
            // Cast back to a bit after the iterator returns an index.
            ShaderType shaderType = GetShaderTypeFromBitfield(angle::Bit<size_t>(singleShaderBit));
            ASSERT(shaderType != ShaderType::InvalidEnum);
            shaderTypes.set(shaderType);
        }
    }
    else
    {
        shaderTypes.set();
    }
    ASSERT(shaderTypes.any());

    bool needToUpdatePipelineState = false;
    for (ShaderType shaderType : shaderTypes)
    {
        if (mState.getShaderProgram(shaderType) != shaderProgram ||
            (shaderProgram &&
             getShaderProgramExecutable(shaderType) != shaderProgram->getSharedExecutable()))
        {
            needToUpdatePipelineState = true;
            break;
        }
    }

    if (!needToUpdatePipelineState)
    {
        return angle::Result::Continue;
    }

    mState.useProgramStages(context, shaderTypes, shaderProgram, &mProgramObserverBindings,
                            &mProgramExecutableObserverBindings);

    mState.mIsLinked = false;
    onStateChange(angle::SubjectMessage::ProgramUnlinked);

    return angle::Result::Continue;
}

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

    for (const ShaderType shaderType : AllShaderTypes())
    {
        if (getShaderProgramExecutable(shaderType))
        {
            mState.mExecutable->setLinkedShaderStages(shaderType);
        }
    }

    mState.mExecutable->updateCanDrawWith();
}

void ProgramPipeline::updateExecutableAttributes()
{
    const SharedProgramExecutable &vertexExecutable =
        getShaderProgramExecutable(ShaderType::Vertex);

    if (!vertexExecutable)
    {
        return;
    }

    mState.mExecutable->mPod.activeAttribLocationsMask =
        vertexExecutable->mPod.activeAttribLocationsMask;
    mState.mExecutable->mPod.maxActiveAttribLocation =
        vertexExecutable->mPod.maxActiveAttribLocation;
    mState.mExecutable->mPod.attributesTypeMask = vertexExecutable->mPod.attributesTypeMask;
    mState.mExecutable->mPod.attributesMask     = vertexExecutable->mPod.attributesMask;
    mState.mExecutable->mProgramInputs          = vertexExecutable->mProgramInputs;

    mState.mExecutable->mPod.numViews             = vertexExecutable->mPod.numViews;
    mState.mExecutable->mPod.drawIDLocation       = vertexExecutable->mPod.drawIDLocation;
    mState.mExecutable->mPod.baseVertexLocation   = vertexExecutable->mPod.baseVertexLocation;
    mState.mExecutable->mPod.baseInstanceLocation = vertexExecutable->mPod.baseInstanceLocation;
}

void ProgramPipeline::updateTransformFeedbackMembers()
{
    ShaderType lastVertexProcessingStage =
        GetLastPreFragmentStage(getExecutable().getLinkedShaderStages());
    if (lastVertexProcessingStage == ShaderType::InvalidEnum)
    {
        return;
    }

    const SharedProgramExecutable &lastPreFragmentExecutable =
        getShaderProgramExecutable(lastVertexProcessingStage);
    ASSERT(lastPreFragmentExecutable);

    mState.mExecutable->mTransformFeedbackStrides =
        lastPreFragmentExecutable->mTransformFeedbackStrides;
    mState.mExecutable->mLinkedTransformFeedbackVaryings =
        lastPreFragmentExecutable->mLinkedTransformFeedbackVaryings;
}

void ProgramPipeline::updateShaderStorageBlocks()
{
    mState.mExecutable->mShaderStorageBlocks.clear();

    // Only copy the storage blocks from each Program in the PPO once, since each Program could
    // contain multiple shader stages.
    ShaderBitSet handledStages;

    for (const ShaderType shaderType : AllShaderTypes())
    {
        const SharedProgramExecutable &programExecutable = getShaderProgramExecutable(shaderType);
        if (programExecutable && !handledStages.test(shaderType))
        {
            // Only add each Program's blocks once.
            handledStages |= programExecutable->getLinkedShaderStages();

            for (const InterfaceBlock &block : programExecutable->getShaderStorageBlocks())
            {
                mState.mExecutable->mShaderStorageBlocks.emplace_back(block);
            }
        }
    }
}

void ProgramPipeline::updateImageBindings()
{
    mState.mExecutable->mImageBindings.clear();
    mState.mExecutable->mActiveImageShaderBits.fill({});

    // Only copy the storage blocks from each Program in the PPO once, since each Program could
    // contain multiple shader stages.
    ShaderBitSet handledStages;

    for (const ShaderType shaderType : AllShaderTypes())
    {
        const SharedProgramExecutable &programExecutable = getShaderProgramExecutable(shaderType);
        if (programExecutable && !handledStages.test(shaderType))
        {
            // Only add each Program's blocks once.
            handledStages |= programExecutable->getLinkedShaderStages();

            for (const ImageBinding &imageBinding : *programExecutable->getImageBindings())
            {
                mState.mExecutable->mImageBindings.emplace_back(imageBinding);
            }

            mState.mExecutable->updateActiveImages(*programExecutable);
        }
    }
}

void ProgramPipeline::updateExecutableGeometryProperties()
{
    const SharedProgramExecutable &geometryExecutable =
        getShaderProgramExecutable(ShaderType::Geometry);

    if (!geometryExecutable)
    {
        return;
    }

    mState.mExecutable->mPod.geometryShaderInputPrimitiveType =
        geometryExecutable->mPod.geometryShaderInputPrimitiveType;
    mState.mExecutable->mPod.geometryShaderOutputPrimitiveType =
        geometryExecutable->mPod.geometryShaderOutputPrimitiveType;
    mState.mExecutable->mPod.geometryShaderInvocations =
        geometryExecutable->mPod.geometryShaderInvocations;
    mState.mExecutable->mPod.geometryShaderMaxVertices =
        geometryExecutable->mPod.geometryShaderMaxVertices;
}

void ProgramPipeline::updateExecutableTessellationProperties()
{
    const SharedProgramExecutable &tessControlExecutable =
        getShaderProgramExecutable(ShaderType::TessControl);
    const SharedProgramExecutable &tessEvalExecutable =
        getShaderProgramExecutable(ShaderType::TessEvaluation);

    if (tessControlExecutable)
    {
        mState.mExecutable->mPod.tessControlShaderVertices =
            tessControlExecutable->mPod.tessControlShaderVertices;
    }

    if (tessEvalExecutable)
    {
        mState.mExecutable->mPod.tessGenMode        = tessEvalExecutable->mPod.tessGenMode;
        mState.mExecutable->mPod.tessGenSpacing     = tessEvalExecutable->mPod.tessGenSpacing;
        mState.mExecutable->mPod.tessGenVertexOrder = tessEvalExecutable->mPod.tessGenVertexOrder;
        mState.mExecutable->mPod.tessGenPointMode   = tessEvalExecutable->mPod.tessGenPointMode;
    }
}

void ProgramPipeline::updateFragmentInoutRangeAndEnablesPerSampleShading()
{
    const SharedProgramExecutable &fragmentExecutable =
        getShaderProgramExecutable(ShaderType::Fragment);

    if (!fragmentExecutable)
    {
        return;
    }

    mState.mExecutable->mPod.fragmentInoutIndices = fragmentExecutable->mPod.fragmentInoutIndices;
    mState.mExecutable->mPod.hasDiscard           = fragmentExecutable->mPod.hasDiscard;
    mState.mExecutable->mPod.enablesPerSampleShading =
        fragmentExecutable->mPod.enablesPerSampleShading;
    mState.mExecutable->mPod.hasDepthInputAttachment =
        fragmentExecutable->mPod.hasDepthInputAttachment;
    mState.mExecutable->mPod.hasStencilInputAttachment =
        fragmentExecutable->mPod.hasStencilInputAttachment;
    mState.mExecutable->mPod.hasFragCoord = fragmentExecutable->mPod.hasFragCoord;
}

void ProgramPipeline::updateLinkedVaryings()
{
    // Need to check all of the shader stages, not just linked, so we handle Compute correctly.
    for (const ShaderType shaderType : kAllGraphicsShaderTypes)
    {
        const SharedProgramExecutable &programExecutable = getShaderProgramExecutable(shaderType);
        if (programExecutable)
        {
            mState.mExecutable->mLinkedOutputVaryings[shaderType] =
                programExecutable->getLinkedOutputVaryings(shaderType);
            mState.mExecutable->mLinkedInputVaryings[shaderType] =
                programExecutable->getLinkedInputVaryings(shaderType);
        }
    }

    const SharedProgramExecutable &computeExecutable =
        getShaderProgramExecutable(ShaderType::Compute);
    if (computeExecutable)
    {
        mState.mExecutable->mLinkedOutputVaryings[ShaderType::Compute] =
            computeExecutable->getLinkedOutputVaryings(ShaderType::Compute);
        mState.mExecutable->mLinkedInputVaryings[ShaderType::Compute] =
            computeExecutable->getLinkedInputVaryings(ShaderType::Compute);
    }
}

void ProgramPipeline::updateExecutable()
{
    // Vertex Shader ProgramExecutable properties
    updateExecutableAttributes();
    updateTransformFeedbackMembers();
    updateShaderStorageBlocks();
    updateImageBindings();

    // Geometry Shader ProgramExecutable properties
    updateExecutableGeometryProperties();

    // Tessellation Shaders ProgramExecutable properties
    updateExecutableTessellationProperties();

    // Fragment Shader ProgramExecutable properties
    updateFragmentInoutRangeAndEnablesPerSampleShading();

    // All Shader ProgramExecutable properties
    mState.updateExecutableTextures();
    mState.updateExecutableSpecConstUsageBits();
    updateLinkedVaryings();
}

void ProgramPipeline::resolveAttachedPrograms(const Context *context)
{
    // Wait for attached programs to finish linking
    for (Program *program : mState.mPrograms)
    {
        if (program != nullptr)
        {
            program->resolveLink(context);
        }
    }
}

// The attached shaders are checked for linking errors by matching up their variables.
// Uniform, input and output variables get collected.
// The code gets compiled into binaries.
angle::Result ProgramPipeline::link(const Context *context)
{
    mState.destroyDiscardedExecutables(context);

    // Make a new executable to hold the result of the link.
    SharedProgramExecutable newExecutable = mState.makeNewExecutable(
        context->getImplementation(), std::move(mState.mExecutable->mPPOProgramExecutables));

    InstallExecutable(context, newExecutable, &mState.mExecutable);
    onStateChange(angle::SubjectMessage::ProgramUnlinked);

    updateLinkedShaderStages();

    ASSERT(!mState.mIsLinked);

    ProgramMergedVaryings mergedVaryings;
    ProgramVaryingPacking varyingPacking;
    LinkingVariables linkingVariables;

    mState.mInfoLog.reset();

    linkingVariables.initForProgramPipeline(mState);

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

    if (mState.mExecutable->hasLinkedShaderStage(gl::ShaderType::TessControl) !=
        mState.mExecutable->hasLinkedShaderStage(gl::ShaderType::TessEvaluation))
    {
        return angle::Result::Stop;
    }

    if (mState.mExecutable->hasLinkedShaderStage(ShaderType::Vertex))
    {
        if (!linkVaryings())
        {
            return angle::Result::Stop;
        }

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

        const SharedProgramExecutable &fragmentExecutable =
            getShaderProgramExecutable(ShaderType::Fragment);
        if (fragmentExecutable)
        {
            // We should also be validating SSBO and image uniform counts.
            const GLuint combinedImageUniforms       = 0;
            const GLuint combinedShaderStorageBlocks = 0;
            ASSERT(mState.mExecutable->mOutputVariables.empty());
            mState.mExecutable->mOutputVariables = fragmentExecutable->getOutputVariables();
            if (!mState.mExecutable->linkValidateOutputVariables(
                    caps, clientVersion, combinedImageUniforms, combinedShaderStorageBlocks,
                    fragmentExecutable->getLinkedShaderVersion(ShaderType::Fragment),
                    ProgramAliasedBindings(), ProgramAliasedBindings()))
            {
                return angle::Result::Continue;
            }
        }
        mergedVaryings = GetMergedVaryingsFromLinkingVariables(linkingVariables);
        // If separable program objects are in use, the set of attributes captured is taken
        // from the program object active on the last vertex processing stage.
        ShaderType lastVertexProcessingStage =
            GetLastPreFragmentStage(getExecutable().getLinkedShaderStages());
        if (lastVertexProcessingStage == ShaderType::InvalidEnum)
        {
            //  If there is no active program for the vertex or fragment shader stages, the results
            //  of vertex and fragment shader execution will respectively be undefined. However,
            //  this is not an error.
            return angle::Result::Continue;
        }

        const SharedProgramExecutable *tfExecutable =
            &getShaderProgramExecutable(lastVertexProcessingStage);
        ASSERT(*tfExecutable);

        if (!*tfExecutable)
        {
            tfExecutable = &getShaderProgramExecutable(ShaderType::Vertex);
        }

        mState.mExecutable->mTransformFeedbackVaryingNames =
            (*tfExecutable)->mTransformFeedbackVaryingNames;
        mState.mExecutable->mPod.transformFeedbackBufferMode =
            (*tfExecutable)->mPod.transformFeedbackBufferMode;

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

    // Merge uniforms.
    mState.mExecutable->copyUniformsFromProgramMap(mState.mExecutable->mPPOProgramExecutables);

    if (mState.mExecutable->hasLinkedShaderStage(ShaderType::Vertex))
    {
        const SharedProgramExecutable &executable = getShaderProgramExecutable(ShaderType::Vertex);
        mState.mExecutable->copyInputsFromProgram(*executable);
    }

    // Merge shader buffers (UBOs, SSBOs, and atomic counter buffers) into the executable.
    // Also copy over image and sampler bindings.
    for (ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
    {
        const SharedProgramExecutable &executable = getShaderProgramExecutable(shaderType);
        mState.mExecutable->copyUniformBuffersFromProgram(*executable, shaderType,
                                                          &mState.mUniformBlockMap[shaderType]);
        mState.mExecutable->copyStorageBuffersFromProgram(*executable, shaderType);
        mState.mExecutable->copySamplerBindingsFromProgram(*executable);
        mState.mExecutable->copyImageBindingsFromProgram(*executable);
    }
    // Update active uniform and storage buffer block indices mask
    mState.mExecutable->updateActiveUniformBufferBlocks();
    mState.mExecutable->updateActiveStorageBufferBlocks();

    if (mState.mExecutable->hasLinkedShaderStage(ShaderType::Fragment))
    {
        const SharedProgramExecutable &executable =
            getShaderProgramExecutable(ShaderType::Fragment);
        mState.mExecutable->copyOutputsFromProgram(*executable);
    }

    mState.mExecutable->mActiveSamplerRefCounts.fill(0);
    updateExecutable();

    if (mState.mExecutable->hasLinkedShaderStage(ShaderType::Vertex) ||
        mState.mExecutable->hasLinkedShaderStage(ShaderType::Compute))
    {
        ANGLE_TRY(getImplementation()->link(context, mergedVaryings, varyingPacking));
    }

    mState.mIsLinked = true;
    onStateChange(angle::SubjectMessage::ProgramRelinked);

    return angle::Result::Continue;
}

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

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

bool ProgramPipeline::linkVaryings()
{
    ShaderType previousShaderType = ShaderType::InvalidEnum;
    for (ShaderType shaderType : kAllGraphicsShaderTypes)
    {
        const SharedProgramExecutable &programExecutable = getShaderProgramExecutable(shaderType);
        if (!programExecutable)
        {
            continue;
        }

        if (previousShaderType != ShaderType::InvalidEnum)
        {
            const SharedProgramExecutable &previousExecutable =
                getShaderProgramExecutable(previousShaderType);
            ASSERT(previousExecutable);

            if (previousExecutable == programExecutable)
            {
                continue;
            }
            if (!LinkValidateInOutNumberMatching(
                    previousExecutable->getLinkedOutputVaryings(previousShaderType),
                    programExecutable->getLinkedInputVaryings(shaderType), previousShaderType,
                    shaderType, previousExecutable->getLinkedShaderVersion(previousShaderType),
                    programExecutable->getLinkedShaderVersion(shaderType), mState.mInfoLog))
            {
                return false;
            }
            if (!LinkValidateShaderInterfaceMatching(
                    previousExecutable->getLinkedOutputVaryings(previousShaderType),
                    programExecutable->getLinkedInputVaryings(shaderType), previousShaderType,
                    shaderType, previousExecutable->getLinkedShaderVersion(previousShaderType),
                    programExecutable->getLinkedShaderVersion(shaderType), true, mState.mInfoLog))
            {
                return false;
            }
        }
        previousShaderType = 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 SharedProgramExecutable &vertexExecutable =
        getShaderProgramExecutable(ShaderType::Vertex);
    const SharedProgramExecutable &fragmentExecutable =
        getShaderProgramExecutable(ShaderType::Fragment);
    if (!vertexExecutable || !fragmentExecutable)
    {
        return true;
    }
    return LinkValidateBuiltInVaryings(
        vertexExecutable->getLinkedOutputVaryings(ShaderType::Vertex),
        fragmentExecutable->getLinkedInputVaryings(ShaderType::Fragment), ShaderType::Vertex,
        ShaderType::Fragment, vertexExecutable->getLinkedShaderVersion(ShaderType::Vertex),
        fragmentExecutable->getLinkedShaderVersion(ShaderType::Fragment), mState.mInfoLog);
}

void ProgramPipeline::validate(const Context *context)
{
    updateLinkedShaderStages();

    const Caps &caps = context->getCaps();
    mState.mValid    = true;
    mState.mInfoLog.reset();
    bool noActiveStage = true;

    if (mState.mExecutable->hasLinkedShaderStage(gl::ShaderType::TessControl) !=
        mState.mExecutable->hasLinkedShaderStage(gl::ShaderType::TessEvaluation))
    {
        mState.mValid = false;
        mState.mInfoLog << "Program pipeline must have both a Tessellation Control and Evaluation "
                           "shader or neither\n";
        return;
    }

    for (const ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
    {
        Program *shaderProgram = mState.mPrograms[shaderType];
        if (shaderProgram)
        {
            noActiveStage = false;
            shaderProgram->resolveLink(context);
            shaderProgram->validate(caps);
            std::string shaderInfoString = shaderProgram->getExecutable().getInfoLogString();
            if (shaderInfoString.length())
            {
                mState.mValid = false;
                mState.mInfoLog << shaderInfoString << "\n";
                return;
            }
            if (!shaderProgram->isSeparable())
            {
                mState.mValid = false;
                mState.mInfoLog << GetShaderTypeString(shaderType) << " is not marked separable."
                                << "\n";
                return;
            }
        }
    }

    if (noActiveStage)
    {
        mState.mValid = false;
        mState.mInfoLog << "Program pipeline has no active stage yet.\n";
        return;
    }

    intptr_t programPipelineError = context->getStateCache().getProgramPipelineError(context);
    if (programPipelineError)
    {
        mState.mValid            = false;
        const char *errorMessage = reinterpret_cast<const char *>(programPipelineError);
        mState.mInfoLog << errorMessage << "\n";
        return;
    }

    if (!linkVaryings())
    {
        mState.mValid = false;

        for (const ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
        {
            Program *shaderProgram = mState.mPrograms[shaderType];
            ASSERT(shaderProgram);
            shaderProgram->validate(caps);
            std::string shaderInfoString = shaderProgram->getExecutable().getInfoLogString();
            if (shaderInfoString.length())
            {
                mState.mInfoLog << shaderInfoString << "\n";
            }
        }
    }
}

void ProgramPipeline::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
{
    switch (message)
    {
        case angle::SubjectMessage::ProgramTextureOrImageBindingChanged:
            mState.mExecutable->mActiveSamplerRefCounts.fill(0);
            mState.updateExecutableTextures();
            break;

        case angle::SubjectMessage::ProgramUnlinked:
            // A used program is being relinked.  Ensure next usage of the PPO resolve the program
            // link and relinks the PPO.
            mState.mIsLinked = false;
            onStateChange(angle::SubjectMessage::ProgramUnlinked);
            break;

        case angle::SubjectMessage::ProgramRelinked:
        {
            ShaderType shaderType = static_cast<ShaderType>(index);
            ASSERT(mState.mPrograms[shaderType] != nullptr);
            ASSERT(mState.mExecutable->mPPOProgramExecutables[shaderType]);

            mState.mIsLinked = false;
            mState.mProgramExecutablesToDiscard.emplace_back(
                std::move(mState.mExecutable->mPPOProgramExecutables[shaderType]));
            mState.mExecutable->mPPOProgramExecutables[shaderType] =
                mState.mPrograms[shaderType]->getSharedExecutable();

            break;
        }
        case angle::SubjectMessage::SamplerUniformsUpdated:
            mState.mExecutable->clearSamplerBindings();
            for (ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
            {
                const SharedProgramExecutable &executable = getShaderProgramExecutable(shaderType);
                mState.mExecutable->copySamplerBindingsFromProgram(*executable);
            }
            mState.mExecutable->mActiveSamplerRefCounts.fill(0);
            mState.updateExecutableTextures();
            break;
        default:
            if (angle::IsProgramUniformBlockBindingUpdatedMessage(message))
            {
                if (mState.mIsLinked)
                {
                    ShaderType shaderType = static_cast<ShaderType>(index);
                    const SharedProgramExecutable &executable =
                        getShaderProgramExecutable(shaderType);
                    const GLuint blockIndex =
                        angle::ProgramUniformBlockBindingUpdatedMessageToIndex(message);
                    if (executable->getUniformBlocks()[blockIndex].isActive(shaderType))
                    {
                        const uint32_t blockIndexInPPO =
                            mState.mUniformBlockMap[shaderType][blockIndex];
                        ASSERT(blockIndexInPPO < mState.mExecutable->mUniformBlocks.size());

                        // Set the block buffer binding in the PPO to the same binding as the
                        // program's.
                        mState.mExecutable->remapUniformBlockBinding(
                            {blockIndexInPPO}, executable->getUniformBlockBinding(blockIndex));

                        // Notify the contexts that the block binding has changed.
                        onStateChange(angle::ProgramUniformBlockBindingUpdatedMessageFromIndex(
                            blockIndexInPPO));
                    }
                }
                break;
            }
            UNREACHABLE();
            break;
    }
}
}  // namespace gl
