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

#ifndef LIBANGLE_RENDERER_VULKAN_PROGRAMEXECUTABLEVK_H_
#define LIBANGLE_RENDERER_VULKAN_PROGRAMEXECUTABLEVK_H_

#include "common/bitset_utils.h"
#include "common/mathutil.h"
#include "common/utilities.h"
#include "libANGLE/Context.h"
#include "libANGLE/InfoLog.h"
#include "libANGLE/ProgramExecutable.h"
#include "libANGLE/renderer/ProgramExecutableImpl.h"
#include "libANGLE/renderer/vulkan/ContextVk.h"
#include "libANGLE/renderer/vulkan/ShaderInterfaceVariableInfoMap.h"
#include "libANGLE/renderer/vulkan/spv_utils.h"
#include "libANGLE/renderer/vulkan/vk_cache_utils.h"
#include "libANGLE/renderer/vulkan/vk_helpers.h"

namespace rx
{

class ShaderInfo final : angle::NonCopyable
{
  public:
    ShaderInfo();
    ~ShaderInfo();

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

    ANGLE_INLINE bool valid() const { return mIsInitialized; }

    const gl::ShaderMap<angle::spirv::Blob> &getSpirvBlobs() const { return mSpirvBlobs; }

    // Save and load implementation for GLES Program Binary support.
    void load(gl::BinaryInputStream *stream);
    void save(gl::BinaryOutputStream *stream);

  private:
    gl::ShaderMap<angle::spirv::Blob> mSpirvBlobs;
    bool mIsInitialized = false;
};

union ProgramTransformOptions final
{
    struct
    {
        uint8_t removeTransformFeedbackEmulation : 1;
        uint8_t multiSampleFramebufferFetch : 1;
        uint8_t enableSampleShading : 1;
        uint8_t removeDepthStencilInput : 1;
        uint8_t reserved : 4;  // must initialize to zero
    };
    uint8_t permutationIndex;
    static constexpr uint32_t kPermutationCount = 0x1 << 4;
};
static_assert(sizeof(ProgramTransformOptions) == 1, "Size check failed");
static_assert(static_cast<int>(SurfaceRotation::EnumCount) <= 8, "Size check failed");

class ProgramInfo final : angle::NonCopyable
{
  public:
    ProgramInfo();
    ~ProgramInfo();

    angle::Result initProgram(vk::ErrorContext *context,
                              gl::ShaderType shaderType,
                              bool isLastPreFragmentStage,
                              bool isTransformFeedbackProgram,
                              const ShaderInfo &shaderInfo,
                              ProgramTransformOptions optionBits,
                              const ShaderInterfaceVariableInfoMap &variableInfoMap);
    void release(ContextVk *contextVk);

    ANGLE_INLINE bool valid(gl::ShaderType shaderType) const
    {
        return mProgramHelper.valid(shaderType);
    }

    vk::ShaderProgramHelper &getShaderProgram() { return mProgramHelper; }

  private:
    vk::ShaderProgramHelper mProgramHelper;
    vk::ShaderModuleMap mShaders;
};

using ImmutableSamplerIndexMap = angle::HashMap<vk::YcbcrConversionDesc, uint32_t>;

class ProgramExecutableVk : public ProgramExecutableImpl
{
  public:
    ProgramExecutableVk(const gl::ProgramExecutable *executable);
    ~ProgramExecutableVk() override;

    void destroy(const gl::Context *context) override;

    void save(ContextVk *contextVk, bool isSeparable, gl::BinaryOutputStream *stream);
    angle::Result load(ContextVk *contextVk,
                       bool isSeparable,
                       gl::BinaryInputStream *stream,
                       egl::CacheGetResult *resultOut);

