/*
 * Copyright 2022 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "src/gpu/graphite/vk/VulkanResourceProvider.h"

#include "include/core/SkSpan.h"
#include "include/gpu/MutableTextureState.h"
#include "include/gpu/graphite/BackendTexture.h"
#include "include/gpu/graphite/vk/VulkanGraphiteTypes.h"
#include "include/gpu/vk/VulkanMutableTextureState.h"
#include "src/gpu/graphite/Buffer.h"
#include "src/gpu/graphite/ComputePipeline.h"
#include "src/gpu/graphite/GraphicsPipeline.h"
#include "src/gpu/graphite/RenderPassDesc.h"
#include "src/gpu/graphite/Sampler.h"
#include "src/gpu/graphite/Texture.h"
#include "src/gpu/graphite/TextureInfoPriv.h"
#include "src/gpu/graphite/vk/VulkanBuffer.h"
#include "src/gpu/graphite/vk/VulkanCommandBuffer.h"
#include "src/gpu/graphite/vk/VulkanDescriptorPool.h"
#include "src/gpu/graphite/vk/VulkanDescriptorSet.h"
#include "src/gpu/graphite/vk/VulkanFramebuffer.h"
#include "src/gpu/graphite/vk/VulkanGraphicsPipeline.h"
#include "src/gpu/graphite/vk/VulkanGraphiteUtils.h"
#include "src/gpu/graphite/vk/VulkanRenderPass.h"
#include "src/gpu/graphite/vk/VulkanSampler.h"
#include "src/gpu/graphite/vk/VulkanSharedContext.h"
#include "src/gpu/graphite/vk/VulkanTexture.h"
#include "src/gpu/graphite/vk/VulkanYcbcrConversion.h"
#include "src/gpu/vk/VulkanMemory.h"
#include "src/sksl/SkSLCompiler.h"

#ifdef  SK_BUILD_FOR_ANDROID
#include "src/gpu/vk/VulkanUtilsPriv.h"
#include <android/hardware_buffer.h>
#endif

namespace skgpu::graphite {

constexpr int kMaxNumberOfCachedBufferDescSets = 1024;

namespace {

// Create a mock pipeline layout that has a compatible input attachment descriptor set layout and
// push constant parameters with all other real pipeline layouts. This allows us to perform
// once-per-renderpass operations even before a real pipeline is bound by the command buffer.
VkPipelineLayout create_mock_layout(const VulkanSharedContext* sharedContext) {
    SkASSERT(sharedContext);
    VkPushConstantRange pushConstantRange;
    pushConstantRange.offset = 0;
    pushConstantRange.size = VulkanResourceProvider::kIntrinsicConstantSize;
    pushConstantRange.stageFlags = VulkanResourceProvider::kIntrinsicConstantStageFlags;

    skia_private::STArray<1, DescriptorData> inputDesc {
            VulkanGraphicsPipeline::kInputAttachmentDescriptor};
    VkDescriptorSetLayout setLayout;
    DescriptorDataToVkDescSetLayout(sharedContext, inputDesc, &setLayout);

    VkPipelineLayoutCreateInfo layoutCreateInfo = {};
    layoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
    layoutCreateInfo.setLayoutCount = 1;
    layoutCreateInfo.pSetLayouts = &setLayout;
    layoutCreateInfo.pushConstantRangeCount = 1;
    layoutCreateInfo.pPushConstantRanges = &pushConstantRange;

    VkResult result;
    VkPipelineLayout pipelineLayout;
    VULKAN_CALL_RESULT(sharedContext,
                       result,
                       CreatePipelineLayout(sharedContext->device(),
                                            &layoutCreateInfo,
                                            /*const VkAllocationCallbacks*=*/nullptr,
                                            &pipelineLayout));

    // Once the pipeline layout is created, we can clean up the VkDescriptorSetLayout.
    VULKAN_CALL(sharedContext->interface(),
                DestroyDescriptorSetLayout(sharedContext->device(), setLayout, nullptr));

    return pipelineLayout;
}

} // anonymous namespace

VulkanResourceProvider::VulkanResourceProvider(SharedContext* sharedContext,
                                               SingleOwner* singleOwner,
                                               uint32_t recorderID,
                                               size_t resourceBudget)
        : ResourceProvider(sharedContext, singleOwner, recorderID, resourceBudget)
        , fMockPipelineLayout(
                create_mock_layout(static_cast<const VulkanSharedContext*>(sharedContext)))
        , fUniformBufferDescSetCache(kMaxNumberOfCachedBufferDescSets) {}

