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

#ifdef UNSAFE_BUFFERS_BUILD
#    pragma allow_unsafe_libc_calls
#endif

#include "libANGLE/renderer/vulkan/CLContextVk.h"
#include "libANGLE/renderer/vulkan/CLCommandQueueVk.h"
#include "libANGLE/renderer/vulkan/CLEventVk.h"
#include "libANGLE/renderer/vulkan/CLMemoryVk.h"
#include "libANGLE/renderer/vulkan/CLProgramVk.h"
#include "libANGLE/renderer/vulkan/CLSamplerVk.h"
#include "libANGLE/renderer/vulkan/vk_cache_utils.h"
#include "libANGLE/renderer/vulkan/vk_renderer.h"
#include "libANGLE/renderer/vulkan/vk_utils.h"

#include "libANGLE/CLBuffer.h"
#include "libANGLE/CLCommandQueue.h"
#include "libANGLE/CLContext.h"
#include "libANGLE/CLEvent.h"
#include "libANGLE/CLImage.h"
#include "libANGLE/CLProgram.h"
#include "libANGLE/CLSampler.h"
#include "libANGLE/cl_utils.h"

namespace rx
{

CLContextVk::CLContextVk(const cl::Context &context, const cl::DevicePtrs devicePtrs)
    : CLContextImpl(context),
      vk::Context(getPlatform()->getRenderer()),
      mAssociatedDevices(devicePtrs)
{
    mDeviceQueueIndex = mRenderer->getDefaultDeviceQueueIndex();
}

CLContextVk::~CLContextVk()
{
    mMetaDescriptorPool.destroy(getRenderer());
    mDescriptorSetLayoutCache.destroy(getRenderer());
    mPipelineLayoutCache.destroy(getRenderer());
}

void CLContextVk::handleError(VkResult errorCode,
                              const char *file,
                              const char *function,
                              unsigned int line)
{
    ASSERT(errorCode != VK_SUCCESS);

    CLenum clErrorCode = CL_SUCCESS;
    switch (errorCode)
    {
        case VK_ERROR_TOO_MANY_OBJECTS:
        case VK_ERROR_OUT_OF_HOST_MEMORY:
        case VK_ERROR_OUT_OF_DEVICE_MEMORY:
            clErrorCode = CL_OUT_OF_HOST_MEMORY;
            break;
        default:
            clErrorCode = CL_INVALID_OPERATION;
    }
    ERR() << "Internal Vulkan error (" << errorCode << "): " << VulkanResultString(errorCode);
    ERR() << "  CL error (" << clErrorCode << ")";

    if (errorCode == VK_ERROR_DEVICE_LOST)
    {
        handleDeviceLost();
    }
    ANGLE_CL_SET_ERROR(clErrorCode);
}

void CLContextVk::handleDeviceLost() const
{
    // For now just notify the renderer
    getRenderer()->notifyDeviceLost();
}

angle::Result CLContextVk::getDevices(cl::DevicePtrs *devicePtrsOut) const
{
    ASSERT(!mAssociatedDevices.empty());
    *devicePtrsOut = mAssociatedDevices;
    return angle::Result::Continue;
}

angle::Result CLContextVk::createCommandQueue(const cl::CommandQueue &commandQueue,
                                              CLCommandQueueImpl::Ptr *commandQueueOut)
{
    CLCommandQueueVk *queueImpl = new CLCommandQueueVk(commandQueue);
    if (queueImpl == nullptr)
    {
        ANGLE_CL_RETURN_ERROR(CL_OUT_OF_HOST_MEMORY);
    }
    ANGLE_TRY(queueImpl->init());
    *commandQueueOut = CLCommandQueueVk::Ptr(std::move(queueImpl));
    return angle::Result::Continue;
}

angle::Result CLContextVk::createBuffer(const cl::Buffer &buffer,
                                        void *hostPtr,
                                        CLMemoryImpl::Ptr *bufferOut)
{
    CLBufferVk *memory = new (std::nothrow) CLBufferVk(buffer);
    if (memory == nullptr)
    {
        ANGLE_CL_RETURN_ERROR(CL_OUT_OF_HOST_MEMORY);
    }
    ANGLE_TRY(memory->create(hostPtr));
    *bufferOut = CLMemoryImpl::Ptr(memory);
    mAssociatedObjects->mMemories.emplace(buffer.getNative());
    return angle::Result::Continue;
}

angle::Result CLContextVk::createImage(const cl::Image &image,
                                       void *hostPtr,
                                       CLMemoryImpl::Ptr *imageOut)
{
    CLImageVk *memory = new (std::nothrow) CLImageVk(image);
    if (memory == nullptr)
    {
        ANGLE_CL_RETURN_ERROR(CL_OUT_OF_HOST_MEMORY);
    }
    ANGLE_TRY(memory->create(hostPtr));
    *imageOut = CLMemoryImpl::Ptr(memory);
    mAssociatedObjects->mMemories.emplace(image.getNative());
    return angle::Result::Continue;
}

angle::Result CLContextVk::getSupportedImageFormats(cl::MemFlags flags,
                                                    cl::MemObjectType imageType,
                                                    cl_uint numEntries,
                                                    cl_image_format *imageFormats,
                                                    cl_uint *numImageFormats)
{
    // a 1D image buffer is backed by a Vulkan texel buffer (buffer view), so its supported formats
    // must be queried against the buffer feature bits, not the (optimal tiling) image feature bits.
    const bool is1DBuffer = cl::Is1DImageBuffer(imageType);

    VkFormatFeatureFlags requiredFeatures = 0;

    if (flags.intersects(CL_MEM_READ_ONLY) != 0)
    {
        requiredFeatures |= is1DBuffer ? VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT
                                       : VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
    }

    if (flags.intersects(CL_MEM_WRITE_ONLY | CL_MEM_KERNEL_READ_AND_WRITE | CL_MEM_READ_WRITE) != 0)
    {
        requiredFeatures |= is1DBuffer ? VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT
                                       : VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
    }

    std::vector<cl_image_format> finalSupportedFormats;

    for (const auto &clFmt : kSupportedFormats)
    {
        if (cl::IsDepthOrder(clFmt.image_channel_order))
        {
            continue;
        }
        if (clFmt.image_channel_order == CL_A &&
            !getRenderer()->getFeatures().enableAlphaChannelImages.enabled)
        {
            continue;
        }

        const vk::Format &vkFormat        = mRenderer->getFormat(cl::GetImageAngleFormat(clFmt));
        const angle::Format &actualFormat = is1DBuffer
                                                ? vkFormat.getActualBufferFormat()
                                                : vkFormat.getActualImageFormat(vk::SampleOnly);

        if (actualFormat.id != angle::FormatID::NONE)
        {
            const bool hasRequiredFeatures =
                is1DBuffer
                    ? mRenderer->hasBufferFormatFeatureBits(actualFormat.id, requiredFeatures)
                    : mRenderer->hasImageFormatFeatureBits(actualFormat.id, requiredFeatures);

            if (hasRequiredFeatures)
            {
                finalSupportedFormats.push_back(clFmt);
            }
        }
    }

    if (cl::Is2DImage(imageType))
    {
        CLExtensions::SupportedDepthOrderTypes supportedDepthOrderTypesUnion;
        for (const cl::DevicePtr &device : mContext.getDevices())
        {
            // clGetSupportedImageFormats returns a union of image formats supported by all devices
            // in the context
            supportedDepthOrderTypesUnion |= device->getInfo().supportedDepthOrderTypes;
        }
        for (const cl::ImageChannelType imageChannelType : angle::AllEnums<cl::ImageChannelType>())
        {
            if (supportedDepthOrderTypesUnion.test(imageChannelType))
            {
                finalSupportedFormats.push_back({CL_DEPTH, cl::ToCLenum(imageChannelType)});
            }
        }
    }

    if (numImageFormats)
    {
        *numImageFormats = static_cast<cl_uint>(finalSupportedFormats.size());
    }

    if (imageFormats && numEntries)
    {
        const cl_uint finalNumEntries =
            std::min(numEntries, static_cast<cl_uint>(finalSupportedFormats.size()));
        std::copy_n(finalSupportedFormats.begin(), finalNumEntries, imageFormats);
    }

    return angle::Result::Continue;
}

angle::Result CLContextVk::createSampler(const cl::Sampler &sampler, CLSamplerImpl::Ptr *samplerOut)
{
    CLSamplerVk *samplerVk = new (std::nothrow) CLSamplerVk(sampler);
    if (samplerVk == nullptr)
    {
        ANGLE_CL_RETURN_ERROR(CL_OUT_OF_HOST_MEMORY);
    }
    ANGLE_TRY(samplerVk->create());
    *samplerOut = CLSamplerImpl::Ptr(samplerVk);
    return angle::Result::Continue;
}

angle::Result CLContextVk::createProgramWithSource(const cl::Program &program,
                                                   const std::string &source,
                                                   CLProgramImpl::Ptr *programOut)
{
    CLProgramVk *programVk = new (std::nothrow) CLProgramVk(program);
    if (programVk == nullptr)
    {
        ANGLE_CL_RETURN_ERROR(CL_OUT_OF_HOST_MEMORY);
    }
    ANGLE_TRY(programVk->init());
    *programOut = CLProgramImpl::Ptr(std::move(programVk));

    return angle::Result::Continue;
}

angle::Result CLContextVk::createProgramWithIL(const cl::Program &program,
                                               const void *il,
                                               size_t length,
                                               CLProgramImpl::Ptr *programOut)
{
    UNIMPLEMENTED();
    ANGLE_CL_RETURN_ERROR(CL_OUT_OF_RESOURCES);
}

angle::Result CLContextVk::createProgramWithBinary(const cl::Program &program,
                                                   const size_t *lengths,
                                                   const unsigned char **binaries,
                                                   cl_int *binaryStatus,
                                                   CLProgramImpl::Ptr *programOut)
{
    CLProgramVk *programVk = new (std::nothrow) CLProgramVk(program);
    if (programVk == nullptr)
    {
        ANGLE_CL_RETURN_ERROR(CL_OUT_OF_HOST_MEMORY);
    }
    ANGLE_TRY(programVk->init(lengths, binaries, binaryStatus));
    *programOut = CLProgramImpl::Ptr(std::move(programVk));

    return angle::Result::Continue;
}

angle::Result CLContextVk::createProgramWithBuiltInKernels(const cl::Program &program,
                                                           const char *kernel_names,
                                                           CLProgramImpl::Ptr *programOut)
{
    UNIMPLEMENTED();
    ANGLE_CL_RETURN_ERROR(CL_OUT_OF_RESOURCES);
}

angle::Result CLContextVk::linkProgram(const cl::Program &program,
                                       const cl::DevicePtrs &devices,
                                       const char *options,
                                       const cl::ProgramPtrs &inputPrograms,
                                       cl::Program *notify,
                                       CLProgramImpl::Ptr *programOut)
{
    const cl::DevicePtrs &devicePtrs = !devices.empty() ? devices : mContext.getDevices();

    CLProgramVk::Ptr programImpl = CLProgramVk::Ptr(new (std::nothrow) CLProgramVk(program));
    if (programImpl == nullptr)
    {
        ANGLE_CL_RETURN_ERROR(CL_OUT_OF_HOST_MEMORY);
    }
    ANGLE_TRY(programImpl->init());

    cl::DevicePtrs linkDeviceList;
    CLProgramVk::LinkProgramsList linkProgramsList;
    cl::BitField libraryOrObject(CL_PROGRAM_BINARY_TYPE_LIBRARY |
                                 CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT);
    for (const cl::DevicePtr &devicePtr : devicePtrs)
    {
        CLProgramVk::LinkPrograms linkPrograms;
        for (const cl::ProgramPtr &inputProgram : inputPrograms)
        {
            const CLProgramVk::DeviceProgramData *deviceProgramData =
                inputProgram->getImpl<CLProgramVk>().getDeviceProgramData(devicePtr->getNative());

            // Should be valid at this point
            ASSERT(deviceProgramData != nullptr);

            if (libraryOrObject.intersects(deviceProgramData->binaryType))
            {
                linkPrograms.push_back(deviceProgramData);
            }
        }
        if (!linkPrograms.empty())
        {
            linkDeviceList.push_back(devicePtr);
            linkProgramsList.push_back(linkPrograms);
        }
    }

    programImpl->setBuildStatus(linkDeviceList, CL_BUILD_IN_PROGRESS);

    // Perform link
    if (notify)
    {
        std::shared_ptr<angle::WaitableEvent> asyncEvent =
            mContext.getPlatform().getMultiThreadPool()->postWorkerTask(
                std::make_shared<CLAsyncBuildTask>(
                    programImpl.get(), linkDeviceList, std::string(options ? options : ""), "",
                    CLProgramVk::BuildType::LINK, linkProgramsList, notify));
        ASSERT(asyncEvent != nullptr);
    }
    else
    {
        if (!programImpl->buildInternal(linkDeviceList, std::string(options ? options : ""), "",
                                        CLProgramVk::BuildType::LINK, linkProgramsList))
        {
            ANGLE_CL_RETURN_ERROR(CL_LINK_PROGRAM_FAILURE);
        }
    }

    *programOut = std::move(programImpl);
    return angle::Result::Continue;
}

angle::Result CLContextVk::createUserEvent(const cl::Event &event, CLEventImpl::Ptr *eventOut)
{
    *eventOut =
        CLEventImpl::Ptr(new (std::nothrow) CLEventVk(event, cl::ExecutionStatus::Submitted));
    if (*eventOut == nullptr)
    {
        ANGLE_CL_RETURN_ERROR(CL_OUT_OF_HOST_MEMORY);
    }
    return angle::Result::Continue;
}

angle::Result CLContextVk::waitForEvents(const cl::EventPtrs &events)
{
    for (auto &event : events)
    {
        CLEventVk *eventVk = &event.get()->getImpl<CLEventVk>();
        if (eventVk->isUserEvent())
        {
            ANGLE_TRY(eventVk->waitForUserEventStatus());
        }
        else
        {
            // TODO rework this to instead (flush w/ ResourceUse serial wait) once we move away from
            // spawning a submit-thread/Task for flush routine
            // https://anglebug.com/42267107
            ANGLE_TRY(event->getCommandQueue()->finish());
        }
    }

    return angle::Result::Continue;
}

angle::Result CLContextVk::allocateDescriptorSet(
    CLKernelVk *kernelVk,
    DescriptorSetIndex index,
    angle::EnumIterator<DescriptorSetIndex> layoutIndex,
    vk::OutsideRenderPassCommandBufferHelper *computePassCommands)
{
    std::lock_guard<angle::SimpleMutex> lock(mDescriptorSetMutex);

    return kernelVk->allocateDescriptorSet(index, layoutIndex, computePassCommands);
}

angle::Result CLContextVk::initializeDescriptorPools(CLKernelVk *kernelVk)
{
    std::lock_guard<angle::SimpleMutex> lock(mDescriptorSetMutex);

    return kernelVk->initializeDescriptorPools();
}

void CLContextVk::addCommandBufferDiagnostics(const std::string &commandBufferDiagnostics)
{
    mCommandBufferDiagnostics.push_back(commandBufferDiagnostics);
}

void CLContextVk::dumpCommandStreamDiagnostics()
{
    std::ostream &out = std::cout;
    if (mCommandBufferDiagnostics.empty())
    {
        return;
    }

    out << "digraph {\n" << "    node [shape=box fontname=\"Consolas\"]\n";

    for (size_t index = 0; index < mCommandBufferDiagnostics.size(); ++index)
    {
        std::string_view payload = mCommandBufferDiagnostics[index];
        out << "    cb" << index << " [label =\"" << payload << "\"];\n";
    }
    for (size_t index = 0; index < mCommandBufferDiagnostics.size() - 1; ++index)
    {
        out << "    cb" << index << " -> cb" << index + 1 << "\n";
    }
    mCommandBufferDiagnostics.clear();

    out << "}\n";
}

}  // namespace rx