    void setUniform1fv(GLint location, GLsizei count, const GLfloat *v) override;
    void setUniform2fv(GLint location, GLsizei count, const GLfloat *v) override;
    void setUniform3fv(GLint location, GLsizei count, const GLfloat *v) override;
    void setUniform4fv(GLint location, GLsizei count, const GLfloat *v) override;
    void setUniform1iv(GLint location, GLsizei count, const GLint *v) override;
    void setUniform2iv(GLint location, GLsizei count, const GLint *v) override;
    void setUniform3iv(GLint location, GLsizei count, const GLint *v) override;
    void setUniform4iv(GLint location, GLsizei count, const GLint *v) override;
    void setUniform1uiv(GLint location, GLsizei count, const GLuint *v) override;
    void setUniform2uiv(GLint location, GLsizei count, const GLuint *v) override;
    void setUniform3uiv(GLint location, GLsizei count, const GLuint *v) override;
    void setUniform4uiv(GLint location, GLsizei count, const GLuint *v) override;
    void setUniformMatrix2fv(GLint location,
                             GLsizei count,
                             GLboolean transpose,
                             const GLfloat *value) override;
    void setUniformMatrix3fv(GLint location,
                             GLsizei count,
                             GLboolean transpose,
                             const GLfloat *value) override;
    void setUniformMatrix4fv(GLint location,
                             GLsizei count,
                             GLboolean transpose,
                             const GLfloat *value) override;
    void setUniformMatrix2x3fv(GLint location,
                               GLsizei count,
                               GLboolean transpose,
                               const GLfloat *value) override;
    void setUniformMatrix3x2fv(GLint location,
                               GLsizei count,
                               GLboolean transpose,
                               const GLfloat *value) override;
    void setUniformMatrix2x4fv(GLint location,
                               GLsizei count,
                               GLboolean transpose,
                               const GLfloat *value) override;
    void setUniformMatrix4x2fv(GLint location,
                               GLsizei count,
                               GLboolean transpose,
                               const GLfloat *value) override;
    void setUniformMatrix3x4fv(GLint location,
                               GLsizei count,
                               GLboolean transpose,
                               const GLfloat *value) override;
    void setUniformMatrix4x3fv(GLint location,
                               GLsizei count,
                               GLboolean transpose,
                               const GLfloat *value) override;

    void getUniformfv(const gl::Context *context, GLint location, GLfloat *params) const override;
    void getUniformiv(const gl::Context *context, GLint location, GLint *params) const override;
    void getUniformuiv(const gl::Context *context, GLint location, GLuint *params) const override;

    void clearVariableInfoMap();

    vk::BufferSerial getCurrentDefaultUniformBufferSerial() const
    {
        return mCurrentDefaultUniformBufferSerial;
    }

    // Get the graphics pipeline if already created.
    angle::Result getGraphicsPipeline(ContextVk *contextVk,
                                      vk::GraphicsPipelineSubset pipelineSubset,
                                      const vk::GraphicsPipelineDesc &desc,
                                      const vk::GraphicsPipelineDesc **descPtrOut,
                                      vk::PipelineHelper **pipelineOut);

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

    angle::Result createLinkedGraphicsPipeline(ContextVk *contextVk,
                                               vk::PipelineCacheAccess *pipelineCache,
                                               const vk::GraphicsPipelineDesc &desc,
                                               vk::PipelineHelper *shadersPipeline,
                                               const vk::GraphicsPipelineDesc **descPtrOut,
                                               vk::PipelineHelper **pipelineOut);

    angle::Result getOrCreateComputePipeline(vk::ErrorContext *context,
                                             vk::PipelineCacheAccess *pipelineCache,
                                             PipelineSource source,
                                             vk::PipelineRobustness pipelineRobustness,
                                             vk::PipelineProtectedAccess pipelineProtectedAccess,
                                             vk::PipelineHelper **pipelineOut);