VulkanResourceProvider::~VulkanResourceProvider() {
    if (fMockPipelineLayout) {
        VULKAN_CALL(this->vulkanSharedContext()->interface(),
                    DestroyPipelineLayout(this->vulkanSharedContext()->device(),
                                          fMockPipelineLayout,
                                          nullptr));
    }
}

const VulkanSharedContext* VulkanResourceProvider::vulkanSharedContext() const {
    return static_cast<const VulkanSharedContext*>(fSharedContext);
}

VulkanSharedContext* VulkanResourceProvider::nonConstVulkanSharedContext() {
    return static_cast<VulkanSharedContext*>(fSharedContext);
}

sk_sp<Texture> VulkanResourceProvider::onCreateWrappedTexture(const BackendTexture& texture) {
    sk_sp<VulkanYcbcrConversion> ycbcrConversion;
    const auto& vkInfo = TextureInfoPriv::Get<VulkanTextureInfo>(texture.info());
    if (vkInfo.fYcbcrConversionInfo.isValid()) {
        ycbcrConversion = this->findOrCreateCompatibleYcbcrConversion(vkInfo.fYcbcrConversionInfo);
        if (!ycbcrConversion) {
            return nullptr;
        }
    }

    return VulkanTexture::MakeWrapped(this->vulkanSharedContext(),
                                      texture.dimensions(),
                                      texture.info(),
                                      BackendTextures::GetMutableState(texture),
                                      BackendTextures::GetVkImage(texture),
                                      /*alloc=*/{} /*Skia does not own wrapped texture memory*/,
                                      std::move(ycbcrConversion));
}

sk_sp<ComputePipeline> VulkanResourceProvider::createComputePipeline(const ComputePipelineDesc&) {
    return nullptr;
}

sk_sp<Texture> VulkanResourceProvider::createTexture(SkISize size,
                                                     const TextureInfo& info) {
    sk_sp<VulkanYcbcrConversion> ycbcrConversion;
    const auto& vkInfo = TextureInfoPriv::Get<VulkanTextureInfo>(info);
    if (vkInfo.fYcbcrConversionInfo.isValid()) {
        ycbcrConversion = this->findOrCreateCompatibleYcbcrConversion(vkInfo.fYcbcrConversionInfo);
        if (!ycbcrConversion) {
            return nullptr;
        }
    }

    return VulkanTexture::Make(this->vulkanSharedContext(),
                               size,
                               info,
                               std::move(ycbcrConversion));
}

sk_sp<Buffer> VulkanResourceProvider::createBuffer(size_t size,
                                                   BufferType type,
                                                   AccessPattern accessPattern) {
    return VulkanBuffer::Make(this->vulkanSharedContext(), size, type, accessPattern);
}

sk_sp<Sampler> VulkanResourceProvider::createSampler(const SamplerDesc& samplerDesc) {
    sk_sp<VulkanYcbcrConversion> ycbcrConversion = nullptr;

    // Non-zero conversion information means the sampler utilizes a ycbcr conversion.
    const bool usesYcbcrConversion = samplerDesc.isImmutable();
    if (usesYcbcrConversion) {
        VulkanYcbcrConversionInfo ycbcrInfo = VulkanYcbcrConversion::FromImmutableSamplerInfo(
                samplerDesc.immutableSamplerInfo());
        ycbcrConversion = this->findOrCreateCompatibleYcbcrConversion(ycbcrInfo);
        if (!ycbcrConversion) {
            return nullptr;
        }
    }

    return VulkanSampler::Make(this->vulkanSharedContext(),
                               samplerDesc,
                               std::move(ycbcrConversion));
}

BackendTexture VulkanResourceProvider::onCreateBackendTexture(SkISize dimensions,
                                                              const TextureInfo& info) {
    const auto& vkTexInfo = TextureInfoPriv::Get<VulkanTextureInfo>(info);
    VulkanTexture::CreatedImageInfo createdTextureInfo;
    if (!VulkanTexture::MakeVkImage(this->vulkanSharedContext(), dimensions, info,
                                    &createdTextureInfo)) {
        return {};
    }
    return BackendTextures::MakeVulkan(
            dimensions,
            vkTexInfo,
            skgpu::MutableTextureStates::GetVkImageLayout(createdTextureInfo.fMutableState.get()),
            skgpu::MutableTextureStates::GetVkQueueFamilyIndex(
                    createdTextureInfo.fMutableState.get()),
            createdTextureInfo.fImage,
            createdTextureInfo.fMemoryAlloc);
}

