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

#include "anglebase/no_destructor.h"
#include "common/angle_version_info.h"
#include "common/vulkan/vulkan_icd.h"

#include "libANGLE/renderer/vulkan/CLContextVk.h"
#include "libANGLE/renderer/vulkan/CLDeviceVk.h"
#include "libANGLE/renderer/vulkan/CLPlatformVk.h"
#include "libANGLE/renderer/vulkan/vk_renderer.h"
#include "libANGLE/renderer/vulkan/vk_utils.h"

#include "libANGLE/CLPlatform.h"
#include "libANGLE/cl_utils.h"

#include "vulkan/vulkan_core.h"

namespace rx
{

namespace
{
#if defined(ANGLE_ENABLE_VULKAN_VALIDATION_LAYERS_BY_DEFAULT)
constexpr vk::UseDebugLayers kUseDebugLayers = vk::UseDebugLayers::YesIfAvailable;
#else
constexpr vk::UseDebugLayers kUseDebugLayers = vk::UseDebugLayers::No;
#endif

}  // namespace

angle::Result CLPlatformVk::initBackendRenderer()
{
    ASSERT(mRenderer != nullptr);

    angle::FeatureOverrides featureOverrides;

    // In memory |SizedMRUCache| does not require dual slots, supports zero sized values, and evicts
    // minumum number of old items when storing a new item.
    featureOverrides.disabled.push_back("useDualPipelineBlobCacheSlots");
    featureOverrides.enabled.push_back("useEmptyBlobsToEraseOldPipelineCacheFromBlobCache");
    featureOverrides.enabled.push_back("hasBlobCacheThatEvictsOldItemsFirst");
    featureOverrides.disabled.push_back("verifyPipelineCacheInBlobCache");

    ANGLE_TRY(mRenderer->initialize(this, this, angle::vk::ICD::Default, 0, 0, nullptr, nullptr,
                                    static_cast<VkDriverId>(0), kUseDebugLayers, getWSIExtension(),
                                    getWSILayer(), getWindowSystem(), featureOverrides));

    return angle::Result::Continue;
}

CLPlatformVk::~CLPlatformVk()
{
    ASSERT(mRenderer);
    mRenderer->onDestroy(this);
    delete mRenderer;
}

CLPlatformImpl::Info CLPlatformVk::createInfo() const
{
    NameVersionVector extList = {
        cl_name_version{CL_MAKE_VERSION(1, 0, 0), "cl_khr_icd"},
        cl_name_version{CL_MAKE_VERSION(1, 0, 0), "cl_khr_extended_versioning"}};

    Info info;
    info.name.assign("ANGLE Vulkan");
    info.profile.assign("FULL_PROFILE");
    info.versionStr.assign(GetVersionString());
    info.hostTimerRes = 0u;
    info.version      = GetVersion();

    // check all devices to see which device-extensions can be promoted to platform-extensions
    bool platformSupportsBaseInt64Atomics     = true;
    bool platformSupportsExtendedInt64Atomics = true;
    bool platformSupportsDepthImages          = true;
    CLExtensions::ExternalMemoryHandleBitset supportedHandles;
    supportedHandles.set();  // set support for all types initially
    for (const cl::DevicePtr &platformDevice : mPlatform.getDevices())
    {
        platformSupportsBaseInt64Atomics &= platformDevice->getInfo().khrInt64BaseAtomics;
        platformSupportsExtendedInt64Atomics &= platformDevice->getInfo().khrInt64ExtendedAtomics;
        platformSupportsDepthImages &= platformDevice->getInfo().khrDepthImages;
        supportedHandles &= platformDevice->getInfo().externalMemoryHandleSupport;
    }

    if (info.populateSupportedExternalMemoryHandleTypes(supportedHandles))
    {
        extList.push_back(cl_name_version{CL_MAKE_VERSION(1, 0, 0), "cl_khr_external_memory"});

        // cl_arm_import_memory is layered on top of cl_arm_import_memory
        bool reportBaseArmImportMemString = false;
        if (supportedHandles.test(cl::ExternalMemoryHandle::DmaBuf))
        {
            extList.push_back(
                cl_name_version{CL_MAKE_VERSION(1, 0, 0), "cl_arm_import_memory_dma_buf"});
            reportBaseArmImportMemString = true;
        }
        if (reportBaseArmImportMemString)
        {
            extList.push_back(cl_name_version{CL_MAKE_VERSION(1, 11, 0), "cl_arm_import_memory"});
        }
    }
    if (platformSupportsBaseInt64Atomics)
    {
        extList.push_back(cl_name_version{CL_MAKE_VERSION(1, 0, 0), "cl_khr_int64_base_atomics"});
    }
    if (platformSupportsExtendedInt64Atomics)
    {
        extList.push_back(
            cl_name_version{CL_MAKE_VERSION(1, 0, 0), "cl_khr_int64_extended_atomics"});
    }
    if (platformSupportsDepthImages)
    {
        extList.push_back(
            cl_name_version{.version = CL_MAKE_VERSION(1, 0, 0), .name = "cl_khr_depth_images"});
    }

    info.initializeVersionedExtensions(std::move(extList));

    return info;
}

CLDeviceImpl::CreateDatas CLPlatformVk::createDevices() const
{
    CLDeviceImpl::CreateDatas createDatas;

    // Convert Vk device type to CL equivalent
    cl_device_type type = 0;
    switch (mRenderer->getPhysicalDeviceProperties().deviceType)
    {
        case VK_PHYSICAL_DEVICE_TYPE_CPU:
            type |= CL_DEVICE_TYPE_CPU;
            break;
        case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU:
        case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:
        case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:
            type |= CL_DEVICE_TYPE_GPU;
            break;
        case VK_PHYSICAL_DEVICE_TYPE_OTHER:
        case VK_PHYSICAL_DEVICE_TYPE_MAX_ENUM:
            // The default OpenCL device must not be a CL_DEVICE_TYPE_CUSTOM device.
            // Thus, we override type bitfield to custom only.
            type = CL_DEVICE_TYPE_CUSTOM;
            break;
    }

    createDatas.emplace_back(type, [this](const cl::Device &device) {
        return CLDeviceVk::Ptr(new CLDeviceVk(device, mRenderer));
    });
    return createDatas;
}

angle::Result CLPlatformVk::createContext(cl::Context &context,
                                          const cl::DevicePtrs &devices,
                                          bool userSync,
                                          CLContextImpl::Ptr *contextOut)
{
    *contextOut = CLContextImpl::Ptr(new (std::nothrow) CLContextVk(context, devices));
    if (*contextOut == nullptr)
    {
        ANGLE_CL_RETURN_ERROR(CL_OUT_OF_HOST_MEMORY);
    }
    return angle::Result::Continue;
}

angle::Result CLPlatformVk::createContextFromType(cl::Context &context,
                                                  cl::DeviceType deviceType,
                                                  bool userSync,
                                                  CLContextImpl::Ptr *contextOut)
{
    cl::DevicePtrs devices;
    const bool requestForAll     = deviceType.intersects(CL_DEVICE_TYPE_ALL);
    const bool requestForDefault = deviceType.intersects(CL_DEVICE_TYPE_DEFAULT);

    if (requestForAll)
    {
        devices = mPlatform.getDevices();
    }
    else if (requestForDefault)
    {
        if (!mPlatform.getDevices().empty())
        {
            devices.push_back(mPlatform.getDevices().front());
        }
    }
    else
    {
        for (const auto &platformDevice : mPlatform.getDevices())
        {
            const auto &platformDeviceInfo = platformDevice->getInfo();
            if (platformDeviceInfo.type.intersects(deviceType))
            {
                devices.push_back(platformDevice);
            }
        }
    }

    *contextOut = CLContextImpl::Ptr(new (std::nothrow) CLContextVk(context, devices));
    if (*contextOut == nullptr)
    {
        ANGLE_CL_RETURN_ERROR(CL_OUT_OF_HOST_MEMORY);
    }
    return angle::Result::Continue;
}

angle::Result CLPlatformVk::unloadCompiler()
{
    return angle::Result::Continue;
}

void CLPlatformVk::Initialize(CreateFuncs &createFuncs)
{
    createFuncs.emplace_back([](const cl::Platform &platform) -> CLPlatformImpl::Ptr {
        CLPlatformVk::Ptr platformVk = CLPlatformVk::Ptr(new (std::nothrow) CLPlatformVk(platform));
        if (platformVk == nullptr || IsError(platformVk->initBackendRenderer()))
        {
            return Ptr(nullptr);
        }
        return Ptr(std::move(platformVk));
    });
}

const std::string &CLPlatformVk::GetVersionString()
{
    static const angle::base::NoDestructor<const std::string> sVersion(
        "OpenCL " + std::to_string(CL_VERSION_MAJOR(GetVersion())) + "." +
        std::to_string(CL_VERSION_MINOR(GetVersion())) + " ANGLE " +
        angle::GetANGLEVersionString());
    return *sVersion;
}

CLPlatformVk::CLPlatformVk(const cl::Platform &platform)
    : CLPlatformImpl(platform), vk::ErrorContext(new vk::Renderer()), mBlobCache(1024 * 1024)
{}

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