    const vk::PipelineLayout &getPipelineLayout() const { return *mPipelineLayout; }
    void resetLayout(ContextVk *contextVk);
    angle::Result createPipelineLayout(vk::ErrorContext *context,
                                       PipelineLayoutCache *pipelineLayoutCache,
                                       DescriptorSetLayoutCache *descriptorSetLayoutCache,
                                       gl::ActiveTextureArray<TextureVk *> *activeTextures);
    angle::Result initializeDescriptorPools(
        vk::ErrorContext *context,
        DescriptorSetLayoutCache *descriptorSetLayoutCache,
        vk::DescriptorSetArray<vk::MetaDescriptorPool> *metaDescriptorPools);

    angle::Result updateTexturesDescriptorSet(vk::Context *context,
                                              uint32_t currentFrame,
                                              const gl::ActiveTextureArray<TextureVk *> &textures,
                                              const gl::SamplerBindingVector &samplers,
                                              PipelineType pipelineType,
                                              UpdateDescriptorSetsBuilder *updateBuilder);

    template <typename CommandBufferT>
    angle::Result bindDescriptorSets(vk::ErrorContext *context,
                                     uint32_t currentFrame,
                                     vk::CommandBufferHelperCommon *commandBufferHelper,
                                     CommandBufferT *commandBuffer,
                                     PipelineType pipelineType);

    bool usesDynamicUniformBufferDescriptors() const
    {
        return mUniformBufferDescriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
    }
    VkDescriptorType getUniformBufferDescriptorType() const { return mUniformBufferDescriptorType; }
    bool usesDynamicShaderStorageBufferDescriptors() const { return false; }
    VkDescriptorType getStorageBufferDescriptorType() const
    {
        return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
    }
    VkDescriptorType getAtomicCounterBufferDescriptorType() const
    {
        return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
    }
    bool usesDynamicAtomicCounterBufferDescriptors() const { return false; }

    bool areImmutableSamplersCompatible(
        const ImmutableSamplerIndexMap &immutableSamplerIndexMap) const
    {
        return (mImmutableSamplerIndexMap == immutableSamplerIndexMap);
    }

    size_t getDefaultUniformAlignedSize(vk::ErrorContext *context, gl::ShaderType shaderType) const
    {
        vk::Renderer *renderer = context->getRenderer();
        size_t alignment       = static_cast<size_t>(
            renderer->getPhysicalDeviceProperties().limits.minUniformBufferOffsetAlignment);
        return roundUp(mDefaultUniformBlocks[shaderType]->uniformData.size(), alignment);
    }

    std::shared_ptr<BufferAndLayout> &getSharedDefaultUniformBlock(gl::ShaderType shaderType)
    {
        return mDefaultUniformBlocks[shaderType];
    }

    bool updateAndCheckDirtyUniforms()
    {
        if (ANGLE_LIKELY(!mExecutable->IsPPO()))
        {
            return mDefaultUniformBlocksDirty.any();
        }

        const auto &ppoExecutables = mExecutable->getPPOProgramExecutables();
        for (gl::ShaderType shaderType : mExecutable->getLinkedShaderStages())
        {
            ProgramExecutableVk *executableVk = vk::GetImpl(ppoExecutables[shaderType].get());
            if (executableVk->mDefaultUniformBlocksDirty.test(shaderType))
            {
                mDefaultUniformBlocksDirty.set(shaderType);
                // Note: this relies on onProgramBind marking everything as dirty
                executableVk->mDefaultUniformBlocksDirty.reset(shaderType);
            }
        }

        return mDefaultUniformBlocksDirty.any();
    }

    void setAllDefaultUniformsDirty();
    angle::Result updateUniforms(vk::Context *context,
                                 uint32_t currentFrame,
                                 UpdateDescriptorSetsBuilder *updateBuilder,
                                 vk::BufferHelper *emptyBuffer,
                                 vk::DynamicBuffer *defaultUniformStorage,
                                 bool isTransformFeedbackActiveUnpaused,
                                 TransformFeedbackVk *transformFeedbackVk);
    void onProgramBind();

    const ShaderInterfaceVariableInfoMap &getVariableInfoMap() const { return mVariableInfoMap; }