namespace {
GraphiteResourceKey build_desc_set_key(const SkSpan<DescriptorData>& requestedDescriptors) {
    static const ResourceType kType = GraphiteResourceKey::GenerateResourceType();

    // The number of int32s needed for a key can depend on whether we use immutable samplers or not.
    // So, accumulte key data while passing through to check for that quantity and simply copy
    // into builder afterwards.
    skia_private::TArray<uint32_t> keyData (requestedDescriptors.size() + 1);

    keyData.push_back(requestedDescriptors.size());
    for (const DescriptorData& desc : requestedDescriptors) {
        keyData.push_back(static_cast<uint8_t>(desc.fType) << 24 |
                          desc.fBindingIndex << 16 |
                          static_cast<uint16_t>(desc.fCount));
        if (desc.fImmutableSampler) {
            const VulkanSampler* sampler =
                    static_cast<const VulkanSampler*>(desc.fImmutableSampler);
            SkASSERT(sampler);
            keyData.push_back_n(sampler->samplerDesc().asSpan().size(),
                                sampler->samplerDesc().asSpan().data());
        }
    }

    GraphiteResourceKey key;
    GraphiteResourceKey::Builder builder(&key, kType, keyData.size());

    for (int i = 0; i < keyData.size(); i++) {
        builder[i] = keyData[i];
    }

    builder.finish();
    return key;
}

sk_sp<VulkanDescriptorSet> add_new_desc_set_to_cache(const VulkanSharedContext* context,
                                                     const sk_sp<VulkanDescriptorPool>& pool,
                                                     const GraphiteResourceKey& descSetKey,
                                                     ResourceCache* resourceCache) {
    sk_sp<VulkanDescriptorSet> descSet = VulkanDescriptorSet::Make(context, pool);
    if (!descSet) {
        return nullptr;
    }
    resourceCache->insertResource(descSet.get(), descSetKey, Budgeted::kYes, Shareable::kNo);

    return descSet;
}
} // anonymous namespace

sk_sp<VulkanDescriptorSet> VulkanResourceProvider::findOrCreateDescriptorSet(
        SkSpan<DescriptorData> requestedDescriptors) {
    if (requestedDescriptors.empty()) {
        return nullptr;
    }

    // Search for available descriptor sets by assembling a key based upon the set's structure.
    GraphiteResourceKey key = build_desc_set_key(requestedDescriptors);
    if (auto descSet = fResourceCache->findAndRefResource(
                key, skgpu::Budgeted::kYes, Shareable::kNo)) {
        // A non-null resource pointer indicates we have found an available descriptor set.
        return sk_sp<VulkanDescriptorSet>(static_cast<VulkanDescriptorSet*>(descSet));
    }


    // If we did not find an existing avilable desc set, allocate sets with the appropriate layout
    // and add them to the cache.
    VkDescriptorSetLayout layout;
    const VulkanSharedContext* context = this->vulkanSharedContext();
    DescriptorDataToVkDescSetLayout(context, requestedDescriptors, &layout);
    if (!layout) {
        return nullptr;
    }
    auto pool = VulkanDescriptorPool::Make(context, requestedDescriptors, layout);
    if (!pool) {
        VULKAN_CALL(context->interface(), DestroyDescriptorSetLayout(context->device(),
                                                                     layout,
                                                                     nullptr));
        return nullptr;
    }

    // Start with allocating one descriptor set. If one cannot be successfully created, then we can
    // return early before attempting to allocate more. Storing a ptr to the first set also
    // allows us to return that later without having to perform a find operation on the cache once
    // all the sets are added.
    auto firstDescSet =
            add_new_desc_set_to_cache(context, pool, key, fResourceCache.get());
    if (!firstDescSet) {
        return nullptr;
    }

    // Continue to allocate & cache the maximum number of sets so they can be easily accessed as
    // they're needed.
    for (int i = 1; i < VulkanDescriptorPool::kMaxNumSets ; i++) {
        auto descSet =
                add_new_desc_set_to_cache(context, pool, key, fResourceCache.get());
        if (!descSet) {
            SKGPU_LOG_W("Descriptor set allocation %d of %d was unsuccessful; no more sets will be"
                        "allocated from this pool.", i, VulkanDescriptorPool::kMaxNumSets);
            break;
        }
    }

    return firstDescSet;
}