    std::stringstream errorStream;
    errorStream << "Internal Vulkan error (" << result << "): " << VulkanResultString(result)
                << ", in " << file << ", " << function << ":" << line << ".";
    std::string errorString = errorStream.str();

    if (result == VK_ERROR_DEVICE_LOST)
    {
        WARN() << errorString;
        mRenderer->notifyDeviceLost();
    }
}

angle::NativeWindowSystem CLPlatformVk::getWindowSystem()
{
    // This is an indicator that renderer will be used for OpenCL
    return angle::NativeWindowSystem::NullCompute;
}

const char *CLPlatformVk::getWSIExtension()
{
#if defined(ANGLE_ENABLE_VULKAN)
#    if defined(ANGLE_PLATFORM_LINUX)
#        if defined(ANGLE_USE_GBM)
    return nullptr;
#        elif defined(ANGLE_USE_X11)
    return VK_KHR_XCB_SURFACE_EXTENSION_NAME;
#        elif defined(ANGLE_USE_WAYLAND)
    return VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME;
#        else
    handleError(VK_ERROR_INCOMPATIBLE_DRIVER, __FILE__, __func__, __LINE__);
    return nullptr;
#        endif
#    elif defined(ANGLE_PLATFORM_ANDROID)
    return VK_KHR_ANDROID_SURFACE_EXTENSION_NAME;
#    else
    handleError(VK_ERROR_INCOMPATIBLE_DRIVER, __FILE__, __func__, __LINE__);
    return nullptr;
#    endif
#elif
    UNREACHABLE();
#endif
}

// vk::GlobalOps
void CLPlatformVk::putBlob(const angle::BlobCacheKey &key, const angle::MemoryBuffer &value)
{
    std::scoped_lock<angle::SimpleMutex> lock(mBlobCacheMutex);
    size_t valueSize = value.size();
    mBlobCache.put(key, std::move(const_cast<angle::MemoryBuffer &>(value)), valueSize);
}

bool CLPlatformVk::getBlob(const angle::BlobCacheKey &key, angle::BlobCacheValue *valueOut)
{
    std::scoped_lock<angle::SimpleMutex> lock(mBlobCacheMutex);
    const angle::MemoryBuffer *entry;
    bool result = mBlobCache.get(key, &entry);
    if (result)
    {
        *valueOut = angle::BlobCacheValue(entry->data(), entry->size());
    }
    return result;
}

std::shared_ptr<angle::WaitableEvent> CLPlatformVk::postMultiThreadWorkerTask(
    const std::shared_ptr<angle::Closure> &task)
{
    return mPlatform.getMultiThreadPool()->postWorkerTask(task);
}

void CLPlatformVk::notifyDeviceLost()
{
    return;
}

}  // namespace rx