    angle::Result warmUpPipelineCache(vk::Renderer *renderer,
                                      vk::PipelineRobustness pipelineRobustness,
                                      vk::PipelineProtectedAccess pipelineProtectedAccess)
    {
        return getPipelineCacheWarmUpTasks(renderer, pipelineRobustness, pipelineProtectedAccess,
                                           nullptr);
    }
    angle::Result getPipelineCacheWarmUpTasks(
        vk::Renderer *renderer,
        vk::PipelineRobustness pipelineRobustness,
        vk::PipelineProtectedAccess pipelineProtectedAccess,
        std::vector<std::shared_ptr<LinkSubTask>> *postLinkSubTasksOut);

    void waitForPostLinkTasks(const gl::Context *context) override
    {
        ContextVk *contextVk = vk::GetImpl(context);
        waitForPostLinkTasksImpl(contextVk);
    }
    void waitForComputePostLinkTasks(ContextVk *contextVk)
    {
        ASSERT(mExecutable->hasLinkedShaderStage(gl::ShaderType::Compute));
        waitForPostLinkTasksImpl(contextVk);
    }
    void waitForGraphicsPostLinkTasks(ContextVk *contextVk,
                                      const vk::GraphicsPipelineDesc &currentGraphicsPipelineDesc);

    angle::Result mergePipelineCacheToRenderer(vk::ErrorContext *context) const;

    angle::Result updateUniformsAndXfbDescInfo(vk::Context *context,
                                               const vk::BufferHelper *currentUniformBuffer,
                                               const vk::BufferHelper &emptyBuffer,
                                               uint32_t currentFrameCount,
                                               UpdateDescriptorSetsBuilder *updateBuilder,
                                               bool activeUnpaused,
                                               TransformFeedbackVk *transformFeedbackVk);

    angle::Result updateUniformBuffersDescInfo(vk::Context *context,
                                               vk::CommandBufferHelperCommon *commandBufferHelper,
                                               const gl::BufferVector &bufferBindings,
                                               VkDeviceSize maxBoundBufferRange,
                                               const vk::BufferHelper &emptyBuffer,
                                               uint32_t currentFrameCount,
                                               UpdateDescriptorSetsBuilder *updateBuilder);

    void updateOneUniformBufferOffset(const size_t blockIndex,
                                      const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding)
    {
        mUniformBuffersDescriptorDescBuilder.updateOneUniformBufferOffset(
            blockIndex, bufferBinding, mUniformBuffersWriteDescriptorDescs);
    }

    angle::Result 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);

    // The following functions are for internal use of programs, including from a threaded link job:
    angle::Result resizeUniformBlockMemory(vk::ErrorContext *context,
                                           const gl::ShaderMap<size_t> &requiredBufferSize);
    void resolvePrecisionMismatch(const gl::ProgramMergedVaryings &mergedVaryings);
    angle::Result initShaders(vk::ErrorContext *context,
                              const gl::ShaderBitSet &linkedShaderStages,
                              const gl::ShaderMap<const angle::spirv::Blob *> &spirvBlobs,
                              bool isGLES1)
    {
        return mOriginalShaderInfo.initShaders(context, linkedShaderStages, spirvBlobs,
                                               mVariableInfoMap, isGLES1);
    }
    void assignAllSpvLocations(vk::ErrorContext *context,
                               const gl::ProgramState &programState,
                               const gl::ProgramLinkedResources &resources)
    {
        SpvSourceOptions options = SpvCreateSourceOptions(
            context->getFeatures(), context->getRenderer()->getMaxColorInputAttachmentCount());
        SpvAssignAllLocations(options, programState, resources, &mVariableInfoMap);
    }

  private:
    class WarmUpTaskCommon;
    class WarmUpComputeTask;
    class WarmUpGraphicsTask;

    friend class ProgramVk;
    friend class ProgramPipelineVk;

    void reset(ContextVk *contextVk);