namespace {

VulkanResourceProvider::UniformBindGroupKey make_ubo_bind_group_key(
        SkSpan<DescriptorData> requestedDescriptors,
        SkSpan<BindBufferInfo> bindUniformBufferInfo) {
    VulkanResourceProvider::UniformBindGroupKey uniqueKey;
    {
        // Each entry in the bind group needs 2 uint32_t in the key:
        //  - buffer's unique ID: 32 bits.
        //  - buffer's binding size: 32 bits.
        // We need total of 4 entries in the uniform buffer bind group.
        // Unused entries will be assigned zero values.
        VulkanResourceProvider::UniformBindGroupKey::Builder builder(&uniqueKey);

        for (uint32_t i = 0; i < VulkanGraphicsPipeline::kNumUniformBuffers; ++i) {
            builder[2 * i] = 0;
            builder[2 * i + 1] = 0;
        }

        for (uint32_t i = 0; i < requestedDescriptors.size(); ++i) {
            int descriptorBindingIndex = requestedDescriptors[i].fBindingIndex;
            SkASSERT(SkTo<unsigned long>(descriptorBindingIndex) < bindUniformBufferInfo.size());
            SkASSERT(SkTo<unsigned long>(descriptorBindingIndex) <
                     VulkanGraphicsPipeline::kNumUniformBuffers);
            const auto& bindInfo = bindUniformBufferInfo[descriptorBindingIndex];
            const VulkanBuffer* boundBuffer = static_cast<const VulkanBuffer*>(bindInfo.fBuffer);
            SkASSERT(boundBuffer);
            builder[2 * descriptorBindingIndex] = boundBuffer->uniqueID().asUInt();
            builder[2 * descriptorBindingIndex + 1] = bindInfo.fSize;
        }

        builder.finish();
    }

    return uniqueKey;
}

void update_uniform_descriptor_set(SkSpan<DescriptorData> requestedDescriptors,
                                   SkSpan<BindBufferInfo> bindUniformBufferInfo,
                                   VkDescriptorSet descSet,
                                   const VulkanSharedContext* sharedContext) {
    for (size_t i = 0; i < requestedDescriptors.size(); i++) {
        int descriptorBindingIndex = requestedDescriptors[i].fBindingIndex;
        SkASSERT(SkTo<unsigned long>(descriptorBindingIndex) < bindUniformBufferInfo.size());
        const auto& bindInfo = bindUniformBufferInfo[descriptorBindingIndex];
        if (bindInfo.fBuffer) {
#if defined(SK_DEBUG)
            static uint64_t maxBufferRange =
                sharedContext->caps()->storageBufferSupport()
                    ? sharedContext->vulkanCaps().maxStorageBufferRange()
                    : sharedContext->vulkanCaps().maxUniformBufferRange();
            SkASSERT(bindInfo.fSize <= maxBufferRange);
#endif
            VkDescriptorBufferInfo bufferInfo = {};
            auto vulkanBuffer = static_cast<const VulkanBuffer*>(bindInfo.fBuffer);
            bufferInfo.buffer = vulkanBuffer->vkBuffer();
            bufferInfo.offset = 0; // We always use dynamic ubos so we set the base offset to 0
            bufferInfo.range = bindInfo.fSize;

            VkWriteDescriptorSet writeInfo = {};
            writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
            writeInfo.dstSet = descSet;
            writeInfo.dstBinding = descriptorBindingIndex;
            writeInfo.dstArrayElement = 0;
            writeInfo.descriptorCount = requestedDescriptors[i].fCount;
            writeInfo.descriptorType = DsTypeEnumToVkDs(requestedDescriptors[i].fType);
            writeInfo.pBufferInfo = &bufferInfo;

            // TODO(b/293925059): Migrate to updating all the uniform descriptors with one driver
            // call. Calling UpdateDescriptorSets once to encapsulate updates to all uniform
            // descriptors would be ideal, but that led to issues with draws where all the UBOs
            // within that set would unexpectedly be assigned the same offset. Updating them one at
            // a time within this loop works in the meantime but is suboptimal.
            VULKAN_CALL(sharedContext->interface(),
                        UpdateDescriptorSets(sharedContext->device(),
                                             /*descriptorWriteCount=*/1,
                                             &writeInfo,
                                             /*descriptorCopyCount=*/0,
                                             /*pDescriptorCopies=*/nullptr));
        }
    }
}

} // anonymous namespace

sk_sp<VulkanDescriptorSet> VulkanResourceProvider::findOrCreateUniformBuffersDescriptorSet(
        SkSpan<DescriptorData> requestedDescriptors,
        SkSpan<BindBufferInfo> bindUniformBufferInfo) {
    SkASSERT(requestedDescriptors.size() <= VulkanGraphicsPipeline::kNumUniformBuffers);

    auto key = make_ubo_bind_group_key(requestedDescriptors, bindUniformBufferInfo);
    auto* existingDescSet = fUniformBufferDescSetCache.find(key);
    if (existingDescSet) {
        return *existingDescSet;
    }
    sk_sp<VulkanDescriptorSet> newDS = this->findOrCreateDescriptorSet(requestedDescriptors);
    if (!newDS) {
        return nullptr;
    }

    update_uniform_descriptor_set(requestedDescriptors,
                                  bindUniformBufferInfo,
                                  *newDS->descriptorSet(),
                                  this->vulkanSharedContext());
    return *fUniformBufferDescSetCache.insert(key, newDS);
}

