//
// Copyright 2020 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.
//
// ProgramExecutableVk.cpp: Collects the information and interfaces common to both ProgramVks and
// ProgramPipelineVks in order to execute/draw with either.
//

#include "libANGLE/renderer/vulkan/ProgramExecutableVk.h"
#include "common/unsafe_buffers.h"

#include "common/string_utils.h"
#include "libANGLE/renderer/vulkan/BufferVk.h"
#include "libANGLE/renderer/vulkan/DisplayVk.h"
#include "libANGLE/renderer/vulkan/FramebufferVk.h"
#include "libANGLE/renderer/vulkan/ProgramPipelineVk.h"
#include "libANGLE/renderer/vulkan/ProgramVk.h"
#include "libANGLE/renderer/vulkan/TextureVk.h"
#include "libANGLE/renderer/vulkan/TransformFeedbackVk.h"
#include "libANGLE/renderer/vulkan/vk_helpers.h"
#include "libANGLE/renderer/vulkan/vk_utils.h"

namespace rx
{
namespace
{

// Limit decompressed vulkan pipelines to 10MB per program.
static constexpr size_t kMaxLocalPipelineCacheSize = 10 * 1024 * 1024;

bool ValidateTransformedSpirV(vk::ErrorContext *context,
                              const gl::ShaderBitSet &linkedShaderStages,
                              const ShaderInterfaceVariableInfoMap &variableInfoMap,
                              const gl::ShaderMap<angle::spirv::Blob> &spirvBlobs)
{
    gl::ShaderType lastPreFragmentStage = gl::GetLastPreFragmentStage(linkedShaderStages);

    for (gl::ShaderType shaderType : linkedShaderStages)
    {
        SpvTransformOptions options;
        options.shaderType = shaderType;
        options.isLastPreFragmentStage =
            shaderType == lastPreFragmentStage && shaderType != gl::ShaderType::TessControl;
        options.isTransformFeedbackStage = options.isLastPreFragmentStage;
        options.useSpirvVaryingPrecisionFixer =
            context->getFeatures().varyingsRequireMatchingPrecisionInSpirv.enabled;

        angle::spirv::Blob transformed;
        if (SpvTransformSpirvCode(options, variableInfoMap, spirvBlobs[shaderType], &transformed) !=
            angle::Result::Continue)
        {
            return false;
        }
    }
    return true;
}

uint32_t GetInterfaceBlockArraySize(const std::vector<gl::InterfaceBlock> &blocks,
                                    uint32_t bufferIndex)
{
    const gl::InterfaceBlock &block = blocks[bufferIndex];

    if (!block.pod.isArray)
    {
        return 1;
    }

    ASSERT(block.pod.arrayElement == 0);

    // Search consecutively until all array indices of this block are visited.
    uint32_t arraySize;
    for (arraySize = 1; bufferIndex + arraySize < blocks.size(); ++arraySize)
    {
        const gl::InterfaceBlock &nextBlock = blocks[bufferIndex + arraySize];

        if (nextBlock.pod.arrayElement != arraySize)
        {
            break;
        }

        // It's unexpected for an array to start at a non-zero array size, so we can always rely on
        // the sequential `arrayElement`s to belong to the same block.
        ASSERT(nextBlock.name == block.name);
        ASSERT(nextBlock.pod.isArray);
    }

    return arraySize;
}

void SetupDefaultPipelineState(const vk::ErrorContext *context,
                               const gl::ProgramExecutable &glExecutable,
                               gl::PrimitiveMode mode,
                               vk::PipelineRobustness pipelineRobustness,
                               vk::PipelineProtectedAccess pipelineProtectedAccess,
                               vk::GraphicsPipelineSubset subset,
                               vk::GraphicsPipelineDesc *graphicsPipelineDescOut)
{
    graphicsPipelineDescOut->initDefaults(context, vk::GraphicsPipelineSubset::Complete,
                                          pipelineRobustness, pipelineProtectedAccess);

    // Set render pass state, affecting both complete and shaders-only pipelines.
    graphicsPipelineDescOut->setTopology(mode);
    graphicsPipelineDescOut->setRenderPassSampleCount(1);
    graphicsPipelineDescOut->setRenderPassFramebufferFetchMode(
        vk::GetProgramFramebufferFetchMode(&glExecutable));

    const std::vector<gl::ProgramOutput> &outputVariables    = glExecutable.getOutputVariables();
    const std::vector<gl::VariableLocation> &outputLocations = glExecutable.getOutputLocations();

    gl::DrawBufferMask drawBuffers;

    for (const gl::VariableLocation &outputLocation : outputLocations)
    {
        if (outputLocation.arrayIndex == 0 && outputLocation.used() && !outputLocation.ignored)
        {
            const gl::ProgramOutput &outputVar = outputVariables[outputLocation.index];

            if (angle::BeginsWith(outputVar.name, "gl_") && outputVar.name != "gl_FragColor")
            {
                continue;
            }

            uint32_t location = 0;
            if (outputVar.pod.location != -1)
            {
                location = outputVar.pod.location;
            }

            GLenum type            = gl::VariableComponentType(outputVar.pod.type);
            angle::FormatID format = angle::FormatID::R8G8B8A8_UNORM;
            if (type == GL_INT)
            {
                format = angle::FormatID::R8G8B8A8_SINT;
            }
            else if (type == GL_UNSIGNED_INT)
            {
                format = angle::FormatID::R8G8B8A8_UINT;
            }

            const size_t arraySize = outputVar.isArray() ? outputVar.getOutermostArraySize() : 1;
            for (size_t arrayIndex = 0; arrayIndex < arraySize; ++arrayIndex)
            {
                graphicsPipelineDescOut->setRenderPassColorAttachmentFormat(location + arrayIndex,
                                                                            format);
                drawBuffers.set(location + arrayIndex);
            }
        }
    }

    for (const gl::ProgramOutput &outputVar : outputVariables)
    {
        if (outputVar.name == "gl_FragColor" || outputVar.name == "gl_FragData")
        {
            const size_t arraySize = outputVar.isArray() ? outputVar.getOutermostArraySize() : 1;
            for (size_t arrayIndex = 0; arrayIndex < arraySize; ++arrayIndex)
            {
                graphicsPipelineDescOut->setRenderPassColorAttachmentFormat(
                    arrayIndex, angle::FormatID::R8G8B8A8_UNORM);
                drawBuffers.set(arrayIndex);
            }
        }
    }

    if (subset == vk::GraphicsPipelineSubset::Complete)
    {
        // Include vertex input state
        graphicsPipelineDescOut->setVertexShaderComponentTypes(
            glExecutable.getNonBuiltinAttribLocationsMask(), glExecutable.getAttributesTypeMask());

        // Include fragment output state
        gl::BlendStateExt::ColorMaskStorage::Type colorMask =
            gl::BlendStateExt::ColorMaskStorage::GetReplicatedValue(
                gl::BlendStateExt::PackColorMask(true, true, true, true),
                gl::BlendStateExt::ColorMaskStorage::GetMask(gl::IMPLEMENTATION_MAX_DRAW_BUFFERS));
        graphicsPipelineDescOut->setColorWriteMasks(colorMask, {}, drawBuffers);
    }
}

void GetPipelineCacheData(ContextVk *contextVk,
                          const vk::PipelineCache &pipelineCache,
                          angle::MemoryBuffer *cacheDataOut)
{
    ASSERT(pipelineCache.valid() || contextVk->getState().isGLES1() ||
           !contextVk->getFeatures().warmUpPipelineCacheAtLink.enabled ||
           contextVk->getFeatures().skipPipelineCacheSerialization.enabled);
    if (!pipelineCache.valid() || contextVk->getFeatures().skipPipelineCacheSerialization.enabled)
    {
        return;
    }

    // Extract the pipeline data.  If failed, or empty, it's simply not stored on disk.
    size_t pipelineCacheSize = 0;
    VkResult result =
        pipelineCache.getCacheData(contextVk->getDevice(), &pipelineCacheSize, nullptr);
    if (result != VK_SUCCESS || pipelineCacheSize == 0)
    {
        return;
    }

    if (contextVk->getFeatures().enablePipelineCacheDataCompression.enabled)
    {
        std::vector<uint8_t> pipelineCacheData(pipelineCacheSize);
        result = pipelineCache.getCacheData(contextVk->getDevice(), &pipelineCacheSize,
                                            pipelineCacheData.data());
        if (result != VK_SUCCESS && result != VK_INCOMPLETE)
        {
            return;
        }

        // Compress it.
        if (!angle::CompressBlob(pipelineCacheData.size(), pipelineCacheData.data(), cacheDataOut))
        {
            cacheDataOut->clear();
        }
    }
    else
    {
        if (!cacheDataOut->resize(pipelineCacheSize))
        {
            ERR() << "Failed to allocate memory for pipeline cache data.";
            return;
        }
        result = pipelineCache.getCacheData(contextVk->getDevice(), &pipelineCacheSize,
                                            cacheDataOut->data());
        if (result != VK_SUCCESS && result != VK_INCOMPLETE)
        {
            cacheDataOut->clear();
        }
    }
}

vk::GraphicsPipelineSubset GetWarmUpSubset(const angle::FeaturesVk &features)
{
    // Only build the shaders subset of the pipeline if VK_EXT_graphics_pipeline_library is
    // supported.
    return features.supportsGraphicsPipelineLibrary.enabled ? vk::GraphicsPipelineSubset::Shaders
                                                            : vk::GraphicsPipelineSubset::Complete;
}

angle::Result UpdateFullTexturesDescriptorSet(vk::ErrorContext *context,
                                              const ShaderInterfaceVariableInfoMap &variableInfoMap,
                                              const vk::WriteDescriptorDescs &writeDescriptorDescs,
                                              UpdateDescriptorSetsBuilder *updateBuilder,
                                              const gl::ProgramExecutable &executable,
                                              const gl::ActiveTextureArray<TextureVk *> &textures,
                                              const gl::SamplerBindingVector &samplers,
                                              VkDescriptorSet descriptorSet)
{
    vk::Renderer *renderer = context->getRenderer();

    const std::vector<gl::SamplerBinding> &samplerBindings = executable.getSamplerBindings();
    const std::vector<GLuint> &samplerBoundTextureUnits = executable.getSamplerBoundTextureUnits();
    const std::vector<gl::LinkedUniform> &uniforms      = executable.getUniforms();
    const gl::ActiveTextureTypeArray &textureTypes      = executable.getActiveSamplerTypes();

    // Allocate VkWriteDescriptorSet and initialize the data structure
    VkWriteDescriptorSet *writeDescriptorSets =
        updateBuilder->allocWriteDescriptorSets(static_cast<uint32_t>(writeDescriptorDescs.size()));
    for (uint32_t writeIndex = 0; writeIndex < writeDescriptorDescs.size(); ++writeIndex)
    {
        ASSERT(writeDescriptorDescs[writeIndex].descriptorCount > 0);

        VkWriteDescriptorSet &writeSet = ANGLE_UNSAFE_TODO(writeDescriptorSets[writeIndex]);
        writeSet.descriptorCount       = writeDescriptorDescs[writeIndex].descriptorCount;
        writeSet.descriptorType =
            static_cast<VkDescriptorType>(writeDescriptorDescs[writeIndex].descriptorType);
        writeSet.dstArrayElement  = 0;
        writeSet.dstBinding       = writeIndex;
        writeSet.dstSet           = descriptorSet;
        writeSet.pBufferInfo      = nullptr;
        writeSet.pImageInfo       = nullptr;
        writeSet.pNext            = nullptr;
        writeSet.pTexelBufferView = nullptr;
        writeSet.sType            = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
        // Always allocate VkDescriptorImageInfo. In less common case that descriptorType is
        // VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, this will not used.
        writeSet.pImageInfo = updateBuilder->allocDescriptorImageInfos(
            writeDescriptorDescs[writeIndex].descriptorCount);
    }

    for (uint32_t samplerIndex = 0; samplerIndex < samplerBindings.size(); ++samplerIndex)
    {
        uint32_t uniformIndex = executable.getUniformIndexFromSamplerIndex(samplerIndex);
        const gl::LinkedUniform &samplerUniform = uniforms[uniformIndex];
        if (samplerUniform.activeShaders().none())
        {
            continue;
        }

        const gl::ShaderType firstShaderType = samplerUniform.getFirstActiveShaderType();
        const ShaderInterfaceVariableInfo &info =
            variableInfoMap.getVariableById(firstShaderType, samplerUniform.getId(firstShaderType));

        const gl::SamplerBinding &samplerBinding = samplerBindings[samplerIndex];
        uint32_t arraySize = static_cast<uint32_t>(samplerBinding.textureUnitsCount);

        VkWriteDescriptorSet &writeSet = ANGLE_UNSAFE_TODO(writeDescriptorSets[info.binding]);
        // Now fill pImageInfo or pTexelBufferView for writeSet
        for (uint32_t arrayElement = 0; arrayElement < arraySize; ++arrayElement)
        {
            GLuint textureUnit =
                samplerBinding.getTextureUnit(samplerBoundTextureUnits, arrayElement);
            TextureVk *textureVk = textures[textureUnit];

            if (textureTypes[textureUnit] == gl::TextureType::Buffer)
            {
                ASSERT(writeSet.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER);
                const vk::BufferView *view = nullptr;
                ANGLE_TRY(textureVk->getBufferView(context, nullptr, &samplerBinding, false, &view,
                                                   nullptr));

                VkBufferView &bufferView  = updateBuilder->allocBufferView();
                bufferView                = view->getHandle();
                writeSet.pTexelBufferView = &bufferView;
            }
            else
            {
                ASSERT(writeSet.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
                bool isSamplerExternalY2Y =
                    samplerBinding.samplerType == GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT;
                gl::Sampler *sampler       = samplers[textureUnit].get();
                const SamplerVk *samplerVk = sampler ? vk::GetImpl(sampler) : nullptr;
                const vk::SamplerHelper &samplerHelper =
                    samplerVk ? samplerVk->getSampler()
                              : textureVk->getSampler(isSamplerExternalY2Y);
                const gl::SamplerState &samplerState =
                    sampler ? sampler->getSamplerState() : textureVk->getState().getSamplerState();

                vk::ImageAccess imageAccess    = textureVk->getImage().getCurrentImageAccess();
                const vk::ImageView &imageView = textureVk->getReadImageView(
                    samplerState.getSRGBDecode(), samplerUniform.isTexelFetchStaticUse(),
                    isSamplerExternalY2Y);

                VkDescriptorImageInfo *imageInfo =
                    const_cast<VkDescriptorImageInfo *>(&ANGLE_UNSAFE_TODO(
                        writeSet.pImageInfo[arrayElement + samplerUniform.getOuterArrayOffset()]));
                imageInfo->imageLayout = renderer->getVkImageLayout(imageAccess);
                imageInfo->imageView   = imageView.getHandle();
                imageInfo->sampler     = samplerHelper.get().getHandle();
            }
        }
    }

    return angle::Result::Continue;
}

void UpdateBufferWithSharedCacheKey(const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding,
                                    const vk::SharedDescriptorSetCacheKey &sharedCacheKey)
{
    if (bufferBinding.get() != nullptr)
    {
        // For simplicity, we do not check if uniform is active or duplicate. The worst case is
        // we unnecessarily delete the cache entry when buffer bound to inactive uniform is
        // destroyed.
        BufferVk *bufferVk             = vk::GetImpl(bufferBinding.get());
        vk::BufferHelper &bufferHelper = bufferVk->getBuffer();
        bufferHelper.onNewDescriptorSet(sharedCacheKey);
    }
}
}  // namespace

class ProgramExecutableVk::WarmUpTaskCommon : public vk::ErrorContext, public LinkSubTask
{
  public:
    WarmUpTaskCommon(vk::Renderer *renderer) : vk::ErrorContext(renderer) {}
    WarmUpTaskCommon(vk::Renderer *renderer,
                     ProgramExecutableVk *executableVk,
                     vk::PipelineRobustness pipelineRobustness,
                     vk::PipelineProtectedAccess pipelineProtectedAccess)
        : vk::ErrorContext(renderer),
          mExecutableVk(executableVk),
          mPipelineRobustness(pipelineRobustness),
          mPipelineProtectedAccess(pipelineProtectedAccess)
    {}
    ~WarmUpTaskCommon() override = default;