    void addInterfaceBlockDescriptorSetDesc(const std::vector<gl::InterfaceBlock> &blocks,
                                            gl::ShaderBitSet shaderTypes,
                                            VkDescriptorType descType,
                                            vk::DescriptorSetLayoutDesc *descOut);
    void addAtomicCounterBufferDescriptorSetDesc(
        const std::vector<gl::AtomicCounterBuffer> &atomicCounterBuffers,
        vk::DescriptorSetLayoutDesc *descOut);
    void addImageDescriptorSetDesc(vk::DescriptorSetLayoutDesc *descOut);
    void addInputAttachmentDescriptorSetDesc(vk::ErrorContext *context,
                                             vk::DescriptorSetLayoutDesc *descOut);
    angle::Result addTextureDescriptorSetDesc(
        vk::ErrorContext *context,
        const gl::ActiveTextureArray<TextureVk *> *activeTextures,
        vk::DescriptorSetLayoutDesc *descOut);

    size_t calcUniformUpdateRequiredSpace(vk::ErrorContext *context,
                                          gl::ShaderMap<VkDeviceSize> *uniformOffsets) const;

    ANGLE_INLINE angle::Result initProgram(vk::ErrorContext *context,
                                           gl::ShaderType shaderType,
                                           bool isLastPreFragmentStage,
                                           bool isTransformFeedbackProgram,
                                           ProgramTransformOptions optionBits,
                                           ProgramInfo *programInfo,
                                           const ShaderInterfaceVariableInfoMap &variableInfoMap)
    {
        ASSERT(mOriginalShaderInfo.valid());

        // Create the program pipeline.  This is done lazily and once per combination of
        // specialization constants.
        if (!programInfo->valid(shaderType))
        {
            ANGLE_TRY(programInfo->initProgram(context, shaderType, isLastPreFragmentStage,
                                               isTransformFeedbackProgram, mOriginalShaderInfo,
                                               optionBits, variableInfoMap));
        }
        ASSERT(programInfo->valid(shaderType));

        return angle::Result::Continue;
    }

    ANGLE_INLINE angle::Result initGraphicsShaderProgram(
        vk::ErrorContext *context,
        gl::ShaderType shaderType,
        bool isLastPreFragmentStage,
        bool isTransformFeedbackProgram,
        ProgramTransformOptions optionBits,
        ProgramInfo *programInfo,
        const ShaderInterfaceVariableInfoMap &variableInfoMap)
    {
        mValidGraphicsPermutations.set(optionBits.permutationIndex);
        return initProgram(context, shaderType, isLastPreFragmentStage, isTransformFeedbackProgram,
                           optionBits, programInfo, variableInfoMap);
    }

    ANGLE_INLINE angle::Result initComputeProgram(
        vk::ErrorContext *context,
        ProgramInfo *programInfo,
        const ShaderInterfaceVariableInfoMap &variableInfoMap,
        const vk::ComputePipelineOptions &pipelineOptions)
    {
        mValidComputePermutations.set(pipelineOptions.permutationIndex);
        ProgramTransformOptions optionBits = {};
        return initProgram(context, gl::ShaderType::Compute, false, false, optionBits, programInfo,
                           variableInfoMap);
    }