sk_sp<VulkanRenderPass> VulkanResourceProvider::findOrCreateRenderPass(
        const RenderPassDesc& originalRenderPassDesc, bool compatibleOnly) {
    static constexpr Budgeted kBudgeted = Budgeted::kYes;
    static constexpr Shareable kShareable = Shareable::kYes;
    static const ResourceType kType = GraphiteResourceKey::GenerateResourceType();

    const RenderPassDesc renderPassDesc =
            compatibleOnly ? MakePipelineCompatibleRenderPass(originalRenderPassDesc)
                           : originalRenderPassDesc;

    GraphiteResourceKey key;
    {
        GraphiteResourceKey::Builder builder(&key, kType, 1);
        builder[0] = VulkanRenderPass::GetRenderPassKey(renderPassDesc,
                                                        /*compatibleForPipelineKey=*/false);
    }
    if (Resource* resource = fResourceCache->findAndRefResource(key, kBudgeted, kShareable)) {
        return sk_sp<VulkanRenderPass>(static_cast<VulkanRenderPass*>(resource));
    }

    sk_sp<VulkanRenderPass> renderPass =
            VulkanRenderPass::Make(this->vulkanSharedContext(), renderPassDesc);
    if (!renderPass) {
        return nullptr;
    }

    fResourceCache->insertResource(renderPass.get(), key, kBudgeted, kShareable);

    return renderPass;
}

namespace {

void gather_attachment_views(skia_private::TArray<VkImageView>& attachmentViews,
                             VulkanTexture* colorTexture,
                             VulkanTexture* resolveTexture,
                             VulkanTexture* depthStencilTexture) {
    if (colorTexture) {
        VkImageView& colorAttachmentView = attachmentViews.push_back();
        colorAttachmentView =
                colorTexture->getImageView(VulkanImageView::Usage::kAttachment)->imageView();

        if (resolveTexture) {
            VkImageView& resolveView = attachmentViews.push_back();
            resolveView =
                    resolveTexture->getImageView(VulkanImageView::Usage::kAttachment)->imageView();
        }
    }

    if (depthStencilTexture) {
        VkImageView& stencilView = attachmentViews.push_back();
        stencilView =
                depthStencilTexture->getImageView(VulkanImageView::Usage::kAttachment)->imageView();
    }
}

} // anonymous namespace

sk_sp<VulkanFramebuffer> VulkanResourceProvider::findOrCreateFramebuffer(
        const VulkanSharedContext* context,
        VulkanTexture* colorTexture,
        VulkanTexture* resolveTexture,
        VulkanTexture* depthStencilTexture,
        const RenderPassDesc& renderPassDesc,
        const VulkanRenderPass& renderPass,
        const int width,
        const int height) {

    VulkanTexture* mainTexture = nullptr;
    if (colorTexture) {
        mainTexture = resolveTexture ? resolveTexture : colorTexture;
    } else {
        SkASSERT(depthStencilTexture);
        mainTexture = depthStencilTexture;
    }
    SkASSERT(mainTexture);
    VulkanTexture* msaaTexture = resolveTexture ? colorTexture : nullptr;

    // First check for a cached frame buffer.
    sk_sp<VulkanFramebuffer> fb = mainTexture->getCachedFramebuffer(renderPassDesc,
                                                                    msaaTexture,
                                                                    depthStencilTexture);
    if (fb) {
        return fb;
    }

    // Gather attachment views neeeded for frame buffer creation.
    skia_private::TArray<VkImageView> attachmentViews;
    gather_attachment_views(attachmentViews, colorTexture, resolveTexture, depthStencilTexture);

    VkFramebufferCreateInfo framebufferInfo = {};
    framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
    framebufferInfo.renderPass = renderPass.renderPass();
    framebufferInfo.attachmentCount = attachmentViews.size();
    framebufferInfo.pAttachments = attachmentViews.begin();
    framebufferInfo.width = width;
    framebufferInfo.height = height;
    framebufferInfo.layers = 1;
    fb = VulkanFramebuffer::Make(context,
                                 framebufferInfo,
                                 renderPassDesc,
                                 sk_ref_sp(msaaTexture),
                                 sk_ref_sp(depthStencilTexture));
    mainTexture->addCachedFramebuffer(fb);
    return fb;
}

