//
// Copyright 2021 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.
//
// CLKernelVk.cpp: Implements the class methods for CLKernelVk.
//

#include "libANGLE/renderer/vulkan/CLKernelVk.h"
#include "libANGLE/renderer/vulkan/CLContextVk.h"
#include "libANGLE/renderer/vulkan/CLDeviceVk.h"
#include "libANGLE/renderer/vulkan/CLMemoryVk.h"
#include "libANGLE/renderer/vulkan/CLProgramVk.h"
#include "libANGLE/renderer/vulkan/cl_types.h"
#include "libANGLE/renderer/vulkan/vk_wrapper.h"

#include "libANGLE/CLBuffer.h"
#include "libANGLE/CLContext.h"
#include "libANGLE/CLDevice.h"
#include "libANGLE/CLKernel.h"
#include "libANGLE/CLProgram.h"

#include "spirv/unified1/NonSemanticClspvReflection.h"

#include <algorithm>

namespace rx
{

// Setup the CLKernelArgument with info from ClspvKernelArgument
CLKernelArgument::CLKernelArgument(const CLContextVk *context, const ClspvKernelArgument &info)
    : mCompiledInfo(info), mSize(0), mHandle(nullptr)
{
    mArgInfo.typeQualifier    = mCompiledInfo.info.typeQualifier;
    mArgInfo.addressQualifier = mCompiledInfo.info.addressQualifier;
    mArgInfo.accessQualifier  = mCompiledInfo.info.accessQualifier;
    mArgInfo.typeName         = mCompiledInfo.info.typeName;
    mArgInfo.name             = mCompiledInfo.info.name;
}

cl::Memory *CLKernelArgument::getMemoryHandle() const
{
    if (!mCompiledInfo.used)
    {
        return nullptr;
    }
    return cl::Memory::Cast(static_cast<cl_mem>(mHandle));
}

cl::Sampler *CLKernelArgument::getSamplerHandle() const
{
    ASSERT(mCompiledInfo.type == NonSemanticClspvReflectionArgumentSampler);
    return cl::Sampler::Cast(*static_cast<const cl_sampler *>(mHandle));
}

bool CLKernelArgument::isReadOnly() const
{
    // if not used, can safely assume readonly
    if (!mCompiledInfo.used)
    {
        return true;
    }
    switch (getReflectionType())
    {
        case NonSemanticClspvReflectionArgumentPodUniform:
        case NonSemanticClspvReflectionArgumentUniform:
        case NonSemanticClspvReflectionArgumentPointerUniform:
        case NonSemanticClspvReflectionArgumentUniformTexelBuffer:
        case NonSemanticClspvReflectionConstantDataStorageBuffer:
        {
            return true;
        }
        case NonSemanticClspvReflectionArgumentStorageBuffer:
        case NonSemanticClspvReflectionArgumentStorageTexelBuffer:
        case NonSemanticClspvReflectionArgumentStorageImage:
        case NonSemanticClspvReflectionArgumentSampledImage:
        {
            return mArgInfo.accessQualifier == CL_KERNEL_ARG_ACCESS_READ_ONLY;
        }
        default:
        {
            return false;
        }
    }
}

CLKernelVk::CLKernelVk(const cl::Kernel &kernel, std::string &name, std::string &attributes)
    : CLKernelImpl(kernel),
      mProgram(&kernel.getProgram().getImpl<CLProgramVk>()),
      mContext(&kernel.getProgram().getContext().getImpl<CLContextVk>()),
      mName(name),
      mAttributes(attributes),
      mArgs(),
      mPodBuffer(nullptr),
      mLocalMemoryArgSizes(
          mProgram->getDeviceProgramData(mName.c_str())->getKernelArguments(mName.c_str()).size(),
          0)
{
    mShaderProgramHelper.setShader(gl::ShaderType::Compute,
                                   mKernel.getProgram().getImpl<CLProgramVk>().getShaderModule());
}

CLKernelVk::~CLKernelVk()
{
    mComputePipelineCache.destroy(mContext);
    mShaderProgramHelper.destroy(mContext->getRenderer());
}

angle::Result CLKernelVk::init()
{
    const CLProgramVk::DeviceProgramData *deviceProgramData =
        mProgram->getDeviceProgramData(mName.c_str());

    // Literal sampler handling
    for (const ClspvLiteralSampler &literalSampler :
         deviceProgramData->reflectionData.literalSamplers)
    {
        mDescriptorSetLayoutDescs[DescriptorSetIndex::LiteralSampler].addBinding(
            literalSampler.binding, VK_DESCRIPTOR_TYPE_SAMPLER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
            nullptr);
    }

    // Setup the arguments
    for (auto &clspvArg : deviceProgramData->getKernelArguments(mName.c_str()))
    {
        mArgs.push_back(std::make_shared<CLKernelArgument>(mContext, clspvArg));
    }

    vk::DescriptorSetLayoutDesc &descriptorSetLayoutDesc =
        mDescriptorSetLayoutDescs[DescriptorSetIndex::KernelArguments];
    VkPushConstantRange pcRange = deviceProgramData->pushConstRange;
    size_t podBufferSize        = 0;

    bool podFound = false;
    for (const auto arg : getArgs())
    {
        VkDescriptorType descType = VK_DESCRIPTOR_TYPE_MAX_ENUM;
        switch (arg->getReflectionType())
        {
            case NonSemanticClspvReflectionArgumentStorageBuffer:
                descType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
                break;
            case NonSemanticClspvReflectionArgumentUniform:
                descType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
                break;
            case NonSemanticClspvReflectionArgumentPodUniform:
            case NonSemanticClspvReflectionArgumentPodStorageBuffer:
            case NonSemanticClspvReflectionArgumentPointerUniform:
            {
                uint32_t newPodBufferSize =
                    arg->getPodStorageBufferOffset() + arg->getPodStorageBufferSize();
                podBufferSize = newPodBufferSize > podBufferSize ? newPodBufferSize : podBufferSize;
                if (podFound)
                {
                    continue;
                }
                descType =
                    arg->getReflectionType() == NonSemanticClspvReflectionArgumentPodStorageBuffer
                        ? VK_DESCRIPTOR_TYPE_STORAGE_BUFFER
                        : VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
                podFound = true;
                break;
            }
            case NonSemanticClspvReflectionArgumentPodPushConstant:
            case NonSemanticClspvReflectionArgumentPointerPushConstant:
                // Get existing push constant range and see if we need to update
                if (arg->getPushConstantOffset() + arg->getPushConstantSize() >
                    pcRange.offset + pcRange.size)
                {
                    pcRange.size =
                        arg->getPushConstantOffset() + arg->getPushConstantSize() - pcRange.offset;
                }
                continue;
            case NonSemanticClspvReflectionArgumentSampledImage:
                descType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
                break;
            case NonSemanticClspvReflectionArgumentStorageImage:
                descType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
                break;
            case NonSemanticClspvReflectionArgumentSampler:
                descType = VK_DESCRIPTOR_TYPE_SAMPLER;
                break;
            case NonSemanticClspvReflectionArgumentStorageTexelBuffer:
                descType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
                break;
            case NonSemanticClspvReflectionArgumentUniformTexelBuffer:
                descType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
                break;
            default:
                continue;
        }
        if (descType != VK_DESCRIPTOR_TYPE_MAX_ENUM)
        {
            descriptorSetLayoutDesc.addBinding(arg->getDescriptorBinding(), descType, 1,
                                               VK_SHADER_STAGE_COMPUTE_BIT, nullptr);
        }
    }

    if (podBufferSize > 0)
    {
        mPodBuffer = cl::BufferPtr::Create(
            const_cast<cl::Context &>(mKernel.getProgram().getContext()), cl::Memory::PropArray{},
            cl::MemFlags(CL_MEM_READ_ONLY), podBufferSize, nullptr);
    }

    if (usesPrintf() && !usesPrintfBufferPointerPushConstant())
    {
        mDescriptorSetLayoutDescs[DescriptorSetIndex::Printf].addBinding(
            deviceProgramData->reflectionData.printfBufferStorage.binding,
            VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr);
    }

    // Get pipeline layout from cache (creates if missed)
    // A given kernel need not have resulted in use of all the descriptor sets. Unless the
    // graphicsPipelineLibrary extension is supported, the pipeline layout need all the descriptor
    // set layouts to be valide. So set them up in the order of their occurrence.
    mPipelineLayoutDesc = {};
    for (DescriptorSetIndex index : angle::AllEnums<DescriptorSetIndex>())
    {
        if (!mDescriptorSetLayoutDescs[index].empty())
        {
            mPipelineLayoutDesc.updateDescriptorSetLayout(index, mDescriptorSetLayoutDescs[index]);
        }
    }

    // push constant range size and offset both need to be a multiple of 4
    pcRange.size   = roundUpPow2(pcRange.size, 4u);
    pcRange.offset = roundDownPow2(pcRange.offset, 4u);
    mPipelineLayoutDesc.updatePushConstantRange(pcRange.stageFlags, pcRange.offset, pcRange.size);

    mPodArgumentPushConstants.resize(pcRange.size);

    angle::EnumIterator<DescriptorSetIndex> layoutIndex(DescriptorSetIndex::LiteralSampler);
    for (DescriptorSetIndex index : angle::AllEnums<DescriptorSetIndex>())
    {
        if (!getDescriptorSetLayoutDesc(index).empty())
        {
            ANGLE_CL_IMPL_TRY_ERROR(mContext->getDescriptorSetLayoutCache()->getDescriptorSetLayout(
                                        mContext, getDescriptorSetLayoutDesc(index),
                                        &getDescriptorSetLayouts()[*layoutIndex]),
                                    CL_INVALID_OPERATION);
            ASSERT(getDescriptorSetLayouts()[*layoutIndex]->valid());
            ++layoutIndex;
        }
    }
    ANGLE_CL_IMPL_TRY_ERROR(initPipelineLayout(), CL_INVALID_OPERATION);

    // initialize the descriptor pools
    // descriptor pools are setup as per their indices
    return mContext->initializeDescriptorPools(this);
}

angle::Result CLKernelVk::setArg(cl_uint argIndex, size_t argSize, const void *argValue)
{
    auto &arg = mArgs.at(argIndex);
    if (arg->getUsed())
    {
        switch (arg->getReflectionType())
        {
            case NonSemanticClspvReflectionArgumentPodPushConstant:
            {
                ASSERT(mPodArgumentPushConstants.size() >=
                       arg->getPushConstantSize() + arg->getPushConstantOffset());
                void *handle = &mPodArgumentPushConstants[arg->getPushConstantOffset()];
                size_t handleSize =
                    (argSize > arg->getPushConstantSize() ? arg->getPushConstantSize() : argSize);
                if (argSize > 0 && argValue != nullptr)
                {
                    // Copy the contents since app is free to delete/reassign the contents after
                    ANGLE_UNSAFE_TODO(memcpy(handle, argValue, handleSize));
                }
                arg->set(handleSize, handle);
                break;
            }
            case NonSemanticClspvReflectionArgumentPodUniform:
            case NonSemanticClspvReflectionArgumentPodStorageBuffer:
            {
                ASSERT(mPodBuffer->getSize() >= argSize + arg->getPodUniformOffset());
                if (argSize > 0 && argValue != nullptr)
                {
                    ANGLE_TRY(mPodBuffer->getImpl<CLBufferVk>().copyFrom(
                        argValue, arg->getPodStorageBufferOffset(), argSize));
                }
                break;
            }
            case NonSemanticClspvReflectionArgumentUniform:
            case NonSemanticClspvReflectionArgumentStorageBuffer:
            {
                ASSERT(argSize == sizeof(cl_mem *));
                size_t handleSize = argSize;
                void *handle      = nullptr;
                // Argument can be null ptr
                if (argValue && *static_cast<const cl_mem *>(argValue))
                {
                    handle = *static_cast<const cl_mem *>(argValue);
                }
                arg->set(handleSize, handle);
                break;
            }
            case NonSemanticClspvReflectionArgumentStorageImage:
            case NonSemanticClspvReflectionArgumentSampledImage:
            case NonSemanticClspvReflectionArgumentUniformTexelBuffer:
            case NonSemanticClspvReflectionArgumentStorageTexelBuffer:
            case NonSemanticClspvReflectionArgumentPointerPushConstant:
            case NonSemanticClspvReflectionArgumentPointerUniform:
            {
                ASSERT(argSize == sizeof(cl_mem *));
                cl_mem memHandle = *static_cast<const cl_mem *>(argValue);

                if (cl::Memory::Cast(memHandle)->getFlags().intersects(CL_MEM_READ_ONLY) &&
                    !arg->isReadOnly())
                {
                    WARN() << "The cl_mem argument at index:" << argIndex
                           << " is setup as read-only, and the kernel is writing to it -- This "
                              "could lead to undefined behavior";
                }
                arg->set(argSize, memHandle);
                break;
            }
            case NonSemanticClspvReflectionArgumentWorkgroup:
                ASSERT(arg->getWorkGroupElementSize() != 0);
                mLocalMemoryArgSizes[argIndex] = argSize;
                arg->set(argSize, const_cast<void *>(argValue));
                break;
            default:
                // Just store ptr and size (if we end up here)
                arg->set(argSize, const_cast<void *>(argValue));
                break;
        }
    }

    return angle::Result::Continue;
}

angle::Result CLKernelVk::createInfo(CLKernelImpl::Info *info) const
{
    info->functionName = mName;
    info->attributes   = mAttributes;
    info->numArgs      = static_cast<cl_uint>(mArgs.size());
    for (const auto arg : mArgs)
    {
        info->args.push_back(arg->getArgInfo());
    }

    auto &ctx = mKernel.getProgram().getContext();
    info->workGroups.resize(ctx.getDevices().size());
    const CLProgramVk::DeviceProgramData *deviceProgramData = nullptr;
    for (auto i = 0u; i < ctx.getDevices().size(); ++i)
    {
        auto &workGroup     = info->workGroups[i];
        const auto device   = &ctx.getDevices()[i];
        const auto deviceVk = &device->get()->getImpl<CLDeviceVk>();
        deviceProgramData   = mProgram->getDeviceProgramData(ctx.getDevices()[i]->getNative());
        if (deviceProgramData == nullptr)
        {
            continue;
        }

        // TODO: http://anglebug.com/42267005
        ANGLE_TRY(
            deviceVk->getInfoSizeT(cl::DeviceInfo::MaxWorkGroupSize, &workGroup.workGroupSize));

        // TODO: http://anglebug.com/42267004
        workGroup.privateMemSize = 0;

        workGroup.localMemSize = deviceProgramData->reflectionData.workgroupVariableSize.size;
        workGroup.prefWorkGroupSizeMultiple = deviceVk->getWorkGroupSizeMultiple();
        workGroup.globalWorkSize            = {0, 0, 0};
        if (deviceProgramData->reflectionData.kernelCompileWorkgroupSize.contains(mName))
        {
            workGroup.compileWorkGroupSize = {
                deviceProgramData->reflectionData.kernelCompileWorkgroupSize.at(mName)[0],
                deviceProgramData->reflectionData.kernelCompileWorkgroupSize.at(mName)[1],
                deviceProgramData->reflectionData.kernelCompileWorkgroupSize.at(mName)[2]};
        }
        else
        {
            workGroup.compileWorkGroupSize = {0, 0, 0};
        }

        if (device->get()->getInfo().khrSubgroups)
        {
            workGroup.subGroupSizeForNDRange =
                mContext->getRenderer()->getPhysicalDeviceSubgroupProperties().subgroupSize;
        }
        else
        {
            workGroup.subGroupSizeForNDRange = 0;
        }
    }

    return angle::Result::Continue;
}

angle::Result CLKernelVk::initPipelineLayout()
{
    PipelineLayoutCache *pipelineLayoutCache = mContext->getPipelineLayoutCache();
    return pipelineLayoutCache->getPipelineLayout(mContext, mPipelineLayoutDesc,
                                                  mDescriptorSetLayouts, &mPipelineLayout);
}

angle::Result CLKernelVk::getOrCreateComputePipeline(vk::PipelineCacheAccess *pipelineCache,
                                                     const cl::NDRange &ndrange,
                                                     const cl::Device &device,
                                                     vk::PipelineHelper **pipelineOut)
{
    const CLProgramVk::DeviceProgramData *devProgramData =
        getProgram()->getDeviceProgramData(device.getNative());
    ASSERT(devProgramData != nullptr);

    // Populate program specialization constants (if any)
    uint32_t constantDataOffset = 0;
    std::vector<uint32_t> specConstantData;
    std::vector<VkSpecializationMapEntry> mapEntries;
    for (const auto specConstantUsed : devProgramData->reflectionData.specConstantsUsed)
    {
        switch (specConstantUsed)
        {
            case SpecConstantType::WorkDimension:
                specConstantData.push_back(ndrange.workDimensions);
                break;
            case SpecConstantType::WorkgroupSizeX:
                specConstantData.push_back(ndrange.localWorkSize[0]);
                break;
            case SpecConstantType::WorkgroupSizeY:
                specConstantData.push_back(ndrange.localWorkSize[1]);
                break;
            case SpecConstantType::WorkgroupSizeZ:
                specConstantData.push_back(ndrange.localWorkSize[2]);
                break;
            case SpecConstantType::GlobalOffsetX:
                specConstantData.push_back(ndrange.globalWorkOffset[0]);
                break;
            case SpecConstantType::GlobalOffsetY:
                specConstantData.push_back(ndrange.globalWorkOffset[1]);
                break;
            case SpecConstantType::GlobalOffsetZ:
                specConstantData.push_back(ndrange.globalWorkOffset[2]);
                break;
            case SpecConstantType::SubgroupMaxSize:
            {
                // We should only be here if cl_khr_subgroups is supported
                ASSERT(device.getInfo().khrSubgroups);
                specConstantData.push_back(
                    mContext->getRenderer()->getPhysicalDeviceSubgroupProperties().subgroupSize);
                break;
            }
            default:
                UNIMPLEMENTED();
                continue;
        }
        mapEntries.push_back(VkSpecializationMapEntry{
            .constantID = devProgramData->reflectionData.specConstantIDs[specConstantUsed],
            .offset     = constantDataOffset,
            .size       = sizeof(uint32_t)});
        constantDataOffset += sizeof(uint32_t);
    }
    // Populate kernel specialization constants (if any)
    for (const auto arg : mArgs)
    {
        if (arg->getUsed() &&
            arg->getReflectionType() == NonSemanticClspvReflectionArgumentWorkgroup)
        {
            ASSERT(arg->getWorkGroupElementSize() != 0);

            specConstantData.push_back(
                static_cast<uint32_t>(arg->getSize() / arg->getWorkGroupElementSize()));
            mapEntries.push_back(
                VkSpecializationMapEntry{.constantID = arg->getWorkGroupBufferSpecId(),
                                         .offset     = constantDataOffset,
                                         .size       = sizeof(uint32_t)});
            constantDataOffset += sizeof(uint32_t);
        }
    }
    VkSpecializationInfo computeSpecializationInfo{
        .mapEntryCount = static_cast<uint32_t>(mapEntries.size()),
        .pMapEntries   = mapEntries.data(),
        .dataSize      = specConstantData.size() * sizeof(uint32_t),
        .pData         = specConstantData.data(),
    };

    // Now get or create (on compute pipeline cache miss) compute pipeline and return it
    vk::ComputePipelineOptions options = vk::GetComputePipelineOptions(
        vk::PipelineRobustness::NonRobust, vk::PipelineProtectedAccess::Unprotected);
    return mShaderProgramHelper.getOrCreateComputePipeline(
        mContext, &mComputePipelineCache, pipelineCache, getPipelineLayout(), options,
        PipelineSource::Draw, pipelineOut, mName.c_str(), &computeSpecializationInfo);
}

bool CLKernelVk::usesPrintf() const
{
    return mProgram->getDeviceProgramData(mName.c_str())->getKernelFlags(mName) &
           NonSemanticClspvReflectionMayUsePrintf;
}

bool CLKernelVk::usesPrintfBufferPointerPushConstant() const
{
    return mProgram->getDeviceProgramData(mName.c_str())
        ->reflectionData.pushConstants.contains(
            NonSemanticClspvReflectionPrintfBufferPointerPushConstant);
}

angle::Result CLKernelVk::initializeDescriptorPools()
{
    for (DescriptorSetIndex index : angle::AllEnums<DescriptorSetIndex>())
    {
        if (!mDescriptorSetLayoutDescs[index].empty())
        {
            ANGLE_TRY(mContext->getMetaDescriptorPool().bindCachedDescriptorPool(
                mContext, mDescriptorSetLayoutDescs[index], 1,
                mContext->getDescriptorSetLayoutCache(), &mDynamicDescriptorPools[index]));
        }
    }
    return angle::Result::Continue;
}

angle::Result CLKernelVk::allocateDescriptorSet(
    DescriptorSetIndex index,
    angle::EnumIterator<DescriptorSetIndex> layoutIndex,
    vk::OutsideRenderPassCommandBufferHelper *computePassCommands)
{
    if (mDescriptorSets[index] && mDescriptorSets[index]->valid())
    {
        // Safe to reuse: descriptor set is no longer in use by the GPU.
        if (mContext->getRenderer()->hasResourceUseFinished(
                mDescriptorSets[index]->getResourceUse()))
        {
            // Set DS serial to current CB serial upon reuse.
            mDescriptorSets[index]->setQueueSerial(computePassCommands->getQueueSerial());
            return angle::Result::Continue;
        }
        else
        {
            mDescriptorSets[index].reset();
        }
    }

    if (mDynamicDescriptorPools[index]->valid())
    {
        ANGLE_TRY(mDynamicDescriptorPools[index]->allocateDescriptorSet(
            mContext, *mDescriptorSetLayouts[*layoutIndex], &mDescriptorSets[index]));
        computePassCommands->retainResource(mDescriptorSets[index].get());
    }

    return angle::Result::Continue;
}

cl_ulong CLKernelVk::getLocalMemSizeUsed(const cl::Device &device) const
{
    return getAllArgLocalMemSize() + getCompiledLocalMemSize(device);
}

cl_ulong CLKernelVk::getAllArgLocalMemSize() const
{
    return std::reduce(mLocalMemoryArgSizes.begin(), mLocalMemoryArgSizes.end(), 0,
                       std::plus<size_t>());
}

cl_ulong CLKernelVk::getCompiledLocalMemSize(const cl::Device &device) const
{
    return mProgram->getDeviceProgramData(const_cast<cl_device_id>(device.getNative()))
        ->reflectionData.workgroupVariableSize.size;
}

}  // namespace rx
