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

#ifdef UNSAFE_BUFFERS_BUILD
#    pragma allow_unsafe_buffers
#endif

#include "libANGLE/renderer/vulkan/ProgramExecutableVk.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::SpecializationConstants MakeSpecConsts(ProgramTransformOptions transformOptions,
                                           const vk::GraphicsPipelineDesc &desc)
{
    vk::SpecializationConstants specConsts;
    specConsts.dither          = desc.getEmulatedDitherControl();
    return specConsts;
}

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 = 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 = 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 *>(
                    &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;
    }

  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,
                       SharedRenderPass *compatibleRenderPass,
                       vk::PipelineHelper *placeholderPipelineHelper)
        : WarmUpTaskCommon(renderer, executableVk, pipelineRobustness, pipelineProtectedAccess),
          mPipelineSubset(subset),
          mGraphicsPipelineDesc(graphicsPipelineDesc),
          mWarmUpPipelineHelper(placeholderPipelineHelper),
          mCompatibleRenderPass(compatibleRenderPass)
    {
        ASSERT(mCompatibleRenderPass);
        mCompatibleRenderPass->addRef();
    }
    ~WarmUpGraphicsTask() override = default;

    void operator()() override
    {
        angle::Result result = mExecutableVk->warmUpGraphicsPipelineCache(
            this, mPipelineRobustness, mPipelineProtectedAccess, mPipelineSubset,
            mGraphicsPipelineDesc, 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);
        }
    }

  private:
    vk::GraphicsPipelineSubset mPipelineSubset;
    vk::GraphicsPipelineDesc mGraphicsPipelineDesc;
    vk::PipelineHelper *mWarmUpPipelineHelper;

    // 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.removeDepthStencilInput =
        optionBits.removeDepthStencilInput && shaderType == gl::ShaderType::Fragment;

    options.useSpirvVaryingPrecisionFixer =
        context->getFeatures().varyingsRequireMatchingPrecisionInSpirv.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{},
      mValidGraphicsPermutations{},
      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(mValidGraphicsPermutations.none());
        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 (size_t index : mValidGraphicsPermutations)
    {
        mCompleteGraphicsPipelines[index].release(contextVk);
        mShadersGraphicsPipelines[index].release(contextVk);

        // Program infos and pipeline layout must be released after pipelines are; they might be
        // having pending jobs that are referencing them.
        mGraphicsProgramInfos[index].release(contextVk);
    }
    mValidGraphicsPermutations.reset();

    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.data(), compressedPipelineDataSize);
            // 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.data(), cacheData.size());
        }
    }
}

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 uint8_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, 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::TriangleStrip;
    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,
    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;
    ProgramTransformOptions transformOptions = {};

    ANGLE_TRY(createGraphicsPipelineImpl(context, transformOptions, 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");
        }
    }

    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);
    mShaderResourceDescriptorDescBuilder.resize(
        mShaderResourceWriteDescriptorDescs.getTotalDescriptorCount());

    // 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.removeDepthStencilInput =
        hasDepthStencilFramebufferFetch &&
        drawFrameBuffer->getDepthStencilRenderTarget() == nullptr;

    return transformOptions;
}

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

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

    return createGraphicsPipelineImpl(context, transformOptions, pipelineSubset, pipelineCache,
                                      source, desc, compatibleRenderPass, descPtrOut, pipelineOut);
}

angle::Result ProgramExecutableVk::createGraphicsPipelineImpl(
    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)
{
    // 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 program index is within range
    const uint8_t programIndex = transformOptions.permutationIndex;
    ASSERT(programIndex >= 0 && programIndex < ProgramTransformOptions::kPermutationCount);

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

    // Generate spec consts, a change in which results in a new pipeline.
    vk::SpecializationConstants specConsts = MakeSpecConsts(transformOptions, desc);

    // Choose appropriate pipeline cache based on pipeline subset
    if (pipelineSubset == vk::GraphicsPipelineSubset::Complete)
    {
        CompleteGraphicsPipelineCache &pipelines = mCompleteGraphicsPipelines[programIndex];
        return programInfo.getShaderProgram().createGraphicsPipeline(
            context, &pipelines, pipelineCache, compatibleRenderPass, getPipelineLayout(), source,
            desc, specConsts, 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);

        ShadersGraphicsPipelineCache &pipelines = mShadersGraphicsPipelines[programIndex];
        return programInfo.getShaderProgram().createGraphicsPipeline(
            context, &pipelines, pipelineCache, compatibleRenderPass, getPipelineLayout(), source,
            desc, specConsts, 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 uint8_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 uint8_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)
    {
        vk::SpecializationConstants specConsts = MakeSpecConsts(transformOptions, desc);

        mGraphicsProgramInfos[programIndex].getShaderProgram().createMonolithicPipelineCreationTask(
            contextVk, pipelineCache, desc, getPipelineLayout(), specConsts, *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)
{
    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 && 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 = context->getRenderer()->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 =
        context->getRenderer()->getSupportedVulkanShaderStageMask();

    uint32_t pushConstantSize = GetDriverUniformSize(context, PipelineType::Graphics);
    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 (newSharedCacheKey)
    {
        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.
            activeImages[imageUnit]->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)
    {
        // Update writeDescriptorDescs with inputAttachments
        mShaderResourceWriteDescriptorDescs.updateInputAttachments(*executable, mVariableInfoMap,
                                                                   framebufferVk);

        // Total descriptor count could have changed, resize DescriptorSetDescBuilder
        mShaderResourceDescriptorDescBuilder.resize(
            mShaderResourceWriteDescriptorDescs.getTotalDescriptorCount());

        // Update DescriptorSetDescBuilder with inputAttachments
        ANGLE_TRY(mShaderResourceDescriptorDescBuilder.updateInputAttachments(
            contextVk, *executable, mVariableInfoMap, framebufferVk,
            mShaderResourceWriteDescriptorDescs));
    }

    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;
            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 (newSharedCacheKey)
        {
            if (mExecutable->hasTransformFeedbackOutput() &&
                context->getFeatures().emulateTransformFeedback.enabled)
            {
                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