void VulkanResourceProvider::onDeleteBackendTexture(const BackendTexture& texture) {
    SkASSERT(texture.isValid());
    SkASSERT(texture.backend() == BackendApi::kVulkan);

    VULKAN_CALL(this->vulkanSharedContext()->interface(),
                DestroyImage(this->vulkanSharedContext()->device(),
                             BackendTextures::GetVkImage(texture),
                             /*VkAllocationCallbacks=*/nullptr));

    VulkanAlloc alloc = BackendTextures::GetMemoryAlloc(texture);
    // Free the image memory used for the BackendTexture's VkImage.
    //
    // How we do this is dependent upon on how the image was allocated (via the memory allocator or
    // with a direct call to the Vulkan driver) . If the VulkanAlloc's fBackendMemory is != 0, then
    // that means the allocator was used. Otherwise, a direct driver call was used and we should
    // free the VkDeviceMemory (fMemory).
    if (alloc.fBackendMemory) {
        skgpu::VulkanMemory::FreeImageMemory(this->vulkanSharedContext()->memoryAllocator(), alloc);
    } else {
        SkASSERT(alloc.fMemory != VK_NULL_HANDLE);
        VULKAN_CALL(this->vulkanSharedContext()->interface(),
                    FreeMemory(this->vulkanSharedContext()->device(), alloc.fMemory, nullptr));
    }
}

sk_sp<VulkanYcbcrConversion> VulkanResourceProvider::findOrCreateCompatibleYcbcrConversion(
        const VulkanYcbcrConversionInfo& ycbcrInfo) const {
    static constexpr Budgeted kBudgeted = Budgeted::kYes;
    static constexpr Shareable kShareable = Shareable::kYes;
    if (!ycbcrInfo.isValid()) {
        return nullptr;
    }

    GraphiteResourceKey key;
    {
        static const ResourceType kType = GraphiteResourceKey::GenerateResourceType();
        static constexpr int kKeySize = 3;

        GraphiteResourceKey::Builder builder(&key, kType, kKeySize);
        ImmutableSamplerInfo packedInfo = VulkanYcbcrConversion::ToImmutableSamplerInfo(ycbcrInfo);
        builder[0] = packedInfo.fNonFormatYcbcrConversionInfo;
        builder[1] = (uint32_t) packedInfo.fFormat;
        builder[2] = (uint32_t) (packedInfo.fFormat >> 32);
    }

    if (Resource* resource = fResourceCache->findAndRefResource(key, kBudgeted, kShareable)) {
        return sk_sp(static_cast<VulkanYcbcrConversion*>(resource));
    }

    auto ycbcrConversion = VulkanYcbcrConversion::Make(this->vulkanSharedContext(), ycbcrInfo);
    if (!ycbcrConversion) {
        return nullptr;
    }

    fResourceCache->insertResource(ycbcrConversion.get(), key, kBudgeted, kShareable);
    return ycbcrConversion;
}

sk_sp<VulkanGraphicsPipeline> VulkanResourceProvider::findOrCreateLoadMSAAPipeline(
        const RenderPassDesc& renderPassDesc) {
    if (renderPassDesc.fColorResolveAttachment.fFormat == TextureFormat::kUnsupported ||
        renderPassDesc.fColorAttachment.fFormat == TextureFormat::kUnsupported) {
        SKGPU_LOG_E("Loading MSAA from resolve texture requires valid color & resolve attachment");
        return nullptr;
    }

    // Check to see if we already have a suitable pipeline that we can use.
    const uint32_t compatibleRenderPassHash =
            VulkanRenderPass::GetRenderPassKey(renderPassDesc, /*compatibleForPipelineKey=*/true);
    for (int i = 0; i < fLoadMSAAPipelines.size(); i++) {
        if (compatibleRenderPassHash == fLoadMSAAPipelines.at(i).first) {
            return fLoadMSAAPipelines.at(i).second;
        }
    }

    if (!fLoadMSAAProgram) {
        // Lazily create the modules and pipeline layout the first time we need to load MSAA
        fLoadMSAAProgram =
                VulkanGraphicsPipeline::CreateLoadMSAAProgram(this->vulkanSharedContext());
        if (!fLoadMSAAProgram) {
            SKGPU_LOG_E("Failed to initialize MSAA load pipeline creation structure(s)");
            return nullptr;
        }
    }

    sk_sp<VulkanGraphicsPipeline> pipeline = VulkanGraphicsPipeline::MakeLoadMSAAPipeline(
            this->nonConstVulkanSharedContext(), *fLoadMSAAProgram, renderPassDesc);
    if (!pipeline) {
        SKGPU_LOG_E("Failed to create MSAA load pipeline");
        return nullptr;
    }

    fLoadMSAAPipelines.push_back(std::make_pair(compatibleRenderPassHash, pipeline));
    return pipeline;
}