    void handleError(VkResult result,
                     const char *file,
                     const char *function,
                     unsigned int line) override
    {
        mErrorCode     = result;
        mErrorFile     = file;
        mErrorFunction = function;
        mErrorLine     = line;
    }

    void operator()() override { UNREACHABLE(); }

    angle::Result getResult(const gl::Context *context, gl::InfoLog &infoLog) override
    {
        ContextVk *contextVk = vk::GetImpl(context);
        return getResultImpl(contextVk, infoLog);
    }

    angle::Result getResultImpl(ContextVk *contextVk, gl::InfoLog &infoLog)
    {
        // Forward any errors
        if (mErrorCode != VK_SUCCESS)
        {
            contextVk->handleError(mErrorCode, mErrorFile, mErrorFunction, mErrorLine);
            return angle::Result::Stop;
        }

        // Accumulate relevant perf counters
        const angle::VulkanPerfCounters &from = getPerfCounters();
        angle::VulkanPerfCounters &to         = contextVk->getPerfCounters();

        to.pipelineCreationCacheHits += from.pipelineCreationCacheHits;
        to.pipelineCreationCacheMisses += from.pipelineCreationCacheMisses;
        to.pipelineCreationTotalCacheHitsDurationNs +=
            from.pipelineCreationTotalCacheHitsDurationNs;
        to.pipelineCreationTotalCacheMissesDurationNs +=
            from.pipelineCreationTotalCacheMissesDurationNs;

        return angle::Result::Continue;
    }

    virtual void removeFailedPipeline() {}

  protected:
    void mergeProgramExecutablePipelineCacheToRenderer()
    {
        angle::Result mergeResult = mExecutableVk->mergePipelineCacheToRenderer(this);

        // Treat error during merge as non fatal, log it and move on
        if (mergeResult != angle::Result::Continue)
        {
            INFO() << "Error while merging to Renderer's pipeline cache";
        }
    }

    // The front-end ensures that the program is not modified while the subtask is running, so it is
    // safe to directly access the executable from this parallel job.  Note that this is the reason
    // why the front-end does not let the parallel job continue when a relink happens or the first
    // draw with this program.
    ProgramExecutableVk *mExecutableVk               = nullptr;
    const vk::PipelineRobustness mPipelineRobustness = vk::PipelineRobustness::NonRobust;
    const vk::PipelineProtectedAccess mPipelineProtectedAccess =
        vk::PipelineProtectedAccess::Unprotected;

    // Error handling
    VkResult mErrorCode        = VK_SUCCESS;
    const char *mErrorFile     = nullptr;
    const char *mErrorFunction = nullptr;
    unsigned int mErrorLine    = 0;
};

class ProgramExecutableVk::WarmUpComputeTask : public WarmUpTaskCommon
{
  public:
    WarmUpComputeTask(vk::Renderer *renderer,
                      ProgramExecutableVk *executableVk,
                      vk::PipelineRobustness pipelineRobustness,
                      vk::PipelineProtectedAccess pipelineProtectedAccess)
        : WarmUpTaskCommon(renderer, executableVk, pipelineRobustness, pipelineProtectedAccess)
    {}
    ~WarmUpComputeTask() override = default;

    void operator()() override
    {
        angle::Result result = mExecutableVk->warmUpComputePipelineCache(this, mPipelineRobustness,
                                                                         mPipelineProtectedAccess);
        ASSERT((result == angle::Result::Continue) == (mErrorCode == VK_SUCCESS));

        mergeProgramExecutablePipelineCacheToRenderer();
    }
};

using SharedRenderPass = vk::AtomicRefCounted<vk::RenderPass>;
class ProgramExecutableVk::WarmUpGraphicsTask : public WarmUpTaskCommon
{
  public:
    WarmUpGraphicsTask(vk::Renderer *renderer,
                       ProgramExecutableVk *executableVk,
                       vk::PipelineRobustness pipelineRobustness,
                       vk::PipelineProtectedAccess pipelineProtectedAccess,
                       vk::GraphicsPipelineSubset subset,
                       const vk::GraphicsPipelineDesc &graphicsPipelineDesc,
                       ProgramInfo &programInfo,
                       CompleteGraphicsPipelineCache &completePipelines,
                       ShadersGraphicsPipelineCache &shadersPipelines,
                       SharedRenderPass *compatibleRenderPass,
                       vk::PipelineHelper *placeholderPipelineHelper)
        : WarmUpTaskCommon(renderer, executableVk, pipelineRobustness, pipelineProtectedAccess),
          mPipelineSubset(subset),
          mGraphicsPipelineDesc(graphicsPipelineDesc),
          mWarmUpPipelineHelper(placeholderPipelineHelper),
          mProgramInfo(programInfo),
          mCompletePipelines(completePipelines),
          mShadersPipelines(shadersPipelines),
          mCompatibleRenderPass(compatibleRenderPass)
    {
        ASSERT(mCompatibleRenderPass);
        mCompatibleRenderPass->addRef();
    }
    ~WarmUpGraphicsTask() override = default;

    void operator()() override
    {
        angle::Result result = mExecutableVk->warmUpGraphicsPipelineCache(
            this, mPipelineRobustness, mPipelineProtectedAccess, mPipelineSubset,
            mGraphicsPipelineDesc, mProgramInfo, mCompletePipelines, mShadersPipelines,
            mCompatibleRenderPass->get(), mWarmUpPipelineHelper);
        ASSERT((result == angle::Result::Continue) == (mErrorCode == VK_SUCCESS));

        // Release reference to shared renderpass. If this is the last reference -
        // 1. merge ProgramExecutableVk's pipeline cache into the Renderer's cache
        // 2. cleanup temporary renderpass
        //
        // Note: with dynamic rendering, |mCompatibleRenderPass| holds a VK_NULL_HANDLE, and it's
        // just used as a ref count for this purpose.
        const bool isLastWarmUpTask = mCompatibleRenderPass->getAndReleaseRef() == 1;
        if (isLastWarmUpTask)
        {
            mergeProgramExecutablePipelineCacheToRenderer();

            mCompatibleRenderPass->get().destroy(getDevice());
            SafeDelete(mCompatibleRenderPass);
        }
    }

    void removeFailedPipeline() override
    {
        // Remove the placeholder entry in GraphicsPipelineCache. This
        // function must NOT be called from the task itself, as the cache is
        // not internally synchronized, which is why there was a placeholder
        // pipeline in the first place.
        ASSERT(mErrorCode != VK_SUCCESS);
        if (mPipelineSubset == vk::GraphicsPipelineSubset::Complete)
        {
            mCompletePipelines.remove(mGraphicsPipelineDesc);
        }
        else
        {
            mShadersPipelines.remove(mGraphicsPipelineDesc);
        }
    }

  private:
    vk::GraphicsPipelineSubset mPipelineSubset;
    vk::GraphicsPipelineDesc mGraphicsPipelineDesc;
    vk::PipelineHelper *mWarmUpPipelineHelper;
    ProgramInfo &mProgramInfo;
    CompleteGraphicsPipelineCache &mCompletePipelines;
    ShadersGraphicsPipelineCache &mShadersPipelines;