    ProgramTransformOptions getTransformOptions(ContextVk *contextVk,
                                                const vk::GraphicsPipelineDesc &desc);
    angle::Result initGraphicsShaderPrograms(vk::ErrorContext *context,
                                             ProgramTransformOptions transformOptions);
    angle::Result 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::Result 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);
    angle::Result preparePipelineCacheForWarmUp(vk::ErrorContext *context,
                                                vk::PipelineRobustness pipelineRobustness,
                                                vk::PipelineProtectedAccess pipelineProtectedAccess,
                                                vk::GraphicsPipelineSubset subset,
                                                bool *isComputeOut,
                                                vk::GraphicsPipelineDesc **graphicsPipelineDescOut,
                                                vk::RenderPass *renderPassOut);
    angle::Result warmUpComputePipelineCache(vk::ErrorContext *context,
                                             vk::PipelineRobustness pipelineRobustness,
                                             vk::PipelineProtectedAccess pipelineProtectedAccess);
    angle::Result warmUpGraphicsPipelineCache(vk::ErrorContext *context,
                                              vk::PipelineRobustness pipelineRobustness,
                                              vk::PipelineProtectedAccess pipelineProtectedAccess,
                                              vk::GraphicsPipelineSubset subset,
                                              const vk::GraphicsPipelineDesc &graphicsPipelineDesc,
                                              const vk::RenderPass &renderPass,
                                              vk::PipelineHelper *placeholderPipelineHelper);
    void waitForPostLinkTasksImpl(ContextVk *contextVk);

    angle::Result getOrAllocateDescriptorSet(vk::Context *context,
                                             uint32_t currentFrame,
                                             UpdateDescriptorSetsBuilder *updateBuilder,
                                             const vk::DescriptorSetDescBuilder &descriptorSetDesc,
                                             const vk::WriteDescriptorDescs &writeDescriptorDescs,
                                             DescriptorSetIndex setIndex,
                                             vk::SharedDescriptorSetCacheKey *newSharedCacheKeyOut);

    // When loading from cache / binary, initialize the pipeline cache with given data.  Otherwise
    // the cache is lazily created as needed.
    angle::Result initializePipelineCache(vk::ErrorContext *context,
                                          bool compressed,
                                          const std::vector<uint8_t> &pipelineData);
    angle::Result ensurePipelineCacheInitialized(vk::ErrorContext *context);

    void initializeWriteDescriptorDesc(vk::ErrorContext *context);

    void updateShaderResourcesWithSharedCacheKey(
        const gl::BufferVector &shaderStorageBufferBindings,
        const gl::BufferVector &atomicCounterBufferBindings,
        const gl::ActiveTextureArray<TextureVk *> &activeImages,
        const vk::SharedDescriptorSetCacheKey &newSharedCacheKey);

    angle::Result updateUniformsAndXfbDescriptorSet(
        vk::Context *context,
        uint32_t currentFrame,
        UpdateDescriptorSetsBuilder *updateBuilder,
        const vk::BufferHelper *defaultUniformBuffer,
        vk::SharedDescriptorSetCacheKey *sharedCacheKeyOut);

    angle::Result updateBuffersDescriptorSet(vk::Context *context,
                                             const uint32_t currentFrame,
                                             const vk::DescriptorSetDescBuilder &descriptorSetDesc,
                                             const vk::WriteDescriptorDescs &writeDescriptorDescs,
                                             const DescriptorSetIndex setIndex,
                                             UpdateDescriptorSetsBuilder *updateBuilder,
                                             vk::SharedDescriptorSetCacheKey *newSharedCacheKeyOut);

    // Descriptor sets and pools for shader resources for this program.
    angle::PackedEnumBitSet<DescriptorSetIndex, uint8_t> mValidDescriptorSetIndices;
    vk::DescriptorSetArray<vk::DescriptorSetPointer> mDescriptorSets;
    vk::DescriptorSetArray<vk::DynamicDescriptorPoolPointer> mDynamicDescriptorPools;
    vk::BufferSerial mCurrentDefaultUniformBufferSerial;

    // We keep a reference to the pipeline and descriptor set layouts. This ensures they don't get
    // deleted while this program is in use.
    uint32_t mImmutableSamplersMaxDescriptorCount;
    ImmutableSamplerIndexMap mImmutableSamplerIndexMap;
    vk::PipelineLayoutPtr mPipelineLayout;
    vk::DescriptorSetLayoutPointerArray mDescriptorSetLayouts;

    // A set of dynamic offsets used with vkCmdBindDescriptorSets for the default uniform buffers.
    VkDescriptorType mUniformBufferDescriptorType;
    gl::ShaderVector<uint32_t> mDefaultUniformDynamicDescriptorOffsets;

    ShaderInterfaceVariableInfoMap mVariableInfoMap;

    static_assert((ProgramTransformOptions::kPermutationCount == 16),
                  "ProgramTransformOptions::kPermutationCount must be 16.");
    angle::BitSet32<ProgramTransformOptions::kPermutationCount> mValidGraphicsPermutations;

    static_assert((vk::ComputePipelineOptions::kPermutationCount == 4),
                  "ComputePipelineOptions::kPermutationCount must be 4.");
    angle::BitSet8<vk::ComputePipelineOptions::kPermutationCount> mValidComputePermutations;

    // We store all permutations of surface rotation and transformed SPIR-V programs here. We may
    // need some LRU algorithm to free least used programs to reduce the number of programs.
    ProgramInfo mGraphicsProgramInfos[ProgramTransformOptions::kPermutationCount];
    ProgramInfo mComputeProgramInfo;

    // Pipeline caches.  The pipelines are tightly coupled with the shaders they are created for, so
    // they live in the program executable.  With VK_EXT_graphics_pipeline_library, the pipeline is
    // divided in subsets; the "shaders" subset is created based on the shaders, so its cache lives
    // in the program executable.  The "vertex input" and "fragment output" pipelines are
    // independent, and live in the context.
    CompleteGraphicsPipelineCache
        mCompleteGraphicsPipelines[ProgramTransformOptions::kPermutationCount];
    ShadersGraphicsPipelineCache
        mShadersGraphicsPipelines[ProgramTransformOptions::kPermutationCount];
    ComputePipelineCache mComputePipelines;

    DefaultUniformBlockMap mDefaultUniformBlocks;
    gl::ShaderBitSet mDefaultUniformBlocksDirty;

    ShaderInfo mOriginalShaderInfo;

    // The pipeline cache specific to this program executable.  Currently:
    //
    // - This is used during warm up (at link time)
    // - The contents are merged to Renderer's pipeline cache immediately after warm up
    // - The contents are returned as part of program binary
    // - Draw-time pipeline creation uses Renderer's cache
    //
    // Without VK_EXT_graphics_pipeline_library, this cache is not used for draw-time pipeline
    // creations to allow reuse of other blobs that are independent of the actual shaders; vertex
    // input fetch, fragment output and blend.
    //
    // With VK_EXT_graphics_pipeline_library, this cache is used for the "shaders" subset of the
    // pipeline.
    vk::PipelineCache mPipelineCache;

    vk::GraphicsPipelineDesc mWarmUpGraphicsPipelineDesc;

    // The "layout" information for descriptorSets
    vk::WriteDescriptorDescs mUniformBuffersWriteDescriptorDescs;
    vk::WriteDescriptorDescs mShaderResourceWriteDescriptorDescs;
    vk::WriteDescriptorDescs mTextureWriteDescriptorDescs;
    vk::WriteDescriptorDescs mDefaultUniformAndXfbWriteDescriptorDescs;

    // The DescriptorSetDescBuilder for descriptorSets
    vk::DescriptorSetDescBuilder mUniformBuffersDescriptorDescBuilder;
    vk::DescriptorSetDescBuilder mShaderResourceDescriptorDescBuilder;
    vk::DescriptorSetDescBuilder mTextureDescriptorDescBuilder;
    vk::DescriptorSetDescBuilder mDefaultUniformAndXfbDescriptorDescBuilder;

    vk::DescriptorSetLayoutDesc mUniformBuffersSetDesc;
    vk::DescriptorSetLayoutDesc mShaderResourceSetDesc;
    vk::DescriptorSetLayoutDesc mTextureSetDesc;
    vk::DescriptorSetLayoutDesc mDefaultUniformAndXfbSetDesc;
};

}  // namespace rx

#endif  // LIBANGLE_RENDERER_VULKAN_PROGRAMEXECUTABLEVK_H_