VulkanThreadSafeResourceProvider::VulkanThreadSafeResourceProvider(
        std::unique_ptr<ResourceProvider> resourceProvider)
    : ThreadSafeResourceProvider(std::move(resourceProvider)) {}

sk_sp<VulkanRenderPass> VulkanThreadSafeResourceProvider::findOrCreateRenderPass(
        const RenderPassDesc& renderPassDesc,
        bool compatibleOnly) {
    SkAutoSpinlock lock{fSpinLock};

    VulkanResourceProvider* vkResourceProvider =
        static_cast<VulkanResourceProvider*>(fWrappedProvider.get());

    sk_sp<VulkanRenderPass> renderPass =
        vkResourceProvider->findOrCreateRenderPass(renderPassDesc, compatibleOnly);
    SkAssertResult(renderPass->gpuMemorySize() == 0);

    return renderPass;
}

#ifdef SK_BUILD_FOR_ANDROID

BackendTexture VulkanResourceProvider::onCreateBackendTexture(AHardwareBuffer* hardwareBuffer,
                                                              bool isRenderable,
                                                              bool isProtectedContent,
                                                              SkISize dimensions,
                                                              bool fromAndroidWindow) const {

    const VulkanSharedContext* vkContext = this->vulkanSharedContext();
    VkDevice device = vkContext->device();
    const VulkanCaps& vkCaps = vkContext->vulkanCaps();

    VkAndroidHardwareBufferFormatPropertiesANDROID hwbFormatProps;
    VkAndroidHardwareBufferPropertiesANDROID hwbProps;
    if (!skgpu::GetAHardwareBufferProperties(
                &hwbFormatProps, &hwbProps, vkContext->interface(), hardwareBuffer, device)) {
        return {};
    }

    // Import as external if the AHardwareBuffer has an undefined format or if graphite does not
    // support the provided VkFormat.
    bool importAsExternalFormat = hwbFormatProps.format == VK_FORMAT_UNDEFINED ||
                                  !vkCaps.isFormatSupported(hwbFormatProps.format);
#if defined(SK_DEBUG)
    if (importAsExternalFormat && hwbFormatProps.format != VK_FORMAT_UNDEFINED) {
        SKGPU_LOG_D("Ignoring AHardwareBuffer VkFormat(%d) because it is not supported by graphite."
                    " Falling back to importing as external format.\n", hwbFormatProps.format);
    }
#endif

    // Start to assemble VulkanTextureInfo which is needed later on to create the VkImage but can
    // sooner help us query VulkanCaps for certain format feature support.
    //
    // Note that the optimal tiling is always the right choice, including for external formats
    // (which always require optimal) and AHBs (where the real layout is determined by AHB usage
    // flags, and optimal tiling would automatically mean linear if it has to).
    VkImageTiling tiling = VK_IMAGE_TILING_OPTIMAL;
    VkImageCreateFlags imgCreateflags = isProtectedContent ? VK_IMAGE_CREATE_PROTECTED_BIT : 0;
    VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT;
    // When importing as an external format the image usage can only be VK_IMAGE_USAGE_SAMPLED_BIT.
    if (!importAsExternalFormat) {
        usageFlags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
        if (isRenderable) {
            // Renderable attachments can be used as input attachments if we are loading from MSAA.
            usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
            // Opt into MSAA-render-to-SS to match getDefaultSampled/AttachmentInfo in VulkanCaps
            if (vkCaps.msaaRenderToSingleSampledSupport()) {
                imgCreateflags |= VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT;
            }
        }
        // For non-renderable Graphite-created textures, VulkanCaps also attempts to use
        // VK_IMAGE_USAGE_HOST_TRANSFER_BIT, but if we are wrapping an AHardwareBuffer, its contents
        // are presumably managed by the client and we aren't expecting to have to write directly
        // to it from CPU memory.
    }
    VulkanTextureInfo vkTexInfo {
            VK_SAMPLE_COUNT_1_BIT,
            Mipmapped::kNo,
            imgCreateflags,
            importAsExternalFormat ? VK_FORMAT_UNDEFINED : hwbFormatProps.format,
            tiling,
            usageFlags,
            VK_SHARING_MODE_EXCLUSIVE,
            VK_IMAGE_ASPECT_COLOR_BIT,
            VulkanYcbcrConversionInfo() };

    if (isRenderable && (importAsExternalFormat || !vkCaps.isRenderable(vkTexInfo))) {
        SKGPU_LOG_W("Renderable texture requested from an AHardwareBuffer which uses a VkFormat "
                    "that Skia cannot render to (VkFormat: %d).\n",  hwbFormatProps.format);
        return {};
    }

    if (!importAsExternalFormat && (!vkCaps.isTransferSrc(vkTexInfo) ||
                                    !vkCaps.isTransferDst(vkTexInfo) ||
                                    !vkCaps.isTexturable(vkTexInfo))) {
        if (isRenderable) {
            SKGPU_LOG_W("VkFormat %d does not support the necessary format features. Because a "
                        "renderable texture was requested, we cannot fall back to importing with "
                        "an external format.\n", hwbFormatProps.format);
            return {};
        }
        // If the VkFormat does not support the features we need, then import as an external format.
        importAsExternalFormat = true;
        // If we use VkExternalFormatANDROID with an externalFormat != 0, then format must =
        // VK_FORMAT_UNDEFINED.
        vkTexInfo.fFormat = VK_FORMAT_UNDEFINED;
        vkTexInfo.fImageUsageFlags = VK_IMAGE_USAGE_SAMPLED_BIT;
    }

    VulkanYcbcrConversionInfo ycbcrInfo;
    VkExternalFormatANDROID externalFormat;
    externalFormat.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID;
    externalFormat.pNext = nullptr;
    externalFormat.externalFormat = 0;  // If this is zero it is as if we aren't using this struct.
    if (importAsExternalFormat || skgpu::VkFormatNeedsYcbcrSampler(hwbFormatProps.format)) {
        GetYcbcrConversionInfoFromFormatProps(&ycbcrInfo, hwbFormatProps);
        if (!ycbcrInfo.isValid()) {
            SKGPU_LOG_W("Failed to create valid YCbCr conversion information from hardware buffer"
                        "format properties.\n");
            return {};
        }
        vkTexInfo.fYcbcrConversionInfo = ycbcrInfo;
        externalFormat.externalFormat = hwbFormatProps.externalFormat;
    }
    const VkExternalMemoryImageCreateInfo externalMemoryImageInfo{
            VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,                 // sType
            &externalFormat,                                                     // pNext
            VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID,  // handleTypes
    };

    SkASSERT(!(vkTexInfo.fFlags & VK_IMAGE_CREATE_PROTECTED_BIT) ||
             fSharedContext->isProtected() == Protected::kYes);

    const VkImageCreateInfo imageCreateInfo = {
        VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                 // sType
        &externalMemoryImageInfo,                                            // pNext
        vkTexInfo.fFlags,                                                    // VkImageCreateFlags
        VK_IMAGE_TYPE_2D,                                                    // VkImageType
        vkTexInfo.fFormat,                                                   // VkFormat
        { (uint32_t)dimensions.fWidth, (uint32_t)dimensions.fHeight, 1 },    // VkExtent3D
        1,                                                                   // mipLevels
        1,                                                                   // arrayLayers
        VK_SAMPLE_COUNT_1_BIT,                                               // samples
        vkTexInfo.fImageTiling,                                              // VkImageTiling
        vkTexInfo.fImageUsageFlags,                                          // VkImageUsageFlags
        vkTexInfo.fSharingMode,                                              // VkSharingMode
        0,                                                                   // queueFamilyCount
        nullptr,                                                             // pQueueFamilyIndices
        VK_IMAGE_LAYOUT_UNDEFINED,                                           // initialLayout
    };

    VkResult result;
    VkImage image;
    VULKAN_CALL_RESULT(vkContext, result, CreateImage(device, &imageCreateInfo, nullptr, &image));
    if (result != VK_SUCCESS) {
        return {};
    }

    const VkPhysicalDeviceMemoryProperties2& phyDevMemProps =
            vkContext->vulkanCaps().physicalDeviceMemoryProperties2();
    VulkanAlloc alloc;
    if (!AllocateAndBindImageMemory(&alloc, image, phyDevMemProps, hwbProps, hardwareBuffer,
                                    vkContext->interface(), device)) {
        VULKAN_CALL(vkContext->interface(), DestroyImage(device, image, nullptr));
        return {};
    }

    return BackendTextures::MakeVulkan(dimensions,
                                       vkTexInfo,
                                       VK_IMAGE_LAYOUT_UNDEFINED,
                                       VK_QUEUE_FAMILY_FOREIGN_EXT,
                                       image,
                                       alloc);
}

#endif // SK_BUILD_FOR_ANDROID

} // namespace skgpu::graphite