    // Temporary objects to clean up at the end
    SharedRenderPass *mCompatibleRenderPass;
};

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

ShaderInfo::~ShaderInfo() = default;

angle::Result ShaderInfo::initShaders(vk::ErrorContext *context,
                                      const gl::ShaderBitSet &linkedShaderStages,
                                      const gl::ShaderMap<const angle::spirv::Blob *> &spirvBlobs,
                                      const ShaderInterfaceVariableInfoMap &variableInfoMap,
                                      bool isGLES1)
{
    clear();

    for (gl::ShaderType shaderType : gl::AllShaderTypes())
    {
        if (spirvBlobs[shaderType] != nullptr)
        {
            mSpirvBlobs[shaderType] = *spirvBlobs[shaderType];
        }
    }

    // Assert that SPIR-V transformation is correct, even if the test never issues a draw call.
    // Don't validate GLES1 programs because they are always created right before a draw, so they
    // will naturally be validated.  This improves GLES1 test run times.
    if (!isGLES1)
    {
        ASSERT(ValidateTransformedSpirV(context, linkedShaderStages, variableInfoMap, mSpirvBlobs));
    }

    mIsInitialized = true;
    return angle::Result::Continue;
}

void ShaderInfo::initShaderFromProgram(gl::ShaderType shaderType,
                                       const ShaderInfo &programShaderInfo)
{
    mSpirvBlobs[shaderType] = programShaderInfo.mSpirvBlobs[shaderType];
    mIsInitialized          = true;
}

void ShaderInfo::clear()
{
    for (angle::spirv::Blob &spirvBlob : mSpirvBlobs)
    {
        spirvBlob.clear();
    }
    mIsInitialized = false;
}

void ShaderInfo::load(gl::BinaryInputStream *stream)
{
    clear();

    // Read in shader codes for all shader types
    for (gl::ShaderType shaderType : gl::AllShaderTypes())
    {
        stream->readVector(&mSpirvBlobs[shaderType]);
    }

    mIsInitialized = true;
}

void ShaderInfo::save(gl::BinaryOutputStream *stream)
{
    ASSERT(valid());

    // Write out shader codes for all shader types
    for (gl::ShaderType shaderType : gl::AllShaderTypes())
    {
        stream->writeVector(mSpirvBlobs[shaderType]);
    }
}

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

ProgramInfo::~ProgramInfo() = default;

angle::Result ProgramInfo::initProgram(vk::ErrorContext *context,
                                       gl::ShaderType shaderType,
                                       bool isLastPreFragmentStage,
                                       bool isTransformFeedbackProgram,
                                       const ShaderInfo &shaderInfo,
                                       ProgramTransformOptions optionBits,
                                       const ShaderInterfaceVariableInfoMap &variableInfoMap)
{
    const gl::ShaderMap<angle::spirv::Blob> &originalSpirvBlobs = shaderInfo.getSpirvBlobs();
    const angle::spirv::Blob &originalSpirvBlob                 = originalSpirvBlobs[shaderType];
    gl::ShaderMap<angle::spirv::Blob> transformedSpirvBlobs;
    angle::spirv::Blob &transformedSpirvBlob = transformedSpirvBlobs[shaderType];

    SpvTransformOptions options;
    options.shaderType               = shaderType;
    options.isLastPreFragmentStage   = isLastPreFragmentStage;
    options.isTransformFeedbackStage = isLastPreFragmentStage && isTransformFeedbackProgram &&
                                       !optionBits.removeTransformFeedbackEmulation;
    options.isTransformFeedbackEmulated = context->getFeatures().emulateTransformFeedback.enabled;
    options.isMultisampledFramebufferFetch =
        optionBits.multiSampleFramebufferFetch && shaderType == gl::ShaderType::Fragment;
    options.enableSampleShading = optionBits.enableSampleShading;
    options.removeDepthInput =
        optionBits.removeDepthInput && shaderType == gl::ShaderType::Fragment;
    options.removeStencilInput =
        optionBits.removeStencilInput && shaderType == gl::ShaderType::Fragment;

    options.useSpirvVaryingPrecisionFixer =
        context->getFeatures().varyingsRequireMatchingPrecisionInSpirv.enabled;

    options.ditherControl = (shaderType == gl::ShaderType::Fragment) ? optionBits.ditherControl : 0;
    options.roundOutputAfterDithering = context->getFeatures().roundOutputAfterDithering.enabled;

    ANGLE_TRY(
        SpvTransformSpirvCode(options, variableInfoMap, originalSpirvBlob, &transformedSpirvBlob));
    ANGLE_TRY(vk::InitShaderModule(context, &mShaders[shaderType], transformedSpirvBlob.data(),
                                   transformedSpirvBlob.size() * sizeof(uint32_t)));

    mProgramHelper.setShader(shaderType, mShaders[shaderType]);

    return angle::Result::Continue;
}

void ProgramInfo::release(ContextVk *contextVk)
{
    mProgramHelper.release(contextVk);

    for (vk::ShaderModulePtr &shader : mShaders)
    {
        shader.reset();
    }
}

ProgramExecutableVk::ProgramExecutableVk(const gl::ProgramExecutable *executable)
    : ProgramExecutableImpl(executable),
      mImmutableSamplersMaxDescriptorCount(1),
      mUniformBufferDescriptorType(VK_DESCRIPTOR_TYPE_MAX_ENUM),
      mDefaultUniformDynamicDescriptorOffsets{},
      mValidComputePermutations{}
{
    for (std::shared_ptr<BufferAndLayout> &defaultBlock : mDefaultUniformBlocks)
    {
        defaultBlock = std::make_shared<BufferAndLayout>();
    }
}

ProgramExecutableVk::~ProgramExecutableVk()
{
    ASSERT(!mPipelineCache.valid());
}

void ProgramExecutableVk::destroy(const gl::Context *context)
{
    reset(vk::GetImpl(context));
}

void ProgramExecutableVk::resetLayout(ContextVk *contextVk)
{
    if (!mPipelineLayout)
    {
        ASSERT(mGraphicsProgramInfos.empty());
        ASSERT(mValidComputePermutations.none());
        return;
    }

    waitForPostLinkTasksImpl(contextVk);

    for (auto &descriptorSetLayout : mDescriptorSetLayouts)
    {
        descriptorSetLayout.reset();
    }
    mImmutableSamplersMaxDescriptorCount = 1;
    mImmutableSamplerIndexMap.clear();

    for (vk::DescriptorSetPointer &descriptorSet : mDescriptorSets)
    {
        descriptorSet.reset();
    }
    mValidDescriptorSetIndices.reset();

    for (vk::DynamicDescriptorPoolPointer &pool : mDynamicDescriptorPools)
    {
        pool.reset();
    }

    // Initialize with an invalid BufferSerial
    mCurrentDefaultUniformBufferSerial = vk::BufferSerial();

    for (auto &completeGraphicsPipeline : mCompleteGraphicsPipelines)
    {
        completeGraphicsPipeline.second.release(contextVk);
    }
    for (auto &shadersGraphicsPipeline : mShadersGraphicsPipelines)
    {
        shadersGraphicsPipeline.second.release(contextVk);
    }
    for (auto &graphicsProgramInfo : mGraphicsProgramInfos)
    {
        // Program infos and pipeline layout must be released after pipelines are; they might be
        // having pending jobs that are referencing them.
        graphicsProgramInfo.second.release(contextVk);
    }
    mCompleteGraphicsPipelines.clear();
    mShadersGraphicsPipelines.clear();
    mGraphicsProgramInfos.clear();

    mComputePipelines.release(contextVk);
    mComputeProgramInfo.release(contextVk);
    mValidComputePermutations.reset();

    mPipelineLayout.reset();

    contextVk->onProgramExecutableReset(this);
}

void ProgramExecutableVk::reset(ContextVk *contextVk)
{
    resetLayout(contextVk);

    if (mPipelineCache.valid())
    {
        mPipelineCache.destroy(contextVk->getDevice());
    }
}

angle::Result ProgramExecutableVk::initializePipelineCache(vk::ErrorContext *context,
                                                           bool compressed,
                                                           const std::vector<uint8_t> &pipelineData)
{
    ASSERT(!mPipelineCache.valid());

    size_t dataSize            = pipelineData.size();
    const uint8_t *dataPointer = pipelineData.data();

    angle::MemoryBuffer uncompressedData;
    if (compressed)
    {
        if (!angle::DecompressBlob(dataPointer, dataSize, kMaxLocalPipelineCacheSize,
                                   &uncompressedData))
        {
            return angle::Result::Stop;
        }
        dataSize    = uncompressedData.size();
        dataPointer = uncompressedData.data();
    }

    VkPipelineCacheCreateInfo pipelineCacheCreateInfo = {};
    pipelineCacheCreateInfo.sType           = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
    pipelineCacheCreateInfo.initialDataSize = dataSize;
    pipelineCacheCreateInfo.pInitialData    = dataPointer;

    ANGLE_VK_TRY(context, mPipelineCache.init(context->getDevice(), pipelineCacheCreateInfo));

    // Merge the pipeline cache into Renderer's.
    if (context->getFeatures().mergeProgramPipelineCachesToGlobalCache.enabled)
    {
        ANGLE_TRY(context->getRenderer()->mergeIntoPipelineCache(context, mPipelineCache));
    }

    return angle::Result::Continue;
}

angle::Result ProgramExecutableVk::ensurePipelineCacheInitialized(vk::ErrorContext *context)
{
    if (!mPipelineCache.valid())
    {
        VkPipelineCacheCreateInfo pipelineCacheCreateInfo = {};
        pipelineCacheCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;

        ANGLE_VK_TRY(context, mPipelineCache.init(context->getDevice(), pipelineCacheCreateInfo));
    }

    return angle::Result::Continue;
}

angle::Result ProgramExecutableVk::load(ContextVk *contextVk,
                                        bool isSeparable,
                                        gl::BinaryInputStream *stream,
                                        egl::CacheGetResult *resultOut)
{
    mVariableInfoMap.load(stream);
    mOriginalShaderInfo.load(stream);

    // Deserializes the uniformLayout data of mDefaultUniformBlocks
    for (gl::ShaderType shaderType : gl::AllShaderTypes())
    {
        stream->readVector(&mDefaultUniformBlocks[shaderType]->uniformLayout);
    }

    // Deserializes required uniform block memory sizes
    gl::ShaderMap<size_t> requiredBufferSize;
    stream->readPackedEnumMap(&requiredBufferSize);

    if (!isSeparable && !contextVk->getFeatures().preferGlobalPipelineCache.enabled)
    {
        size_t compressedPipelineDataSize = 0;
        stream->readInt<size_t>(&compressedPipelineDataSize);

        std::vector<uint8_t> compressedPipelineData(compressedPipelineDataSize);
        if (compressedPipelineDataSize > 0)
        {
            bool compressedData = false;
            stream->readBool(&compressedData);
            stream->readBytes(compressedPipelineData);
            // Initialize the pipeline cache based on cached data.
            ANGLE_TRY(initializePipelineCache(contextVk, compressedData, compressedPipelineData));
        }
    }

    // Initialize and resize the mDefaultUniformBlocks' memory
    ANGLE_TRY(resizeUniformBlockMemory(contextVk, requiredBufferSize));

    resetLayout(contextVk);
    ANGLE_TRY(createPipelineLayout(contextVk, &contextVk->getPipelineLayoutCache(),
                                   &contextVk->getDescriptorSetLayoutCache(), nullptr));

    ANGLE_TRY(initializeDescriptorPools(contextVk, &contextVk->getDescriptorSetLayoutCache(),
                                        &contextVk->getMetaDescriptorPools()));

    *resultOut = egl::CacheGetResult::Success;
    return angle::Result::Continue;
}

void ProgramExecutableVk::save(ContextVk *contextVk,
                               bool isSeparable,
                               gl::BinaryOutputStream *stream)
{
    mVariableInfoMap.save(stream);
    mOriginalShaderInfo.save(stream);

    // Serializes the uniformLayout data of mDefaultUniformBlocks
    for (gl::ShaderType shaderType : gl::AllShaderTypes())
    {
        stream->writeVector(mDefaultUniformBlocks[shaderType]->uniformLayout);
    }

    // Serializes required uniform block memory sizes
    gl::ShaderMap<size_t> uniformDataSize;
    for (gl::ShaderType shaderType : gl::AllShaderTypes())
    {
        uniformDataSize[shaderType] = mDefaultUniformBlocks[shaderType]->uniformData.size();
    }
    stream->writePackedEnumMap(uniformDataSize);

    // Need to wait for warm up tasks to complete.
    waitForPostLinkTasksImpl(contextVk);

    // Compress and save mPipelineCache.  Separable programs don't warm up the cache, while program
    // pipelines do.  However, currently ANGLE doesn't sync program pipelines to cache.  ANGLE could
    // potentially use VK_EXT_graphics_pipeline_library to create separate pipelines for
    // pre-rasterization and fragment subsets, but currently those subsets are bundled together.
    if (!isSeparable && !contextVk->getFeatures().preferGlobalPipelineCache.enabled)
    {
        angle::MemoryBuffer cacheData;

        GetPipelineCacheData(contextVk, mPipelineCache, &cacheData);
        stream->writeInt(cacheData.size());
        if (cacheData.size() > 0)
        {
            stream->writeBool(contextVk->getFeatures().enablePipelineCacheDataCompression.enabled);
            stream->writeBytes(cacheData);
        }
    }
}

void ProgramExecutableVk::clearVariableInfoMap()
{
    mVariableInfoMap.clear();
}

angle::Result ProgramExecutableVk::getPipelineCacheWarmUpTasks(
    vk::Renderer *renderer,
    vk::PipelineRobustness pipelineRobustness,
    vk::PipelineProtectedAccess pipelineProtectedAccess,
    std::vector<std::shared_ptr<LinkSubTask>> *postLinkSubTasksOut)
{
    ASSERT(!postLinkSubTasksOut || postLinkSubTasksOut->empty());

    const vk::GraphicsPipelineSubset subset = GetWarmUpSubset(renderer->getFeatures());

    bool isCompute                                        = false;
    vk::GraphicsPipelineDesc *graphicsPipelineDesc        = nullptr;
    vk::RenderPass compatibleRenderPass;

    WarmUpTaskCommon prepForWarmUpContext(renderer);
    ANGLE_TRY(preparePipelineCacheForWarmUp(&prepForWarmUpContext, pipelineRobustness,
                                            pipelineProtectedAccess, subset, &isCompute,
                                            &graphicsPipelineDesc, &compatibleRenderPass));

    std::vector<std::shared_ptr<rx::LinkSubTask>> warmUpSubTasks;
    if (isCompute)
    {
        ASSERT(!compatibleRenderPass.valid());

        warmUpSubTasks.push_back(std::make_shared<WarmUpComputeTask>(
            renderer, this, pipelineRobustness, pipelineProtectedAccess));
    }
    else
    {
        ProgramTransformOptions transformOptions = {};
        SharedRenderPass *sharedRenderPass = new SharedRenderPass(std::move(compatibleRenderPass));

        // Add a placeholder entry in GraphicsPipelineCache
        const uint32_t programIndex        = transformOptions.permutationIndex;
        vk::PipelineHelper *pipelineHelper = nullptr;
        if (subset == vk::GraphicsPipelineSubset::Complete)
        {
            CompleteGraphicsPipelineCache &pipelines = mCompleteGraphicsPipelines[programIndex];
            pipelines.populate(mWarmUpGraphicsPipelineDesc, vk::Pipeline(), &pipelineHelper);
        }
        else
        {
            ASSERT(subset == vk::GraphicsPipelineSubset::Shaders);
            ShadersGraphicsPipelineCache &pipelines = mShadersGraphicsPipelines[programIndex];
            pipelines.populate(mWarmUpGraphicsPipelineDesc, vk::Pipeline(), &pipelineHelper);
        }

        warmUpSubTasks.push_back(std::make_shared<WarmUpGraphicsTask>(
            renderer, this, pipelineRobustness, pipelineProtectedAccess, subset,
            *graphicsPipelineDesc, mGraphicsProgramInfos[programIndex],
            mCompleteGraphicsPipelines[programIndex], mShadersGraphicsPipelines[programIndex],
            sharedRenderPass, pipelineHelper));
    }

    // If the caller hasn't provided a valid async task container, inline the warmUp tasks.
    if (postLinkSubTasksOut)
    {
        *postLinkSubTasksOut = std::move(warmUpSubTasks);
    }
    else
    {
        for (std::shared_ptr<rx::LinkSubTask> &task : warmUpSubTasks)
        {
            (*task)();
        }
        warmUpSubTasks.clear();
    }

    ASSERT(warmUpSubTasks.empty());

    return angle::Result::Continue;
}

angle::Result ProgramExecutableVk::preparePipelineCacheForWarmUp(
    vk::ErrorContext *context,
    vk::PipelineRobustness pipelineRobustness,
    vk::PipelineProtectedAccess pipelineProtectedAccess,
    vk::GraphicsPipelineSubset subset,
    bool *isComputeOut,
    vk::GraphicsPipelineDesc **graphicsPipelineDescOut,
    vk::RenderPass *renderPassOut)
{
    ASSERT(isComputeOut);
    ASSERT(graphicsPipelineDescOut);
    ASSERT(renderPassOut);
    ASSERT(context->getFeatures().warmUpPipelineCacheAtLink.enabled);

    // Ensure pipeline cache is initialized
    if (context->getFeatures().preferGlobalPipelineCache.enabled)
    {
        // Make sure Renderer's pipeline cache is initialized
        vk::PipelineCacheAccess unused;
        ANGLE_TRY(context->getRenderer()->getPipelineCache(context, &unused));
    }
    else
    {
        // Make sure ProgramExecutableVk's pipeline cache is initialized
        ANGLE_TRY(ensurePipelineCacheInitialized(context));
    }

    *isComputeOut        = false;
    const bool isCompute = mExecutable->hasLinkedShaderStage(gl::ShaderType::Compute);
    if (isCompute)
    {
        // Initialize compute program.
        vk::ComputePipelineOptions pipelineOptions =
            vk::GetComputePipelineOptions(pipelineRobustness, pipelineProtectedAccess);
        ANGLE_TRY(
            initComputeProgram(context, &mComputeProgramInfo, mVariableInfoMap, pipelineOptions));

        *isComputeOut = true;
        return angle::Result::Continue;
    }

    // It is only at drawcall time that we will have complete information required to build the
    // graphics pipeline descriptor. Use the most "commonly seen" state values and create the
    // pipeline.
    gl::PrimitiveMode mode = (mExecutable->hasLinkedShaderStage(gl::ShaderType::TessControl) ||
                              mExecutable->hasLinkedShaderStage(gl::ShaderType::TessEvaluation))
                                 ? gl::PrimitiveMode::Patches
                             : mExecutable->hasLinkedShaderStage(gl::ShaderType::Geometry)
                                 ? mExecutable->getGeometryShaderInputPrimitiveType()
                                 : gl::PrimitiveMode::Triangles;
    SetupDefaultPipelineState(context, *mExecutable, mode, pipelineRobustness,
                              pipelineProtectedAccess, subset, &mWarmUpGraphicsPipelineDesc);

    // Create a temporary compatible RenderPass.  The render pass cache in ContextVk cannot be used
    // because this function may be called from a worker thread.
    vk::AttachmentOpsArray ops;
    RenderPassCache::InitializeOpsForCompatibleRenderPass(
        mWarmUpGraphicsPipelineDesc.getRenderPassDesc(), &ops);
    if (!context->getFeatures().preferDynamicRendering.enabled)
    {
        ANGLE_TRY(RenderPassCache::MakeRenderPass(
            context, mWarmUpGraphicsPipelineDesc.getRenderPassDesc(), ops, renderPassOut, nullptr));
    }

    *graphicsPipelineDescOut = &mWarmUpGraphicsPipelineDesc;

    // There are a number of states that are not currently dynamic (and may never be, such as sample
    // shading), but pre-creating shaders for them is impractical.  Most such state is likely unused
    // by most applications, but variations can be added here for certain apps that are known to
    // benefit from it.
    ProgramTransformOptions transformOptions = {};
    return initGraphicsShaderPrograms(context, transformOptions);
}

angle::Result ProgramExecutableVk::warmUpComputePipelineCache(
    vk::ErrorContext *context,
    vk::PipelineRobustness pipelineRobustness,
    vk::PipelineProtectedAccess pipelineProtectedAccess)
{
    ANGLE_TRACE_EVENT0("gpu.angle", "ProgramExecutableVk::warmUpComputePipelineCache");

    // This method assumes that all the state necessary to create a compute pipeline has already
    // been setup by the caller. Assert that all required state is valid so all that is left will
    // be the call to `vkCreateComputePipelines`

    // Make sure the shader module for compute shader stage is valid.
    ASSERT(mComputeProgramInfo.valid(gl::ShaderType::Compute));

    vk::PipelineCacheAccess pipelineCache;
    if (context->getFeatures().preferGlobalPipelineCache.enabled)
    {
        ANGLE_TRY(context->getRenderer()->getPipelineCache(context, &pipelineCache));
    }
    else
    {
        // No synchronization necessary since mPipelineCache is internally synchronized.
        pipelineCache.init(&mPipelineCache, nullptr);
    }

    // There is no state associated with compute programs, so only one pipeline needs creation
    // to warm up the cache.
    vk::PipelineHelper *pipeline = nullptr;
    ANGLE_TRY(getOrCreateComputePipeline(context, &pipelineCache, PipelineSource::WarmUp,
                                         pipelineRobustness, pipelineProtectedAccess, &pipeline));

    return angle::Result::Continue;
}

angle::Result ProgramExecutableVk::warmUpGraphicsPipelineCache(
    vk::ErrorContext *context,
    vk::PipelineRobustness pipelineRobustness,
    vk::PipelineProtectedAccess pipelineProtectedAccess,
    vk::GraphicsPipelineSubset subset,
    const vk::GraphicsPipelineDesc &graphicsPipelineDesc,
    ProgramInfo &programInfo,
    CompleteGraphicsPipelineCache &completePipelines,
    ShadersGraphicsPipelineCache &shadersPipelines,
    const vk::RenderPass &renderPass,
    vk::PipelineHelper *placeholderPipelineHelper)
{
    ANGLE_TRACE_EVENT0("gpu.angle", "ProgramExecutableVk::warmUpGraphicsPipelineCache");

    ASSERT(placeholderPipelineHelper && !placeholderPipelineHelper->valid());

    vk::PipelineCacheAccess pipelineCache;

    if (context->getFeatures().preferGlobalPipelineCache.enabled)
    {
        ANGLE_TRY(context->getRenderer()->getPipelineCache(context, &pipelineCache));
    }
    else
    {
        // No synchronization necessary since mPipelineCache is internally synchronized.
        pipelineCache.init(&mPipelineCache, nullptr);
    }

    const vk::GraphicsPipelineDesc *descPtr  = nullptr;

    ANGLE_TRY(createGraphicsPipelineImpl(context, programInfo, completePipelines, shadersPipelines,
                                         subset, &pipelineCache, PipelineSource::WarmUp,
                                         graphicsPipelineDesc, renderPass, &descPtr,
                                         &placeholderPipelineHelper));

    ASSERT(placeholderPipelineHelper->valid());
    return angle::Result::Continue;
}

void ProgramExecutableVk::waitForPostLinkTasksImpl(ContextVk *contextVk)
{
    const std::vector<std::shared_ptr<rx::LinkSubTask>> &postLinkSubTasks =
        mExecutable->getPostLinkSubTasks();

    if (postLinkSubTasks.empty())
    {
        return;
    }

    // Wait for all post-link tasks to finish
    angle::WaitableEvent::WaitMany(&mExecutable->getPostLinkSubTaskWaitableEvents());

    // Get results and clean up
    for (const std::shared_ptr<rx::LinkSubTask> &task : postLinkSubTasks)
    {
        WarmUpTaskCommon *warmUpTask = static_cast<WarmUpTaskCommon *>(task.get());

        // As these tasks can be run post-link, their results are ignored.  Failure is harmless, but
        // more importantly the error (effectively due to a link event) may not be allowed through
        // the entry point that results in this call.
        gl::InfoLog infoLog;
        angle::Result result = warmUpTask->getResultImpl(contextVk, infoLog);
        if (result != angle::Result::Continue)
        {
            ANGLE_PERF_WARNING(contextVk->getDebug(), GL_DEBUG_SEVERITY_LOW,
                               "Post-link task unexpectedly failed. Performance may degrade, or "
                               "device may soon be lost");

            warmUpTask->removeFailedPipeline();
        }
    }

    mExecutable->onPostLinkTasksComplete();
}

void ProgramExecutableVk::waitForGraphicsPostLinkTasks(
    ContextVk *contextVk,
    const vk::GraphicsPipelineDesc &currentGraphicsPipelineDesc)
{
    ASSERT(mExecutable->hasLinkedShaderStage(gl::ShaderType::Vertex));

    if (mExecutable->getPostLinkSubTasks().empty())
    {
        return;
    }

    const vk::GraphicsPipelineSubset subset = GetWarmUpSubset(contextVk->getFeatures());

    if (!mWarmUpGraphicsPipelineDesc.keyEqual(currentGraphicsPipelineDesc, subset))
    {
        // The GraphicsPipelineDesc used for warm up differs from the one used by the draw call.
        // There is no need to wait for the warm up tasks to complete.
        ANGLE_PERF_WARNING(
            contextVk->getDebug(), GL_DEBUG_SEVERITY_LOW,
            "GraphicsPipelineDesc used for warm up differs from the one used by draw.");

        // If the warm up tasks are finished anyway, let |waitForPostLinkTasksImpl| clean them up.
        if (!angle::WaitableEvent::AllReady(&mExecutable->getPostLinkSubTaskWaitableEvents()))
        {
            return;
        }
    }

    waitForPostLinkTasksImpl(contextVk);
}

angle::Result ProgramExecutableVk::mergePipelineCacheToRenderer(vk::ErrorContext *context) const
{
    // Merge the cache with Renderer's
    if (context->getFeatures().mergeProgramPipelineCachesToGlobalCache.enabled)
    {
        ANGLE_TRACE_EVENT0("gpu.angle", "ProgramExecutableVk::mergePipelineCacheToRenderer");
        ANGLE_TRY(context->getRenderer()->mergeIntoPipelineCache(context, mPipelineCache));
    }

    return angle::Result::Continue;
}

void ProgramExecutableVk::addInterfaceBlockDescriptorSetDesc(
    const std::vector<gl::InterfaceBlock> &blocks,
    gl::ShaderBitSet shaderTypes,
    VkDescriptorType descType,
    vk::DescriptorSetLayoutDesc *descOut)
{
    for (uint32_t bufferIndex = 0, arraySize = 0; bufferIndex < blocks.size();
         bufferIndex += arraySize)
    {
        gl::InterfaceBlock block = blocks[bufferIndex];
        arraySize                = GetInterfaceBlockArraySize(blocks, bufferIndex);

        if (block.activeShaders().none())
        {
            continue;
        }

        const gl::ShaderType firstShaderType = block.getFirstActiveShaderType();
        const ShaderInterfaceVariableInfo &info =
            mVariableInfoMap.getVariableById(firstShaderType, block.getId(firstShaderType));

        const VkShaderStageFlags activeStages = gl_vk::GetShaderStageFlags(info.activeStages);

        descOut->addBinding(info.binding, descType, arraySize, activeStages, nullptr);
    }
}

void ProgramExecutableVk::addAtomicCounterBufferDescriptorSetDesc(
    const std::vector<gl::AtomicCounterBuffer> &atomicCounterBuffers,
    vk::DescriptorSetLayoutDesc *descOut)
{
    if (atomicCounterBuffers.empty())
    {
        return;
    }

    const ShaderInterfaceVariableInfo &info =
        mVariableInfoMap.getAtomicCounterInfo(atomicCounterBuffers[0].getFirstActiveShaderType());
    VkShaderStageFlags activeStages = gl_vk::GetShaderStageFlags(info.activeStages);

    // A single storage buffer array is used for all stages for simplicity.
    descOut->addBinding(info.binding, vk::kStorageBufferDescriptorType,
                        gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, activeStages,
                        nullptr);
}

void ProgramExecutableVk::addImageDescriptorSetDesc(vk::DescriptorSetLayoutDesc *descOut)
{
    const std::vector<gl::ImageBinding> &imageBindings = mExecutable->getImageBindings();
    const std::vector<gl::LinkedUniform> &uniforms     = mExecutable->getUniforms();

    for (uint32_t imageIndex = 0; imageIndex < imageBindings.size(); ++imageIndex)
    {
        uint32_t uniformIndex = mExecutable->getUniformIndexFromImageIndex(imageIndex);
        const gl::LinkedUniform &imageUniform = uniforms[uniformIndex];

        // 2D arrays are split into multiple 1D arrays when generating LinkedUniforms. Since they
        // are flattened into one array, ignore the nonzero elements and expand the array to the
        // total array size.
        if (imageUniform.activeShaders().none() || imageUniform.getOuterArrayOffset() > 0)
        {
            ASSERT(gl::SamplerNameContainsNonZeroArrayElement(
                mExecutable->getUniformNameByIndex(uniformIndex)));
            continue;
        }

        ASSERT(!gl::SamplerNameContainsNonZeroArrayElement(
            mExecutable->getUniformNameByIndex(uniformIndex)));

        // The front-end always binds array image units sequentially.
        const gl::ImageBinding &imageBinding = imageBindings[imageIndex];
        uint32_t arraySize = static_cast<uint32_t>(imageBinding.boundImageUnits.size());
        arraySize *= imageUniform.getOuterArraySizeProduct();

        const gl::ShaderType firstShaderType = imageUniform.getFirstActiveShaderType();
        const ShaderInterfaceVariableInfo &info =
            mVariableInfoMap.getVariableById(firstShaderType, imageUniform.getId(firstShaderType));

        const VkShaderStageFlags activeStages = gl_vk::GetShaderStageFlags(info.activeStages);

        const VkDescriptorType descType = imageBinding.textureType == gl::TextureType::Buffer
                                              ? VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER
                                              : VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
        descOut->addBinding(info.binding, descType, arraySize, activeStages, nullptr);
    }
}

void ProgramExecutableVk::addInputAttachmentDescriptorSetDesc(vk::ErrorContext *context,
                                                              vk::DescriptorSetLayoutDesc *descOut)
{
    if (!mExecutable->getLinkedShaderStages()[gl::ShaderType::Fragment])
    {
        return;
    }

    if (mExecutable->usesDepthFramebufferFetch())
    {
        const uint32_t depthBinding =
            mVariableInfoMap
                .getVariableById(gl::ShaderType::Fragment, sh::vk::spirv::kIdDepthInputAttachment)
                .binding;
        descOut->addBinding(depthBinding, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1,
                            VK_SHADER_STAGE_FRAGMENT_BIT, nullptr);
    }

    if (mExecutable->usesStencilFramebufferFetch())
    {
        const uint32_t stencilBinding =
            mVariableInfoMap
                .getVariableById(gl::ShaderType::Fragment, sh::vk::spirv::kIdStencilInputAttachment)
                .binding;
        descOut->addBinding(stencilBinding, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1,
                            VK_SHADER_STAGE_FRAGMENT_BIT, nullptr);
    }

    if (!mExecutable->usesColorFramebufferFetch())
    {
        return;
    }

    const uint32_t firstInputAttachment =
        static_cast<uint32_t>(mExecutable->getFragmentInoutIndices().first());

    const ShaderInterfaceVariableInfo &baseInfo = mVariableInfoMap.getVariableById(
        gl::ShaderType::Fragment, sh::vk::spirv::kIdInputAttachment0 + firstInputAttachment);

    uint32_t baseBinding = baseInfo.binding - firstInputAttachment;

    const uint32_t maxColorInputAttachmentCount =
        context->getRenderer()->getMaxColorInputAttachmentCount();
    for (uint32_t colorIndex = 0; colorIndex < maxColorInputAttachmentCount; ++colorIndex)
    {
        descOut->addBinding(baseBinding, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1,
                            VK_SHADER_STAGE_FRAGMENT_BIT, nullptr);
        baseBinding++;
    }
}

angle::Result ProgramExecutableVk::addTextureDescriptorSetDesc(
    vk::ErrorContext *context,
    const gl::ActiveTextureArray<TextureVk *> *activeTextures,
    vk::DescriptorSetLayoutDesc *descOut)
{
    const std::vector<gl::SamplerBinding> &samplerBindings = mExecutable->getSamplerBindings();
    const std::vector<gl::LinkedUniform> &uniforms         = mExecutable->getUniforms();
    const std::vector<GLuint> &samplerBoundTextureUnits =
        mExecutable->getSamplerBoundTextureUnits();

    for (uint32_t samplerIndex = 0; samplerIndex < samplerBindings.size(); ++samplerIndex)
    {
        uint32_t uniformIndex = mExecutable->getUniformIndexFromSamplerIndex(samplerIndex);
        const gl::LinkedUniform &samplerUniform = uniforms[uniformIndex];

        // 2D arrays are split into multiple 1D arrays when generating LinkedUniforms. Since they
        // are flattened into one array, ignore the nonzero elements and expand the array to the
        // total array size.
        if (samplerUniform.activeShaders().none() || samplerUniform.getOuterArrayOffset() > 0)
        {
            ASSERT(gl::SamplerNameContainsNonZeroArrayElement(
                mExecutable->getUniformNameByIndex(uniformIndex)));
            continue;
        }

        ASSERT(!gl::SamplerNameContainsNonZeroArrayElement(
            mExecutable->getUniformNameByIndex(uniformIndex)));

        // The front-end always binds array sampler units sequentially.
        const gl::SamplerBinding &samplerBinding = samplerBindings[samplerIndex];
        uint32_t arraySize = static_cast<uint32_t>(samplerBinding.textureUnitsCount);
        arraySize *= samplerUniform.getOuterArraySizeProduct();

        const gl::ShaderType firstShaderType    = samplerUniform.getFirstActiveShaderType();
        const ShaderInterfaceVariableInfo &info = mVariableInfoMap.getVariableById(
            firstShaderType, samplerUniform.getId(firstShaderType));

        const VkShaderStageFlags activeStages = gl_vk::GetShaderStageFlags(info.activeStages);

        // TODO: https://issuetracker.google.com/issues/158215272: how do we handle array of
        // immutable samplers?
        GLuint textureUnit = samplerBinding.getTextureUnit(samplerBoundTextureUnits, 0);
        if (activeTextures != nullptr &&
            (*activeTextures)[textureUnit]->getImage().hasImmutableSampler())
        {
            ASSERT(samplerBinding.textureUnitsCount == 1);

            // In the case of samplerExternal2DY2YEXT, we need
            // samplerYcbcrConversion object with IDENTITY conversion model
            bool isSamplerExternalY2Y =
                samplerBinding.samplerType == GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT;

            // Always take the texture's sampler, that's only way to get to yuv conversion for
            // externalFormat
            const TextureVk *textureVk          = (*activeTextures)[textureUnit];
            const vk::Sampler &immutableSampler = textureVk->getSampler(isSamplerExternalY2Y).get();
            descOut->addBinding(info.binding, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, arraySize,
                                activeStages, &immutableSampler);
            const vk::ImageHelper &image = textureVk->getImage();
            const vk::YcbcrConversionDesc ycbcrConversionDesc =
                isSamplerExternalY2Y ? image.getY2YConversionDesc()
                                     : image.getYcbcrConversionDesc();
            mImmutableSamplerIndexMap[ycbcrConversionDesc] = samplerIndex;
            // The Vulkan spec has the following note -
            // All descriptors in a binding use the same maximum
            // combinedImageSamplerDescriptorCount descriptors to allow implementations to use a
            // uniform stride for dynamic indexing of the descriptors in the binding.
            uint64_t externalFormat        = image.getExternalFormat();
            uint32_t formatDescriptorCount = 0;

            vk::Renderer *renderer = context->getRenderer();

            if (externalFormat != 0)
            {
                ANGLE_TRY(renderer->getFormatDescriptorCountForExternalFormat(
                    context, externalFormat, &formatDescriptorCount));
            }
            else
            {
                VkFormat vkFormat = image.getActualVkFormat(renderer);
                ASSERT(vkFormat != 0);
                ANGLE_TRY(renderer->getFormatDescriptorCountForVkFormat(context, vkFormat,
                                                                        &formatDescriptorCount));
            }

            ASSERT(formatDescriptorCount > 0);
            mImmutableSamplersMaxDescriptorCount =
                std::max(mImmutableSamplersMaxDescriptorCount, formatDescriptorCount);
        }
        else
        {
            const VkDescriptorType descType = samplerBinding.textureType == gl::TextureType::Buffer
                                                  ? VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER
                                                  : VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
            descOut->addBinding(info.binding, descType, arraySize, activeStages, nullptr);
        }
    }

    return angle::Result::Continue;
}

void ProgramExecutableVk::initializeWriteDescriptorDesc(vk::ErrorContext *context)
{
    const gl::ShaderBitSet &linkedShaderStages = mExecutable->getLinkedShaderStages();

    // Update mUniformBuffersWriteDescriptorDescs and its builder
    mUniformBuffersWriteDescriptorDescs.reset();
    mUniformBuffersWriteDescriptorDescs.updateShaderBuffers(
        mVariableInfoMap, mExecutable->getUniformBlocks(), getUniformBufferDescriptorType());
    mUniformBuffersWriteDescriptorDescs.updateDynamicDescriptorsCount();
    mUniformBuffersDescriptorDescBuilder.resize(
        mUniformBuffersWriteDescriptorDescs.getTotalDescriptorCount());

    // Update mShaderResourceWriteDescriptorDescs and its builder
    mShaderResourceWriteDescriptorDescs.reset();
    mShaderResourceWriteDescriptorDescs.updateShaderBuffers(
        mVariableInfoMap, mExecutable->getShaderStorageBlocks(), getStorageBufferDescriptorType());
    mShaderResourceWriteDescriptorDescs.updateAtomicCounters(
        mVariableInfoMap, mExecutable->getAtomicCounterBuffers());
    mShaderResourceWriteDescriptorDescs.updateImages(*mExecutable, mVariableInfoMap);

    mShaderResourceWriteDescriptorDescs.initInputAttachments(
        *mExecutable, mVariableInfoMap, context->getRenderer()->getMaxColorInputAttachmentCount());
    mShaderResourceDescriptorDescBuilder.resize(
        mShaderResourceWriteDescriptorDescs.getTotalDescriptorCount());

    mCurrentInputAttachmentsMask.reset();

    // Update mTextureWriteDescriptors and its builder
    mTextureWriteDescriptorDescs.reset();
    mTextureWriteDescriptorDescs.updateExecutableActiveTextures(mVariableInfoMap, *mExecutable);
    mTextureWriteDescriptorDescs.updateDynamicDescriptorsCount();
    mTextureDescriptorDescBuilder.resize(mTextureWriteDescriptorDescs.getTotalDescriptorCount());

    // Update mDefaultUniformAndXfbWriteDescriptorDescs and its builder
    mDefaultUniformAndXfbWriteDescriptorDescs.reset();
    mDefaultUniformAndXfbWriteDescriptorDescs.updateDefaultUniform(linkedShaderStages,
                                                                   mVariableInfoMap, *mExecutable);
    if (mExecutable->hasTransformFeedbackOutput() &&
        context->getFeatures().emulateTransformFeedback.enabled)
    {
        // Update mDefaultUniformAndXfbWriteDescriptorDescs for the emulation code path.
        if (linkedShaderStages[gl::ShaderType::Vertex])
        {
            mDefaultUniformAndXfbWriteDescriptorDescs.updateTransformFeedbackWrite(mVariableInfoMap,
                                                                                   *mExecutable);
        }
        mDefaultUniformAndXfbWriteDescriptorDescs.updateDynamicDescriptorsCount();
    }
    mDefaultUniformAndXfbDescriptorDescBuilder.resize(
        mDefaultUniformAndXfbWriteDescriptorDescs.getTotalDescriptorCount());
}

ProgramTransformOptions ProgramExecutableVk::getTransformOptions(
    ContextVk *contextVk,
    const vk::GraphicsPipelineDesc &desc)
{
    ProgramTransformOptions transformOptions = {};

    transformOptions.removeTransformFeedbackEmulation =
        contextVk->getFeatures().emulateTransformFeedback.enabled &&
        !contextVk->getState().isTransformFeedbackActiveUnpaused();
    FramebufferVk *drawFrameBuffer = vk::GetImpl(contextVk->getState().getDrawFramebuffer());
    const bool hasDepthStencilFramebufferFetch =
        mExecutable->usesDepthFramebufferFetch() || mExecutable->usesStencilFramebufferFetch();
    const bool hasFramebufferFetch =
        mExecutable->usesColorFramebufferFetch() || hasDepthStencilFramebufferFetch;
    const bool isMultisampled                    = drawFrameBuffer->getSamples() > 1;
    transformOptions.multiSampleFramebufferFetch = hasFramebufferFetch && isMultisampled;
    transformOptions.enableSampleShading =
        contextVk->getState().isSampleShadingEnabled() && isMultisampled;
    transformOptions.removeDepthInput =
        mExecutable->usesDepthFramebufferFetch() &&
        (drawFrameBuffer->getDepthStencilRenderTarget() == nullptr ||
         drawFrameBuffer->getDepthStencilRenderTarget()->getImageActualFormat().depthBits == 0);
    transformOptions.removeStencilInput =
        mExecutable->usesStencilFramebufferFetch() &&
        (drawFrameBuffer->getDepthStencilRenderTarget() == nullptr ||
         drawFrameBuffer->getDepthStencilRenderTarget()->getImageActualFormat().stencilBits == 0);

    transformOptions.ditherControl = static_cast<uint16_t>(desc.getEmulatedDitherControl());

    return transformOptions;
}

angle::Result ProgramExecutableVk::initGraphicsShaderPrograms(
    vk::ErrorContext *context,
    ProgramTransformOptions transformOptions)
{
    ASSERT(mExecutable->hasLinkedShaderStage(gl::ShaderType::Vertex));

    const uint32_t programIndex               = transformOptions.permutationIndex;
    ProgramInfo &programInfo                  = mGraphicsProgramInfos[programIndex];
    const gl::ShaderBitSet linkedShaderStages = mExecutable->getLinkedShaderStages();
    gl::ShaderType lastPreFragmentStage       = gl::GetLastPreFragmentStage(linkedShaderStages);

    const bool isTransformFeedbackProgram =
        !mExecutable->getLinkedTransformFeedbackVaryings().empty();

    for (gl::ShaderType shaderType : linkedShaderStages)
    {
        ANGLE_TRY(initGraphicsShaderProgram(context, shaderType, shaderType == lastPreFragmentStage,
                                            isTransformFeedbackProgram, transformOptions,
                                            &programInfo, mVariableInfoMap));
    }

    return angle::Result::Continue;
}

angle::Result ProgramExecutableVk::initProgramThenCreateGraphicsPipeline(
    vk::ErrorContext *context,
    ProgramTransformOptions transformOptions,
    vk::GraphicsPipelineSubset pipelineSubset,
    vk::PipelineCacheAccess *pipelineCache,
    PipelineSource source,
    const vk::GraphicsPipelineDesc &desc,
    const vk::RenderPass &compatibleRenderPass,
    const vk::GraphicsPipelineDesc **descPtrOut,
    vk::PipelineHelper **pipelineOut)
{
    ANGLE_TRY(initGraphicsShaderPrograms(context, transformOptions));

    const uint32_t programIndex = transformOptions.permutationIndex;
    return createGraphicsPipelineImpl(
        context, mGraphicsProgramInfos[programIndex], mCompleteGraphicsPipelines[programIndex],
        mShadersGraphicsPipelines[programIndex], pipelineSubset, pipelineCache, source, desc,
        compatibleRenderPass, descPtrOut, pipelineOut);
}

angle::Result ProgramExecutableVk::createGraphicsPipelineImpl(
    vk::ErrorContext *context,
    ProgramInfo &programInfo,
    CompleteGraphicsPipelineCache &completePipelines,
    ShadersGraphicsPipelineCache &shadersPipelines,
    vk::GraphicsPipelineSubset pipelineSubset,
    vk::PipelineCacheAccess *pipelineCache,
    PipelineSource source,
    const vk::GraphicsPipelineDesc &desc,
    const vk::RenderPass &compatibleRenderPass,
    const vk::GraphicsPipelineDesc **descPtrOut,
    vk::PipelineHelper **pipelineOut)
{
    // This method assumes that all the state necessary to create a graphics pipeline has already
    // been setup by the caller. Assert that all required state is valid so all that is left will
    // be the call to `vkCreateGraphicsPipelines`

    // Make sure the shader modules for all linked shader stages are valid.
    for (gl::ShaderType shaderType : mExecutable->getLinkedShaderStages())
    {
        ASSERT(programInfo.valid(shaderType));
    }

    // Choose appropriate pipeline cache based on pipeline subset
    if (pipelineSubset == vk::GraphicsPipelineSubset::Complete)
    {
        return programInfo.getShaderProgram().createGraphicsPipeline(
            context, &completePipelines, pipelineCache, compatibleRenderPass, getPipelineLayout(),
            source, desc, descPtrOut, pipelineOut);
    }
    else
    {
        // Vertex input and fragment output subsets are independent of shaders, and are not created
        // through the program executable.
        ASSERT(pipelineSubset == vk::GraphicsPipelineSubset::Shaders);

        return programInfo.getShaderProgram().createGraphicsPipeline(
            context, &shadersPipelines, pipelineCache, compatibleRenderPass, getPipelineLayout(),
            source, desc, descPtrOut, pipelineOut);
    }
}

angle::Result ProgramExecutableVk::getGraphicsPipeline(ContextVk *contextVk,
                                                       vk::GraphicsPipelineSubset pipelineSubset,
                                                       const vk::GraphicsPipelineDesc &desc,
                                                       const vk::GraphicsPipelineDesc **descPtrOut,
                                                       vk::PipelineHelper **pipelineOut)
{
    ProgramTransformOptions transformOptions = getTransformOptions(contextVk, desc);

    ANGLE_TRY(initGraphicsShaderPrograms(contextVk, transformOptions));

    const uint32_t programIndex = transformOptions.permutationIndex;

    *descPtrOut  = nullptr;
    *pipelineOut = nullptr;

    if (pipelineSubset == vk::GraphicsPipelineSubset::Complete)
    {
        mCompleteGraphicsPipelines[programIndex].getPipeline(desc, descPtrOut, pipelineOut);
    }
    else
    {
        // Vertex input and fragment output subsets are independent of shaders, and are not created
        // through the program executable.
        ASSERT(pipelineSubset == vk::GraphicsPipelineSubset::Shaders);

        mShadersGraphicsPipelines[programIndex].getPipeline(desc, descPtrOut, pipelineOut);
    }

    return angle::Result::Continue;
}

angle::Result ProgramExecutableVk::createGraphicsPipeline(
    ContextVk *contextVk,
    vk::GraphicsPipelineSubset pipelineSubset,
    vk::PipelineCacheAccess *pipelineCache,
    PipelineSource source,
    const vk::GraphicsPipelineDesc &desc,
    const vk::GraphicsPipelineDesc **descPtrOut,
    vk::PipelineHelper **pipelineOut)
{
    ProgramTransformOptions transformOptions = getTransformOptions(contextVk, desc);

    // When creating monolithic pipelines, the renderer's pipeline cache is used as passed in.
    // When creating the shaders subset of pipelines, the program's own pipeline cache is used,
    // unless the renderer's pipeline cache is preferred.
    vk::PipelineCacheAccess perProgramPipelineCache;
    const bool useProgramPipelineCache =
        !contextVk->getFeatures().preferGlobalPipelineCache.enabled &&
        pipelineSubset == vk::GraphicsPipelineSubset::Shaders;
    if (useProgramPipelineCache)
    {
        ANGLE_TRY(ensurePipelineCacheInitialized(contextVk));

        perProgramPipelineCache.init(&mPipelineCache, nullptr);
        pipelineCache = &perProgramPipelineCache;
    }

    // Pull in a compatible RenderPass.
    const vk::RenderPass *compatibleRenderPass = nullptr;
    ANGLE_TRY(contextVk->getCompatibleRenderPass(desc.getRenderPassDesc(), &compatibleRenderPass));

    ANGLE_TRY(initProgramThenCreateGraphicsPipeline(
        contextVk, transformOptions, pipelineSubset, pipelineCache, source, desc,
        *compatibleRenderPass, descPtrOut, pipelineOut));

    if (useProgramPipelineCache &&
        contextVk->getFeatures().mergeProgramPipelineCachesToGlobalCache.enabled)
    {
        ANGLE_TRY(contextVk->getRenderer()->mergeIntoPipelineCache(contextVk, mPipelineCache));
    }

    return angle::Result::Continue;
}

angle::Result ProgramExecutableVk::createLinkedGraphicsPipeline(
    ContextVk *contextVk,
    vk::PipelineCacheAccess *pipelineCache,
    const vk::GraphicsPipelineDesc &desc,
    vk::PipelineHelper *shadersPipeline,
    const vk::GraphicsPipelineDesc **descPtrOut,
    vk::PipelineHelper **pipelineOut)
{
    ProgramTransformOptions transformOptions = getTransformOptions(contextVk, desc);
    const uint32_t programIndex              = transformOptions.permutationIndex;

    // When linking libraries, use the program's own pipeline cache if monolithic pipelines are not
    // to be created, otherwise there is effectively a merge to global pipeline cache happening.
    vk::PipelineCacheAccess programPipelineCache;
    vk::PipelineCacheAccess *linkPipelineCache = pipelineCache;
    if (!contextVk->getFeatures().preferGlobalPipelineCache.enabled &&
        !contextVk->getFeatures().preferMonolithicPipelinesOverLibraries.enabled)
    {
        // No synchronization necessary since mPipelineCache is internally synchronized.
        programPipelineCache.init(&mPipelineCache, nullptr);
        linkPipelineCache = &programPipelineCache;
    }

    // Pull in a compatible RenderPass.
    const vk::RenderPass *compatibleRenderPass = nullptr;
    ANGLE_TRY(contextVk->getCompatibleRenderPass(desc.getRenderPassDesc(), &compatibleRenderPass));

    ANGLE_TRY(mCompleteGraphicsPipelines[programIndex].createPipeline(
        contextVk, linkPipelineCache, *compatibleRenderPass, getPipelineLayout(), {shadersPipeline},
        PipelineSource::DrawLinked, desc, descPtrOut, pipelineOut));

    // If monolithic pipelines are preferred over libraries, create a task so that it can be created
    // asynchronously.
    if (contextVk->getFeatures().preferMonolithicPipelinesOverLibraries.enabled)
    {
        mGraphicsProgramInfos[programIndex].getShaderProgram().createMonolithicPipelineCreationTask(
            contextVk, pipelineCache, desc, getPipelineLayout(), *pipelineOut);
    }

    return angle::Result::Continue;
}

angle::Result ProgramExecutableVk::getOrCreateComputePipeline(
    vk::ErrorContext *context,
    vk::PipelineCacheAccess *pipelineCache,
    PipelineSource source,
    vk::PipelineRobustness pipelineRobustness,
    vk::PipelineProtectedAccess pipelineProtectedAccess,
    vk::PipelineHelper **pipelineOut)
{
    ASSERT(mExecutable->hasLinkedShaderStage(gl::ShaderType::Compute));

    vk::ComputePipelineOptions pipelineOptions =
        vk::GetComputePipelineOptions(pipelineRobustness, pipelineProtectedAccess);
    ANGLE_TRY(initComputeProgram(context, &mComputeProgramInfo, mVariableInfoMap, pipelineOptions));

    return mComputeProgramInfo.getShaderProgram().getOrCreateComputePipeline(
        context, &mComputePipelines, pipelineCache, getPipelineLayout(), pipelineOptions, source,
        pipelineOut, nullptr, nullptr);
}

angle::Result ProgramExecutableVk::createPipelineLayout(
    vk::ErrorContext *context,
    PipelineLayoutCache *pipelineLayoutCache,
    DescriptorSetLayoutCache *descriptorSetLayoutCache,
    gl::ActiveTextureArray<TextureVk *> *activeTextures)
{
    vk::Renderer *renderer                     = context->getRenderer();
    const gl::ShaderBitSet &linkedShaderStages = mExecutable->getLinkedShaderStages();

    // Store a reference to the pipeline and descriptor set layouts. This will create them if they
    // don't already exist in the cache.

    // Default uniforms and transform feedback:
    mDefaultUniformAndXfbSetDesc          = {};
    uint32_t numDefaultUniformDescriptors = 0;
    for (gl::ShaderType shaderType : linkedShaderStages)
    {
        const ShaderInterfaceVariableInfo &info =
            mVariableInfoMap.getDefaultUniformInfo(shaderType);
        // Note that currently the default uniform block is added unconditionally.
        ASSERT(info.activeStages[shaderType]);

        mDefaultUniformAndXfbSetDesc.addBinding(info.binding,
                                                VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1,
                                                gl_vk::kShaderStageMap[shaderType], nullptr);
        numDefaultUniformDescriptors++;
    }

    gl::ShaderType linkedTransformFeedbackStage = mExecutable->getLinkedTransformFeedbackStage();
    bool hasXfbVaryings = linkedTransformFeedbackStage != gl::ShaderType::InvalidEnum &&
                          !mExecutable->getLinkedTransformFeedbackVaryings().empty();
    if (context->getFeatures().emulateTransformFeedback.enabled)
    {
        if (hasXfbVaryings)
        {
            size_t xfbBufferCount = mExecutable->getTransformFeedbackBufferCount();
            for (uint32_t bufferIndex = 0; bufferIndex < xfbBufferCount; ++bufferIndex)
            {
                const uint32_t binding = mVariableInfoMap.getEmulatedXfbBufferBinding(bufferIndex);
                ASSERT(binding != std::numeric_limits<uint32_t>::max());

                mDefaultUniformAndXfbSetDesc.addBinding(binding, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
                                                        1, VK_SHADER_STAGE_VERTEX_BIT, nullptr);
            }
        }
    }

    ANGLE_TRY(descriptorSetLayoutCache->getDescriptorSetLayout(
        context, mDefaultUniformAndXfbSetDesc,
        &mDescriptorSetLayouts[DescriptorSetIndex::UniformsAndXfb]));

    // Uniform buffers:
    mUniformBuffersSetDesc = {};

    // Count the number of active uniform buffer descriptors.
    uint32_t numActiveUniformBufferDescriptors    = 0;
    const std::vector<gl::InterfaceBlock> &blocks = mExecutable->getUniformBlocks();
    for (uint32_t bufferIndex = 0; bufferIndex < blocks.size();)
    {
        const gl::InterfaceBlock &block = blocks[bufferIndex];
        const uint32_t arraySize        = GetInterfaceBlockArraySize(blocks, bufferIndex);
        bufferIndex += arraySize;

        if (block.activeShaders().any())
        {
            numActiveUniformBufferDescriptors += arraySize;
        }
    }

    // Decide if we should use dynamic or fixed descriptor types.
    VkPhysicalDeviceLimits limits = renderer->getPhysicalDeviceProperties().limits;
    uint32_t totalDynamicUniformBufferCount =
        numActiveUniformBufferDescriptors + numDefaultUniformDescriptors;
    if (totalDynamicUniformBufferCount <= limits.maxDescriptorSetUniformBuffersDynamic)
    {
        mUniformBufferDescriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
    }
    else
    {
        mUniformBufferDescriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
    }

    addInterfaceBlockDescriptorSetDesc(mExecutable->getUniformBlocks(), linkedShaderStages,
                                       mUniformBufferDescriptorType, &mUniformBuffersSetDesc);

    ANGLE_TRY(descriptorSetLayoutCache->getDescriptorSetLayout(
        context, mUniformBuffersSetDesc,
        &mDescriptorSetLayouts[DescriptorSetIndex::UniformBuffers]));

    // Storage buffers, atomic counter buffers and images:
    mShaderResourceSetDesc = {};

    addInterfaceBlockDescriptorSetDesc(mExecutable->getShaderStorageBlocks(), linkedShaderStages,
                                       vk::kStorageBufferDescriptorType, &mShaderResourceSetDesc);
    addAtomicCounterBufferDescriptorSetDesc(mExecutable->getAtomicCounterBuffers(),
                                            &mShaderResourceSetDesc);
    addImageDescriptorSetDesc(&mShaderResourceSetDesc);
    addInputAttachmentDescriptorSetDesc(context, &mShaderResourceSetDesc);

    ANGLE_TRY(descriptorSetLayoutCache->getDescriptorSetLayout(
        context, mShaderResourceSetDesc,
        &mDescriptorSetLayouts[DescriptorSetIndex::ShaderResource]));

    // Textures:
    mTextureSetDesc = {};
    ANGLE_TRY(addTextureDescriptorSetDesc(context, activeTextures, &mTextureSetDesc));

    ANGLE_TRY(descriptorSetLayoutCache->getDescriptorSetLayout(
        context, mTextureSetDesc, &mDescriptorSetLayouts[DescriptorSetIndex::Texture]));

    // Create pipeline layout with these 4 descriptor sets.
    vk::PipelineLayoutDesc pipelineLayoutDesc;
    pipelineLayoutDesc.updateDescriptorSetLayout(DescriptorSetIndex::UniformsAndXfb,
                                                 mDefaultUniformAndXfbSetDesc);
    pipelineLayoutDesc.updateDescriptorSetLayout(DescriptorSetIndex::UniformBuffers,
                                                 mUniformBuffersSetDesc);
    pipelineLayoutDesc.updateDescriptorSetLayout(DescriptorSetIndex::ShaderResource,
                                                 mShaderResourceSetDesc);
    pipelineLayoutDesc.updateDescriptorSetLayout(DescriptorSetIndex::Texture, mTextureSetDesc);

    // Set up driver uniforms as push constants. The size is set for a graphics pipeline, as there
    // are more driver uniforms for a graphics pipeline than there are for a compute pipeline. As
    // for the shader stages, both graphics and compute stages are used.
    VkShaderStageFlags pushConstantShaderStageFlags = renderer->getSupportedVulkanShaderStageMask();
    uint32_t pushConstantSize = GraphicsDriverUniforms::GetMaxUniformDataSize(renderer);

    pipelineLayoutDesc.updatePushConstantRange(pushConstantShaderStageFlags, 0, pushConstantSize);

    ANGLE_TRY(pipelineLayoutCache->getPipelineLayout(context, pipelineLayoutDesc,
                                                     mDescriptorSetLayouts, &mPipelineLayout));

    mDefaultUniformDynamicDescriptorOffsets.clear();
    mDefaultUniformDynamicDescriptorOffsets.resize(mExecutable->getLinkedShaderStageCount(), 0);

    initializeWriteDescriptorDesc(context);

    return angle::Result::Continue;
}

angle::Result ProgramExecutableVk::initializeDescriptorPools(
    vk::ErrorContext *context,
    DescriptorSetLayoutCache *descriptorSetLayoutCache,
    vk::DescriptorSetArray<vk::MetaDescriptorPool> *metaDescriptorPools)
{
    ANGLE_TRY((*metaDescriptorPools)[DescriptorSetIndex::UniformsAndXfb].bindCachedDescriptorPool(
        context, mDefaultUniformAndXfbSetDesc, 1, descriptorSetLayoutCache,
        &mDynamicDescriptorPools[DescriptorSetIndex::UniformsAndXfb]));
    ANGLE_TRY((*metaDescriptorPools)[DescriptorSetIndex::Texture].bindCachedDescriptorPool(
        context, mTextureSetDesc, mImmutableSamplersMaxDescriptorCount, descriptorSetLayoutCache,
        &mDynamicDescriptorPools[DescriptorSetIndex::Texture]));
    ANGLE_TRY((*metaDescriptorPools)[DescriptorSetIndex::UniformBuffers].bindCachedDescriptorPool(
        context, mUniformBuffersSetDesc, 1, descriptorSetLayoutCache,
        &mDynamicDescriptorPools[DescriptorSetIndex::UniformBuffers]));
    return (*metaDescriptorPools)[DescriptorSetIndex::ShaderResource].bindCachedDescriptorPool(
        context, mShaderResourceSetDesc, 1, descriptorSetLayoutCache,
        &mDynamicDescriptorPools[DescriptorSetIndex::ShaderResource]);
}

void ProgramExecutableVk::resolvePrecisionMismatch(const gl::ProgramMergedVaryings &mergedVaryings)
{
    for (const gl::ProgramVaryingRef &mergedVarying : mergedVaryings)
    {
        if (!mergedVarying.frontShader || !mergedVarying.backShader)
        {
            continue;
        }

        if (!mergedVarying.frontShader->active || !mergedVarying.backShader->active)
        {
            continue;
        }

        GLenum frontPrecision = mergedVarying.frontShader->precision;
        GLenum backPrecision  = mergedVarying.backShader->precision;
        if (frontPrecision == backPrecision)
        {
            continue;
        }

        ASSERT(frontPrecision >= GL_LOW_FLOAT && frontPrecision <= GL_HIGH_INT);
        ASSERT(backPrecision >= GL_LOW_FLOAT && backPrecision <= GL_HIGH_INT);

        if (frontPrecision > backPrecision)
        {
            // The output is higher precision than the input.
            if (mergedVarying.frontShaderStage == gl::ShaderType::TessControl &&
                mergedVarying.frontShader->isArray())
            {
                // b/42266751
                // if the frontShader output belongs to TCS, and it is an array
                // do not adjust its' precision, as this would result reading output from other
                // invocations not working properly. Adjust the input precision instead.

                // For example, in below test case, TCS output is highp float, assume TES input is
                // lowp float, If we adjust TCS output precision, we will truncate the write result
                // to tc_out[1] to lowp, and get incorrect tc_out[1] > 10000000 comparison result.
                // #extension GL_OES_tessellation_shader : require
                // layout(vertices = 3) out;
                // in highp float tc_in[];
                // out highp float tc_out[];
                // void main()
                // {
                //     tc_out[gl_InvocationID] = tc_in[gl_InvocationID];
                //     barrier();
                //     if (gl_InvocationID == 0)
                //     {
                //         tc_out[gl_InvocationID] = tc_out[1] > 10000000 ? 1.0 : 0.0;
                //     }
                //     barrier();
                // }
                ShaderInterfaceVariableInfo &info = mVariableInfoMap.getMutable(
                    mergedVarying.backShaderStage, mergedVarying.backShader->id);
                info.varyingIsInput = true;
                SetBitField(info.useRelaxedPrecision, PrecisionAdjustmentEnum::kUpperPrecision);
            }
            else
            {
                ShaderInterfaceVariableInfo &info = mVariableInfoMap.getMutable(
                    mergedVarying.frontShaderStage, mergedVarying.frontShader->id);
                info.varyingIsOutput = true;
                SetBitField(info.useRelaxedPrecision, PrecisionAdjustmentEnum::kLowerPrecision);
            }
        }
        else
        {
            // The output is lower precision than the input, adjust the input
            ASSERT(backPrecision > frontPrecision);
            ShaderInterfaceVariableInfo &info = mVariableInfoMap.getMutable(
                mergedVarying.backShaderStage, mergedVarying.backShader->id);
            info.varyingIsInput      = true;
            SetBitField(info.useRelaxedPrecision, PrecisionAdjustmentEnum::kLowerPrecision);
        }
    }
}

angle::Result ProgramExecutableVk::getOrAllocateDescriptorSet(
    vk::Context *context,
    uint32_t currentFrame,
    UpdateDescriptorSetsBuilder *updateBuilder,
    const vk::DescriptorSetDescBuilder &descriptorSetDesc,
    const vk::WriteDescriptorDescs &writeDescriptorDescs,
    DescriptorSetIndex setIndex,
    vk::SharedDescriptorSetCacheKey *newSharedCacheKeyOut)
{
    vk::Renderer *renderer = context->getRenderer();

    if (renderer->getFeatures().descriptorSetCache.enabled)
    {
        ANGLE_TRY(mDynamicDescriptorPools[setIndex]->getOrAllocateDescriptorSet(
            context, currentFrame, descriptorSetDesc.getDesc(), *mDescriptorSetLayouts[setIndex],
            &mDescriptorSets[setIndex], newSharedCacheKeyOut));
        ASSERT(mDescriptorSets[setIndex]);

        if (*newSharedCacheKeyOut)
        {
            ASSERT((*newSharedCacheKeyOut)->valid());
            // Cache miss. A new cache entry has been created.
            updateBuilder->updateWriteDescriptorSet(renderer, descriptorSetDesc,
                                                    writeDescriptorDescs,
                                                    mDescriptorSets[setIndex]->getDescriptorSet());
        }
    }
    else
    {
        ANGLE_TRY(mDynamicDescriptorPools[setIndex]->allocateDescriptorSet(
            context, *mDescriptorSetLayouts[setIndex], &mDescriptorSets[setIndex]));
        ASSERT(mDescriptorSets[setIndex]);

        updateBuilder->updateWriteDescriptorSet(renderer, descriptorSetDesc, writeDescriptorDescs,
                                                mDescriptorSets[setIndex]->getDescriptorSet());
    }

    mValidDescriptorSetIndices.set(setIndex);
    return angle::Result::Continue;
}

angle::Result ProgramExecutableVk::updateBuffersDescriptorSet(
    vk::Context *context,
    const uint32_t currentFrame,
    const vk::DescriptorSetDescBuilder &descriptorSetDesc,
    const vk::WriteDescriptorDescs &writeDescriptorDescs,
    const DescriptorSetIndex setIndex,
    UpdateDescriptorSetsBuilder *updateBuilder,
    vk::SharedDescriptorSetCacheKey *newSharedCacheKeyOut)
{
    if (!mDynamicDescriptorPools[setIndex])
    {
        (*newSharedCacheKeyOut).reset();
        return angle::Result::Continue;
    }

    return getOrAllocateDescriptorSet(context, currentFrame, updateBuilder, descriptorSetDesc,
                                      writeDescriptorDescs, setIndex, newSharedCacheKeyOut);
}

angle::Result ProgramExecutableVk::updateUniformsAndXfbDescriptorSet(
    vk::Context *context,
    uint32_t currentFrame,
    UpdateDescriptorSetsBuilder *updateBuilder,
    const vk::BufferHelper *defaultUniformBuffer,
    vk::SharedDescriptorSetCacheKey *sharedCacheKeyOut)
{
    mCurrentDefaultUniformBufferSerial =
        defaultUniformBuffer ? defaultUniformBuffer->getBufferSerial() : vk::kInvalidBufferSerial;

    return getOrAllocateDescriptorSet(context, currentFrame, updateBuilder,
                                      mDefaultUniformAndXfbDescriptorDescBuilder,
                                      mDefaultUniformAndXfbWriteDescriptorDescs,
                                      DescriptorSetIndex::UniformsAndXfb, sharedCacheKeyOut);
}

angle::Result ProgramExecutableVk::updateTexturesDescriptorSet(
    vk::Context *context,
    uint32_t currentFrame,
    const gl::ActiveTextureArray<TextureVk *> &textures,
    const gl::SamplerBindingVector &samplers,
    PipelineType pipelineType,
    UpdateDescriptorSetsBuilder *updateBuilder)
{
    if (context->getFeatures().descriptorSetCache.enabled)
    {
        vk::SharedDescriptorSetCacheKey newSharedCacheKey;

        // We use textureSerial to optimize texture binding updates. Each permutation of a
        // {VkImage/VkSampler} generates a unique serial. These object ids are combined to form a
        // unique signature for each descriptor set. This allows us to keep a cache of descriptor
        // sets and avoid calling vkAllocateDesctiporSets each texture update.
        mTextureDescriptorDescBuilder.updatePreCacheActiveTextures(
            context, *mExecutable, textures, samplers, mTextureWriteDescriptorDescs);

        ANGLE_TRY(mDynamicDescriptorPools[DescriptorSetIndex::Texture]->getOrAllocateDescriptorSet(
            context, currentFrame, mTextureDescriptorDescBuilder.getDesc(),
            *mDescriptorSetLayouts[DescriptorSetIndex::Texture],
            &mDescriptorSets[DescriptorSetIndex::Texture], &newSharedCacheKey));
        ASSERT(mDescriptorSets[DescriptorSetIndex::Texture]);

        if (newSharedCacheKey)
        {
            ASSERT(newSharedCacheKey->valid());
            ANGLE_TRY(UpdateFullTexturesDescriptorSet(
                context, mVariableInfoMap, mTextureWriteDescriptorDescs, updateBuilder,
                *mExecutable, textures, samplers,
                mDescriptorSets[DescriptorSetIndex::Texture]->getDescriptorSet()));

            const gl::ActiveTextureMask &activeTextureMask = mExecutable->getActiveSamplersMask();
            for (size_t textureUnit : activeTextureMask)
            {
                ASSERT(textures[textureUnit] != nullptr);
                textures[textureUnit]->onNewDescriptorSet(newSharedCacheKey);
            }
        }
    }
    else
    {
        ANGLE_TRY(mDynamicDescriptorPools[DescriptorSetIndex::Texture]->allocateDescriptorSet(
            context, *mDescriptorSetLayouts[DescriptorSetIndex::Texture],
            &mDescriptorSets[DescriptorSetIndex::Texture]));
        ASSERT(mDescriptorSets[DescriptorSetIndex::Texture]);

        ANGLE_TRY(UpdateFullTexturesDescriptorSet(
            context, mVariableInfoMap, mTextureWriteDescriptorDescs, updateBuilder, *mExecutable,
            textures, samplers, mDescriptorSets[DescriptorSetIndex::Texture]->getDescriptorSet()));
    }

    mValidDescriptorSetIndices.set(DescriptorSetIndex::Texture);
    return angle::Result::Continue;
}

angle::Result ProgramExecutableVk::updateUniformsAndXfbDescInfo(
    vk::Context *context,
    const vk::BufferHelper *currentUniformBuffer,
    const vk::BufferHelper &emptyBuffer,
    uint32_t currentFrameCount,
    UpdateDescriptorSetsBuilder *updateBuilder,
    bool activeUnpaused,
    TransformFeedbackVk *transformFeedbackVk)
{
    mDefaultUniformAndXfbDescriptorDescBuilder.updateUniformsAndXfb(
        context, *getExecutable(), mDefaultUniformAndXfbWriteDescriptorDescs, currentUniformBuffer,
        emptyBuffer, activeUnpaused, transformFeedbackVk);

    vk::SharedDescriptorSetCacheKey newSharedCacheKey;
    ANGLE_TRY(updateUniformsAndXfbDescriptorSet(context, currentFrameCount, updateBuilder,
                                                currentUniformBuffer, &newSharedCacheKey));

    // If transform feedback is inactive or paused, updateUniformsAndXfb (via
    // updateTransformFeedbackDescriptorDesc) will bind emptyBuffer, so there is no need to register
    // the new descriptor set cache key with the actual transform feedback buffers.
    if (newSharedCacheKey && activeUnpaused)
    {
        transformFeedbackVk->onNewDescriptorSet(*getExecutable(), newSharedCacheKey);
    }

    return angle::Result::Continue;
}

angle::Result ProgramExecutableVk::updateUniformBuffersDescInfo(
    vk::Context *context,
    vk::CommandBufferHelperCommon *commandBufferHelper,
    const gl::BufferVector &bufferBindings,
    VkDeviceSize maxBoundBufferRange,
    const vk::BufferHelper &emptyBuffer,
    uint32_t currentFrameCount,
    UpdateDescriptorSetsBuilder *updateBuilder)
{
    const gl::ProgramExecutable *executable = getExecutable();
    for (size_t blockIndex : executable->getActiveUniformBufferBlocks())
    {
        const GLuint binding = executable->getUniformBlockBinding(blockIndex);
        mUniformBuffersDescriptorDescBuilder.updateOneUniformBuffer(
            context, commandBufferHelper, blockIndex, executable->getUniformBlocks()[blockIndex],
            bufferBindings[binding], getUniformBufferDescriptorType(), maxBoundBufferRange,
            emptyBuffer, mUniformBuffersWriteDescriptorDescs);
    }

    vk::SharedDescriptorSetCacheKey newSharedCacheKey;
    ANGLE_TRY(updateBuffersDescriptorSet(
        context, currentFrameCount, mUniformBuffersDescriptorDescBuilder,
        mUniformBuffersWriteDescriptorDescs, DescriptorSetIndex::UniformBuffers, updateBuilder,
        &newSharedCacheKey));

    if (newSharedCacheKey && !usesDynamicUniformBufferDescriptors())
    {
        // A new cache entry has been created. We record this cache key in the images and
        // buffers so that the descriptorSet cache can be destroyed when buffer/image is
        // destroyed.
        //
        // Dynamic descriptor type uses the underlying BufferBlock in the descriptorSet.
        // There could be many BufferHelper objects sub-allocated from the same BufferBlock. And
        // each BufferHelper could combine with other buffers to form a descriptorSet. This means
        // the descriptorSet numbers for BufferBlock could potentially very large, in thousands with
        // some app traces like seeing in honkai_star_rail. The overhead of maintaining
        // mDescriptorSetCacheManager for BufferBlock could be too big. We chose to not maintain
        // mDescriptorSetCacheManager in this case. The only downside is that when BufferBlock gets
        // destroyed, we will not able to immediately destroy all cached descriptorSets that it is
        // part of. They will still gets evicted later on if needed.
        for (size_t blockIndex : executable->getActiveUniformBufferBlocks())
        {
            const GLuint binding = executable->getUniformBlockBinding(blockIndex);
            const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding = bufferBindings[binding];
            UpdateBufferWithSharedCacheKey(bufferBinding, newSharedCacheKey);
        }
    }

    return angle::Result::Continue;
}

void ProgramExecutableVk::updateShaderResourcesWithSharedCacheKey(
    const gl::BufferVector &shaderStorageBufferBindings,
    const gl::BufferVector &atomicCounterBufferBindings,
    const gl::ActiveTextureArray<TextureVk *> &activeImages,
    const vk::SharedDescriptorSetCacheKey &newSharedCacheKey)
{
    const gl::ProgramExecutable *executable = getExecutable();
    ASSERT(!usesDynamicShaderStorageBufferDescriptors());
    ASSERT(!usesDynamicAtomicCounterBufferDescriptors());

    // Update shader storage buffers with new shared key
    for (size_t blockIndex : executable->getActiveStorageBufferBlocks())
    {
        const GLuint binding = executable->getShaderStorageBlockBinding(blockIndex);
        const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding =
            shaderStorageBufferBindings[binding];
        UpdateBufferWithSharedCacheKey(bufferBinding, newSharedCacheKey);
    }

    // Update atomic counter buffers with new shared key
    const std::vector<gl::AtomicCounterBuffer> &blocks = executable->getAtomicCounterBuffers();
    for (uint32_t blockIndex = 0; blockIndex < blocks.size(); ++blockIndex)
    {
        const GLuint binding = executable->getAtomicCounterBufferBinding(blockIndex);
        const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding =
            atomicCounterBufferBindings[binding];
        UpdateBufferWithSharedCacheKey(bufferBinding, newSharedCacheKey);
    }

    for (const gl::ImageBinding &imageBinding : executable->getImageBindings())
    {
        uint32_t arraySize = static_cast<uint32_t>(imageBinding.boundImageUnits.size());
        for (uint32_t arrayElement = 0; arrayElement < arraySize; ++arrayElement)
        {
            GLuint imageUnit = imageBinding.boundImageUnits[arrayElement];
            // For simplicity, we do not check if uniform is active or duplicate. The worst case is
            // we unnecessarily delete the cache entry when image bound to inactive uniform is
            // destroyed.
            TextureVk *textureVk = activeImages[imageUnit];
            if (!textureVk)
            {
                continue;
            }
            textureVk->onNewDescriptorSet(newSharedCacheKey);
        }
    }
}

angle::Result ProgramExecutableVk::updateShaderResourcesDescInfo(
    ContextVk *contextVk,
    vk::CommandBufferHelperCommon *commandBufferHelper,
    const FramebufferVk *framebufferVk,
    const gl::BufferVector &shaderStorageBufferBindings,
    const gl::BufferVector &atomicCounterBufferBindings,
    const VkPhysicalDeviceLimits &limits,
    const vk::BufferHelper &emptyBuffer,
    const GLbitfield memoryBarrierBits,
    const gl::ActiveTextureArray<TextureVk *> &activeImages,
    const std::vector<gl::ImageUnit> &imageUnits,
    uint32_t currentFrameCount,
    UpdateDescriptorSetsBuilder *updateBuilder)
{
    const gl::ProgramExecutable *executable = getExecutable();

    const bool hasImages               = executable->hasImages();
    const bool hasStorageBuffers       = executable->hasStorageBuffers();
    const bool hasAtomicCounterBuffers = executable->hasAtomicCounterBuffers();
    const bool hasFramebufferFetch     = executable->usesColorFramebufferFetch() ||
                                     executable->usesDepthFramebufferFetch() ||
                                     executable->usesStencilFramebufferFetch();

    if (!hasStorageBuffers && !hasAtomicCounterBuffers && !hasImages && !hasFramebufferFetch)
    {
        return angle::Result::Continue;
    }

    // Update input attachments first since it could change descriptor counts
    if (hasFramebufferFetch)
    {
        ANGLE_TRY(mShaderResourceDescriptorDescBuilder.updateInputAttachments(
            contextVk, *executable, mVariableInfoMap, framebufferVk,
            mShaderResourceWriteDescriptorDescs, &mCurrentInputAttachmentsMask));
    }

    if (hasStorageBuffers)
    {
        mShaderResourceDescriptorDescBuilder.updateStorageBuffers(
            contextVk, commandBufferHelper, *executable, shaderStorageBufferBindings,
            executable->getShaderStorageBlocks(), getStorageBufferDescriptorType(),
            limits.maxStorageBufferRange, emptyBuffer, mShaderResourceWriteDescriptorDescs,
            memoryBarrierBits);
    }

    if (hasAtomicCounterBuffers)
    {
        mShaderResourceDescriptorDescBuilder.updateAtomicCounters(
            contextVk, commandBufferHelper, *executable, mVariableInfoMap,
            atomicCounterBufferBindings, executable->getAtomicCounterBuffers(),
            limits.minStorageBufferOffsetAlignment, emptyBuffer,
            mShaderResourceWriteDescriptorDescs);
    }

    if (hasImages)
    {
        ANGLE_TRY(mShaderResourceDescriptorDescBuilder.updateImages(
            contextVk, *executable, mVariableInfoMap, activeImages, imageUnits,
            mShaderResourceWriteDescriptorDescs));
    }

    // Record usage of storage buffers and images in the command buffer to aid handling of
    // glMemoryBarrier.
    if (hasImages || hasStorageBuffers || hasAtomicCounterBuffers)
    {
        commandBufferHelper->setHasShaderStorageOutput();
    }

    vk::SharedDescriptorSetCacheKey newSharedCacheKey;
    ANGLE_TRY(updateBuffersDescriptorSet(
        contextVk, currentFrameCount, mShaderResourceDescriptorDescBuilder,
        mShaderResourceWriteDescriptorDescs, DescriptorSetIndex::ShaderResource, updateBuilder,
        &newSharedCacheKey));

    if (newSharedCacheKey)
    {
        // A new cache entry has been created. We record this cache key in the images and buffers so
        // that the descriptorSet cache can be destroyed when buffer/image is destroyed.
        updateShaderResourcesWithSharedCacheKey(shaderStorageBufferBindings,
                                                atomicCounterBufferBindings, activeImages,
                                                newSharedCacheKey);
    }

    return angle::Result::Continue;
}

template <typename CommandBufferT>
angle::Result ProgramExecutableVk::bindDescriptorSets(
    vk::ErrorContext *context,
    uint32_t currentFrame,
    vk::CommandBufferHelperCommon *commandBufferHelper,
    CommandBufferT *commandBuffer,
    PipelineType pipelineType)
{
    const VkPipelineBindPoint pipelineBindPoint = pipelineType == PipelineType::Compute
                                                      ? VK_PIPELINE_BIND_POINT_COMPUTE
                                                      : VK_PIPELINE_BIND_POINT_GRAPHICS;

    for (DescriptorSetIndex descriptorSetIndex : mValidDescriptorSetIndices)
    {
        ASSERT(mDescriptorSets[descriptorSetIndex]);
        VkDescriptorSet descSet = mDescriptorSets[descriptorSetIndex]->getDescriptorSet();
        ASSERT(descSet != VK_NULL_HANDLE);

        switch (descriptorSetIndex)
        {
            case DescriptorSetIndex::UniformsAndXfb:
                // Default uniforms are encompassed in a block per shader stage, and they are
                // assigned through dynamic uniform buffers (requiring dynamic offsets).
                commandBuffer->bindDescriptorSets(
                    getPipelineLayout(), pipelineBindPoint, descriptorSetIndex, 1, &descSet,
                    static_cast<uint32_t>(mDefaultUniformDynamicDescriptorOffsets.size()),
                    mDefaultUniformDynamicDescriptorOffsets.data());
                break;
            case DescriptorSetIndex::UniformBuffers:
                commandBuffer->bindDescriptorSets(
                    getPipelineLayout(), pipelineBindPoint, descriptorSetIndex, 1, &descSet,
                    static_cast<uint32_t>(
                        mUniformBuffersWriteDescriptorDescs.getDynamicDescriptorSetCount()),
                    mUniformBuffersDescriptorDescBuilder.getDynamicOffsets());
                break;
            case DescriptorSetIndex::ShaderResource:
                commandBuffer->bindDescriptorSets(getPipelineLayout(), pipelineBindPoint,
                                                  descriptorSetIndex, 1, &descSet, 0, nullptr);
                break;
            case DescriptorSetIndex::Texture:
                commandBuffer->bindDescriptorSets(getPipelineLayout(), pipelineBindPoint,
                                                  descriptorSetIndex, 1, &descSet, 0, nullptr);
                break;
            default:
                UNREACHABLE();
                break;
        }

        commandBufferHelper->retainResource(mDescriptorSets[descriptorSetIndex].get());
        mDescriptorSets[descriptorSetIndex]->updateLastUsedFrame(currentFrame);
    }

    return angle::Result::Continue;
}

template angle::Result ProgramExecutableVk::bindDescriptorSets<vk::priv::SecondaryCommandBuffer>(
    vk::ErrorContext *context,
    uint32_t currentFrame,
    vk::CommandBufferHelperCommon *commandBufferHelper,
    vk::priv::SecondaryCommandBuffer *commandBuffer,
    PipelineType pipelineType);
template angle::Result ProgramExecutableVk::bindDescriptorSets<vk::VulkanSecondaryCommandBuffer>(
    vk::ErrorContext *context,
    uint32_t currentFrame,
    vk::CommandBufferHelperCommon *commandBufferHelper,
    vk::VulkanSecondaryCommandBuffer *commandBuffer,
    PipelineType pipelineType);

void ProgramExecutableVk::setAllDefaultUniformsDirty()
{
    mDefaultUniformBlocksDirty.reset();
    for (gl::ShaderType shaderType : mExecutable->getLinkedShaderStages())
    {
        if (!mDefaultUniformBlocks[shaderType]->uniformData.empty())
        {
            mDefaultUniformBlocksDirty.set(shaderType);
        }
    }
}

angle::Result ProgramExecutableVk::updateUniforms(vk::Context *context,
                                                  uint32_t currentFrame,
                                                  UpdateDescriptorSetsBuilder *updateBuilder,
                                                  vk::BufferHelper *emptyBuffer,
                                                  vk::DynamicBuffer *defaultUniformStorage,
                                                  bool isTransformFeedbackActiveUnpaused,
                                                  TransformFeedbackVk *transformFeedbackVk)
{
    ASSERT(mDefaultUniformBlocksDirty.any());

    vk::BufferHelper *defaultUniformBuffer;
    bool anyNewBufferAllocated          = false;
    gl::ShaderMap<VkDeviceSize> offsets = {};  // offset to the beginning of bufferData
    uint32_t offsetIndex                = 0;
    size_t requiredSpace;

    // We usually only update uniform data for shader stages that are actually dirty. But when the
    // buffer for uniform data have switched, because all shader stages are using the same buffer,
    // we then must update uniform data for all shader stages to keep all shader stages' uniform
    // data in the same buffer.
    requiredSpace = calcUniformUpdateRequiredSpace(context, &offsets);
    ASSERT(requiredSpace > 0);

    // Allocate space from dynamicBuffer. Always try to allocate from the current buffer first.
    // If that failed, we deal with fall out and try again.
    if (!defaultUniformStorage->allocateFromCurrentBuffer(requiredSpace, &defaultUniformBuffer))
    {
        setAllDefaultUniformsDirty();

        requiredSpace = calcUniformUpdateRequiredSpace(context, &offsets);
        ANGLE_TRY(defaultUniformStorage->allocate(context, requiredSpace, &defaultUniformBuffer,
                                                  &anyNewBufferAllocated));
    }

    ASSERT(defaultUniformBuffer);

    uint8_t *bufferData       = defaultUniformBuffer->getMappedMemory();
    VkDeviceSize bufferOffset = defaultUniformBuffer->getOffset();
    for (gl::ShaderType shaderType : mExecutable->getLinkedShaderStages())
    {
        if (mDefaultUniformBlocksDirty[shaderType])
        {
            const angle::MemoryBuffer &uniformData = mDefaultUniformBlocks[shaderType]->uniformData;
            ANGLE_UNSAFE_TODO(
                memcpy(&bufferData[offsets[shaderType]], uniformData.data(), uniformData.size()));
            mDefaultUniformDynamicDescriptorOffsets[offsetIndex] =
                static_cast<uint32_t>(bufferOffset + offsets[shaderType]);
            mDefaultUniformBlocksDirty.reset(shaderType);
        }
        ++offsetIndex;
    }
    ANGLE_TRY(defaultUniformBuffer->flush(context->getRenderer()));

    // Because the uniform buffers are per context, we can't rely on dynamicBuffer's allocate
    // function to tell us if you have got a new buffer or not. Other program's use of the buffer
    // might already pushed dynamicBuffer to a new buffer. We record which buffer (represented by
    // the unique BufferSerial number) we were using with the current descriptor set and then we
    // use that recorded BufferSerial compare to the current uniform buffer to quickly detect if
    // there is a buffer switch or not. We need to retrieve from the descriptor set cache or
    // allocate a new descriptor set whenever there is uniform buffer switch.
    if (mCurrentDefaultUniformBufferSerial != defaultUniformBuffer->getBufferSerial())
    {
        // We need to reinitialize the descriptor sets if we newly allocated buffers since we can't
        // modify the descriptor sets once initialized.
        mDefaultUniformAndXfbDescriptorDescBuilder.updateUniformsAndXfb(
            context, *mExecutable, mDefaultUniformAndXfbWriteDescriptorDescs, defaultUniformBuffer,
            *emptyBuffer, isTransformFeedbackActiveUnpaused,
            mExecutable->hasTransformFeedbackOutput() ? transformFeedbackVk : nullptr);

        vk::SharedDescriptorSetCacheKey newSharedCacheKey;
        ANGLE_TRY(updateUniformsAndXfbDescriptorSet(context, currentFrame, updateBuilder,
                                                    defaultUniformBuffer, &newSharedCacheKey));
        // If transform feedback is inactive or paused, updateUniformsAndXfb (via
        // updateTransformFeedbackDescriptorDesc) will bind emptyBuffer, so there is no need to
        // register the new descriptor set cache key with the actual transform feedback buffers.
        if (newSharedCacheKey)
        {
            if (mExecutable->hasTransformFeedbackOutput() &&
                context->getFeatures().emulateTransformFeedback.enabled &&
                isTransformFeedbackActiveUnpaused)
            {
                transformFeedbackVk->onNewDescriptorSet(*mExecutable, newSharedCacheKey);
            }
        }
    }

    return angle::Result::Continue;
}

size_t ProgramExecutableVk::calcUniformUpdateRequiredSpace(
    vk::ErrorContext *context,
    gl::ShaderMap<VkDeviceSize> *uniformOffsets) const
{
    size_t requiredSpace = 0;
    for (gl::ShaderType shaderType : mExecutable->getLinkedShaderStages())
    {
        if (mDefaultUniformBlocksDirty[shaderType])
        {
            (*uniformOffsets)[shaderType] = requiredSpace;
            requiredSpace += getDefaultUniformAlignedSize(context, shaderType);
        }
    }
    return requiredSpace;
}

void ProgramExecutableVk::onProgramBind()
{
    // Because all programs share default uniform buffers, when we switch programs, we have to
    // re-update all uniform data. We could do more tracking to avoid update if the context's
    // current uniform buffer is still the same buffer we last time used and buffer has not been
    // recycled. But statistics gathered on gfxbench shows that app always update uniform data on
    // program bind anyway, so not really worth it to add more tracking logic here.
    //
    // Note: if this is changed, PPO uniform checks need to be updated as well
    setAllDefaultUniformsDirty();
}

angle::Result ProgramExecutableVk::resizeUniformBlockMemory(
    vk::ErrorContext *context,
    const gl::ShaderMap<size_t> &requiredBufferSize)
{
    for (gl::ShaderType shaderType : mExecutable->getLinkedShaderStages())
    {
        if (requiredBufferSize[shaderType] > 0)
        {
            if (!mDefaultUniformBlocks[shaderType]->uniformData.resize(
                    requiredBufferSize[shaderType]))
            {
                ANGLE_VK_CHECK(context, false, VK_ERROR_OUT_OF_HOST_MEMORY);
            }

            // Initialize uniform buffer memory to zero by default.
            mDefaultUniformBlocks[shaderType]->uniformData.fill(0);
            mDefaultUniformBlocksDirty.set(shaderType);
        }
    }

    return angle::Result::Continue;
}

void ProgramExecutableVk::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
{
    SetUniform(mExecutable, location, count, v, GL_FLOAT, &mDefaultUniformBlocks,
               &mDefaultUniformBlocksDirty);
}

void ProgramExecutableVk::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
{
    SetUniform(mExecutable, location, count, v, GL_FLOAT_VEC2, &mDefaultUniformBlocks,
               &mDefaultUniformBlocksDirty);
}

void ProgramExecutableVk::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
{
    SetUniform(mExecutable, location, count, v, GL_FLOAT_VEC3, &mDefaultUniformBlocks,
               &mDefaultUniformBlocksDirty);
}

void ProgramExecutableVk::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
{
    SetUniform(mExecutable, location, count, v, GL_FLOAT_VEC4, &mDefaultUniformBlocks,
               &mDefaultUniformBlocksDirty);
}

void ProgramExecutableVk::setUniform1iv(GLint location, GLsizei count, const GLint *v)
{
    const gl::VariableLocation &locationInfo = mExecutable->getUniformLocations()[location];
    const gl::LinkedUniform &linkedUniform   = mExecutable->getUniforms()[locationInfo.index];
    if (linkedUniform.isSampler())
    {
        // We could potentially cache some indexing here. For now this is a no-op since the mapping
        // is handled entirely in ContextVk.
        return;
    }

    SetUniform(mExecutable, location, count, v, GL_INT, &mDefaultUniformBlocks,
               &mDefaultUniformBlocksDirty);
}

void ProgramExecutableVk::setUniform2iv(GLint location, GLsizei count, const GLint *v)
{
    SetUniform(mExecutable, location, count, v, GL_INT_VEC2, &mDefaultUniformBlocks,
               &mDefaultUniformBlocksDirty);
}

void ProgramExecutableVk::setUniform3iv(GLint location, GLsizei count, const GLint *v)
{
    SetUniform(mExecutable, location, count, v, GL_INT_VEC3, &mDefaultUniformBlocks,
               &mDefaultUniformBlocksDirty);
}

void ProgramExecutableVk::setUniform4iv(GLint location, GLsizei count, const GLint *v)
{
    SetUniform(mExecutable, location, count, v, GL_INT_VEC4, &mDefaultUniformBlocks,
               &mDefaultUniformBlocksDirty);
}

void ProgramExecutableVk::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
{
    SetUniform(mExecutable, location, count, v, GL_UNSIGNED_INT, &mDefaultUniformBlocks,
               &mDefaultUniformBlocksDirty);
}

void ProgramExecutableVk::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
{
    SetUniform(mExecutable, location, count, v, GL_UNSIGNED_INT_VEC2, &mDefaultUniformBlocks,
               &mDefaultUniformBlocksDirty);
}

void ProgramExecutableVk::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
{
    SetUniform(mExecutable, location, count, v, GL_UNSIGNED_INT_VEC3, &mDefaultUniformBlocks,
               &mDefaultUniformBlocksDirty);
}

void ProgramExecutableVk::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
{
    SetUniform(mExecutable, location, count, v, GL_UNSIGNED_INT_VEC4, &mDefaultUniformBlocks,
               &mDefaultUniformBlocksDirty);
}

void ProgramExecutableVk::setUniformMatrix2fv(GLint location,
                                              GLsizei count,
                                              GLboolean transpose,
                                              const GLfloat *value)
{
    SetUniformMatrixfv<2, 2>(mExecutable, location, count, transpose, value, &mDefaultUniformBlocks,
                             &mDefaultUniformBlocksDirty);
}

void ProgramExecutableVk::setUniformMatrix3fv(GLint location,
                                              GLsizei count,
                                              GLboolean transpose,
                                              const GLfloat *value)
{
    SetUniformMatrixfv<3, 3>(mExecutable, location, count, transpose, value, &mDefaultUniformBlocks,
                             &mDefaultUniformBlocksDirty);
}

void ProgramExecutableVk::setUniformMatrix4fv(GLint location,
                                              GLsizei count,
                                              GLboolean transpose,
                                              const GLfloat *value)
{
    SetUniformMatrixfv<4, 4>(mExecutable, location, count, transpose, value, &mDefaultUniformBlocks,
                             &mDefaultUniformBlocksDirty);
}

void ProgramExecutableVk::setUniformMatrix2x3fv(GLint location,
                                                GLsizei count,
                                                GLboolean transpose,
                                                const GLfloat *value)
{
    SetUniformMatrixfv<2, 3>(mExecutable, location, count, transpose, value, &mDefaultUniformBlocks,
                             &mDefaultUniformBlocksDirty);
}

void ProgramExecutableVk::setUniformMatrix3x2fv(GLint location,
                                                GLsizei count,
                                                GLboolean transpose,
                                                const GLfloat *value)
{
    SetUniformMatrixfv<3, 2>(mExecutable, location, count, transpose, value, &mDefaultUniformBlocks,
                             &mDefaultUniformBlocksDirty);
}

void ProgramExecutableVk::setUniformMatrix2x4fv(GLint location,
                                                GLsizei count,
                                                GLboolean transpose,
                                                const GLfloat *value)
{
    SetUniformMatrixfv<2, 4>(mExecutable, location, count, transpose, value, &mDefaultUniformBlocks,
                             &mDefaultUniformBlocksDirty);
}

void ProgramExecutableVk::setUniformMatrix4x2fv(GLint location,
                                                GLsizei count,
                                                GLboolean transpose,
                                                const GLfloat *value)
{
    SetUniformMatrixfv<4, 2>(mExecutable, location, count, transpose, value, &mDefaultUniformBlocks,
                             &mDefaultUniformBlocksDirty);
}

void ProgramExecutableVk::setUniformMatrix3x4fv(GLint location,
                                                GLsizei count,
                                                GLboolean transpose,
                                                const GLfloat *value)
{
    SetUniformMatrixfv<3, 4>(mExecutable, location, count, transpose, value, &mDefaultUniformBlocks,
                             &mDefaultUniformBlocksDirty);
}

void ProgramExecutableVk::setUniformMatrix4x3fv(GLint location,
                                                GLsizei count,
                                                GLboolean transpose,
                                                const GLfloat *value)
{
    SetUniformMatrixfv<4, 3>(mExecutable, location, count, transpose, value, &mDefaultUniformBlocks,
                             &mDefaultUniformBlocksDirty);
}

void ProgramExecutableVk::getUniformfv(const gl::Context *context,
                                       GLint location,
                                       GLfloat *params) const
{
    GetUniform(mExecutable, location, params, GL_FLOAT, &mDefaultUniformBlocks);
}

void ProgramExecutableVk::getUniformiv(const gl::Context *context,
                                       GLint location,
                                       GLint *params) const
{
    GetUniform(mExecutable, location, params, GL_INT, &mDefaultUniformBlocks);
}

void ProgramExecutableVk::getUniformuiv(const gl::Context *context,
                                        GLint location,
                                        GLuint *params) const
{
    GetUniform(mExecutable, location, params, GL_UNSIGNED_INT, &mDefaultUniformBlocks);
}
}  // namespace rx
