/*
 * 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/ShaderErrorHandler.h"
#include "include/gpu/graphite/BackendTexture.h"
#include "src/core/SkSLTypeShared.h"
#include "src/gpu/graphite/Buffer.h"
#include "src/gpu/graphite/ComputePipeline.h"
#include "src/gpu/graphite/ContextUtils.h"
#include "src/gpu/graphite/GraphicsPipeline.h"
#include "src/gpu/graphite/PipelineUtils.h"
#include "src/gpu/graphite/RendererProvider.h"
#include "src/gpu/graphite/Sampler.h"
#include "src/gpu/graphite/Texture.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/VulkanGraphicsPipeline.h"
#include "src/gpu/graphite/vk/VulkanGraphiteUtilsPriv.h"
#include "src/gpu/graphite/vk/VulkanSampler.h"
#include "src/gpu/graphite/vk/VulkanSharedContext.h"
#include "src/gpu/graphite/vk/VulkanTexture.h"
#include "src/sksl/SkSLProgramKind.h"
#include "src/sksl/SkSLProgramSettings.h"
#include "src/sksl/ir/SkSLProgram.h"

namespace skgpu::graphite {

VkDescriptorSetLayout VulkanResourceProvider::DescTypeAndCountToVkDescSetLayout(
        const VulkanSharedContext* ctxt,
        SkSpan<DescTypeAndCount> requestedDescriptors) {

    VkDescriptorSetLayout layout;
    skia_private::STArray<kDescriptorTypeCount, VkDescriptorSetLayoutBinding> bindingLayouts;

    for (size_t i = 0, j = 0; i < requestedDescriptors.size(); i++) {
        if (requestedDescriptors[i].count != 0) {
            VkDescriptorSetLayoutBinding* layoutBinding = &bindingLayouts.at(j++);
            memset(layoutBinding, 0, sizeof(VkDescriptorSetLayoutBinding));
            layoutBinding->binding = 0;
            layoutBinding->descriptorType =
                    VulkanDescriptorSet::DsTypeEnumToVkDs(requestedDescriptors[i].type);
            layoutBinding->descriptorCount = requestedDescriptors[i].count;
            // TODO: Obtain layout binding stage flags from visibility (vertex or shader)
            layoutBinding->stageFlags = 0;
            // TODO: Optionally set immutableSamplers here.
            layoutBinding->pImmutableSamplers = nullptr;
        }
    }

    VkDescriptorSetLayoutCreateInfo layoutCreateInfo;
    memset(&layoutCreateInfo, 0, sizeof(VkDescriptorSetLayoutCreateInfo));
    layoutCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
    layoutCreateInfo.pNext = nullptr;
    layoutCreateInfo.flags = 0;
    layoutCreateInfo.bindingCount = bindingLayouts.size();
    layoutCreateInfo.pBindings = &bindingLayouts.front();

    VkResult result;
    VULKAN_CALL_RESULT(ctxt->interface(),
                       result,
                       CreateDescriptorSetLayout(ctxt->device(),
                                                 &layoutCreateInfo,
                                                 nullptr,
                                                 &layout));
    if (result != VK_SUCCESS) {
        SkDebugf("Failed to create VkDescriptorSetLayout\n");
        layout = VK_NULL_HANDLE;
    }
    return layout;
}

VulkanResourceProvider::VulkanResourceProvider(SharedContext* sharedContext,
                                               SingleOwner* singleOwner,
                                               uint32_t recorderID)
        : ResourceProvider(sharedContext, singleOwner, recorderID) {}

VulkanResourceProvider::~VulkanResourceProvider() {}

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

sk_sp<Texture> VulkanResourceProvider::createWrappedTexture(const BackendTexture&) {
    return nullptr;
}

sk_sp<GraphicsPipeline> VulkanResourceProvider::createGraphicsPipeline(
        const RuntimeEffectDictionary* runtimeDict,
        const GraphicsPipelineDesc& pipelineDesc,
        const RenderPassDesc& renderPassDesc) {
    SkSL::Program::Interface vsInterface, fsInterface;
    SkSL::ProgramSettings settings;

    settings.fForceNoRTFlip = true; // TODO: Confirm

    auto compiler = this->skslCompiler();
    ShaderErrorHandler* errorHandler = fSharedContext->caps()->shaderErrorHandler();

    const RenderStep* step =
            fSharedContext->rendererProvider()->lookup(pipelineDesc.renderStepID());

    bool useShadingSsboIndex =
            fSharedContext->caps()->storageBufferPreferred() && step->performsShading();

    const FragSkSLInfo fsSkSLInfo = GetSkSLFS(fSharedContext->caps(),
                                              fSharedContext->shaderCodeDictionary(),
                                              runtimeDict,
                                              step,
                                              pipelineDesc.paintParamsID(),
                                              useShadingSsboIndex,
                                              renderPassDesc.fWriteSwizzle);
    const std::string& fsSkSL = fsSkSLInfo.fSkSL;
    const bool localCoordsNeeded = fsSkSLInfo.fRequiresLocalCoords;

    bool hasFragment = !fsSkSL.empty();
    std::string vsSPIRV, fsSPIRV;
    VkShaderModule fsModule = VK_NULL_HANDLE, vsModule = VK_NULL_HANDLE;

    if (hasFragment) {
        if (!SkSLToSPIRV(compiler,
                         fsSkSL,
                         SkSL::ProgramKind::kGraphiteFragment,
                         settings,
                         &fsSPIRV,
                         &fsInterface,
                         errorHandler)) {
            return {};
        }

        fsModule = createVulkanShaderModule(this->vulkanSharedContext(),
                                            fsSPIRV,
                                            VK_SHADER_STAGE_FRAGMENT_BIT);

        if (!fsModule) {
            return {};
        }
    }

    if (!SkSLToSPIRV(compiler,
                     GetSkSLVS(fSharedContext->caps()->resourceBindingRequirements(),
                               step,
                               useShadingSsboIndex,
                               localCoordsNeeded),
                     SkSL::ProgramKind::kGraphiteVertex,
                     settings,
                     &vsSPIRV,
                     &vsInterface,
                     errorHandler)) {
        return {};
    }

    vsModule = createVulkanShaderModule(this->vulkanSharedContext(),
                                        vsSPIRV,
                                        VK_SHADER_STAGE_VERTEX_BIT);
    if (!vsModule) {
        return {};
    }

    // for now, clean up shader modules
    VULKAN_CALL(this->vulkanSharedContext()->interface(),
                DestroyShaderModule(this->vulkanSharedContext()->device(), vsModule, nullptr));
    VULKAN_CALL(this->vulkanSharedContext()->interface(),
                DestroyShaderModule(this->vulkanSharedContext()->device(), fsModule, nullptr));


    // TODO: Generate depth-stencil state, blend info
    return VulkanGraphicsPipeline::Make(this->vulkanSharedContext());
}

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

sk_sp<Texture> VulkanResourceProvider::createTexture(SkISize size, const TextureInfo& info,
                                                     skgpu::Budgeted budgeted) {
    return VulkanTexture::Make(this->vulkanSharedContext(), size, info, budgeted);
}

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 SkSamplingOptions& samplingOptions,
                                                     SkTileMode xTileMode,
                                                     SkTileMode yTileMode) {
    return VulkanSampler::Make(this->vulkanSharedContext(), samplingOptions, xTileMode, yTileMode);
}

BackendTexture VulkanResourceProvider::onCreateBackendTexture(SkISize dimensions,
                                                              const TextureInfo&) {
    return {};
}

VulkanDescriptorSet* VulkanResourceProvider::findOrCreateDescriptorSet(
        SkSpan<DescTypeAndCount> requestedDescriptors) {
    GraphiteResourceKey key;
    // TODO(nicolettep): Optimize key structure. It is horrendously inefficient but functional.
    // Fow now, have each descriptor type and quantity take up an entire uint32_t, with an
    // additional uint32_t added to include a unique identifier for different descriptor sets that
    // have the same set layout.
    static const int kNum32DataCnt = (kDescriptorTypeCount * 2) + 1;
    static const ResourceType kType = GraphiteResourceKey::GenerateResourceType();

    Resource* descSet = nullptr;
    // Search for available descriptor sets by assembling the last part of the key with a unique set
    // ID (which ranges from 0 to kMaxNumSets - 1). Start the search at 0 and continue until an
    // available set is found.
    // TODO(nicolettep): Explore ways to optimize this traversal.
    for (uint32_t i = 0; i < VulkanDescriptorPool::kMaxNumSets; i++) {
        GraphiteResourceKey::Builder builder(&key, kType, kNum32DataCnt, Shareable::kNo);
        // Assemble the base component of a descriptor set key which is determined by the type and
        // quantity of requested descriptors.
        for (size_t j = 0, k = 0; k < requestedDescriptors.size(); j = j + 2, k++) {
            builder[j+1] = static_cast<uint32_t>(requestedDescriptors[k].type);
            builder[j] = requestedDescriptors[k].count;
        }
        builder[kNum32DataCnt - 1] = i;
        builder.finish();

        if ((descSet = fResourceCache->findAndRefResource(key, skgpu::Budgeted::kNo))) {
            // A non-null resource pointer indicates we have found an available descriptor set.
            return static_cast<VulkanDescriptorSet*>(descSet);
        }
        key.reset();
    }

    // If we did not find an existing avilable desc set, allocate sets with the appropriate layout
    // and add them to the cache.
    auto pool = VulkanDescriptorPool::Make(this->vulkanSharedContext(), requestedDescriptors);
    VkDescriptorSetLayout layout = DescTypeAndCountToVkDescSetLayout(
            this->vulkanSharedContext(),
            requestedDescriptors);

    // Store the key of the first descriptor set so it can be easily accessed later.
    GraphiteResourceKey firstSetKey;
    // Allocate the maximum number of sets so they can be easily accessed as needed from the cache.
    for (int i = 0; i < VulkanDescriptorPool::kMaxNumSets ; i++) {
        GraphiteResourceKey::Builder builder(&key, kType, kNum32DataCnt, Shareable::kNo);
        descSet = VulkanDescriptorSet::Make(this->vulkanSharedContext(), pool, &layout).get();
        // Assemble the base component of a descriptor set key which is determined by the type and
        // quantity of requested descriptors.
        for (size_t j = 0, k = 0; k < requestedDescriptors.size(); j = j + 2, k++) {
            builder[j+1] = static_cast<uint32_t>(requestedDescriptors[k].type);
            builder[j] = requestedDescriptors[k].count;
        }
        builder[kNum32DataCnt - 1] = i;
        builder.finish();
        descSet->setKey(key);
        fResourceCache->insertResource(descSet);
        if (i == 0) {
            firstSetKey = key;
        }
        key.reset();
    }
    descSet = fResourceCache->findAndRefResource(firstSetKey, skgpu::Budgeted::kNo);
    return descSet ? static_cast<VulkanDescriptorSet*>(descSet) : nullptr;
}
} // namespace skgpu::graphite
