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

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

    if (context && context->retainIdUntilObjectDestroyed())
    {
        context->onProgramPipelineDestroy(this);
    }

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