// Copyright 2017 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "dawn/native/vulkan/VulkanInfo.h"

#include <cstring>
#include <string>
#include <unordered_map>
#include <utility>

#include "dawn/native/vulkan/AdapterVk.h"
#include "dawn/native/vulkan/BackendVk.h"
#include "dawn/native/vulkan/UtilsVulkan.h"
#include "dawn/native/vulkan/VulkanError.h"

namespace dawn::native::vulkan {

namespace {
ResultOrError<InstanceExtSet> GatherInstanceExtensions(
    const char* layerName,
    const dawn::native::vulkan::VulkanFunctions& vkFunctions,
    const std::unordered_map<std::string, InstanceExt>& knownExts) {
    uint32_t count = 0;
    VkResult vkResult = VkResult::WrapUnsafe(
        vkFunctions.EnumerateInstanceExtensionProperties(layerName, &count, nullptr));
    if (vkResult != VK_SUCCESS && vkResult != VK_INCOMPLETE) {
        return DAWN_INTERNAL_ERROR("vkEnumerateInstanceExtensionProperties");
    }

    std::vector<VkExtensionProperties> extensions(count);
    DAWN_TRY(CheckVkSuccess(
        vkFunctions.EnumerateInstanceExtensionProperties(layerName, &count, extensions.data()),
        "vkEnumerateInstanceExtensionProperties"));

    InstanceExtSet result;
    for (const VkExtensionProperties& extension : extensions) {
        auto it = knownExts.find(extension.extensionName);
        if (it != knownExts.end()) {
            result.set(it->second, true);
        }
    }

    return result;
}

}  // namespace

bool VulkanGlobalKnobs::HasExt(InstanceExt ext) const {
    return extensions[ext];
}

bool VulkanDeviceKnobs::HasExt(DeviceExt ext) const {
    return extensions[ext];
}

ResultOrError<VulkanGlobalInfo> GatherGlobalInfo(const VulkanFunctions& vkFunctions) {
    VulkanGlobalInfo info = {};
    // Gather info on available API version
    {
        info.apiVersion = VK_MAKE_VERSION(1, 0, 0);
        if (vkFunctions.EnumerateInstanceVersion != nullptr) {
            DAWN_TRY(CheckVkSuccess(vkFunctions.EnumerateInstanceVersion(&info.apiVersion),
                                    "vkEnumerateInstanceVersion"));
        }
    }

    // Gather the info about the instance layers
    {
        uint32_t count = 0;
        VkResult result =
            VkResult::WrapUnsafe(vkFunctions.EnumerateInstanceLayerProperties(&count, nullptr));
        // From the Vulkan spec result should be success if there are 0 layers,
        // incomplete otherwise. This means that both values represent a success.
        // This is the same for all Enumarte functions
        if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
            return DAWN_INTERNAL_ERROR("vkEnumerateInstanceLayerProperties");
        }

        std::vector<VkLayerProperties> layersProperties(count);
        DAWN_TRY(CheckVkSuccess(
            vkFunctions.EnumerateInstanceLayerProperties(&count, layersProperties.data()),
            "vkEnumerateInstanceLayerProperties"));

        std::unordered_map<std::string, VulkanLayer> knownLayers = CreateVulkanLayerNameMap();
        for (const VkLayerProperties& layer : layersProperties) {
            auto it = knownLayers.find(layer.layerName);
            if (it != knownLayers.end()) {
                info.layers.set(it->second, true);
            }
        }
    }

    // Gather the info about the instance extensions
    {
        std::unordered_map<std::string, InstanceExt> knownExts = CreateInstanceExtNameMap();

        DAWN_TRY_ASSIGN(info.extensions, GatherInstanceExtensions(nullptr, vkFunctions, knownExts));
        MarkPromotedExtensions(&info.extensions, info.apiVersion);
        info.extensions = EnsureDependencies(info.extensions);

        for (VulkanLayer layer : IterateBitSet(info.layers)) {
            DAWN_TRY_ASSIGN(
                info.layerExtensions[layer],
                GatherInstanceExtensions(GetVulkanLayerInfo(layer).name, vkFunctions, knownExts));
            MarkPromotedExtensions(&info.layerExtensions[layer], info.apiVersion);
            info.layerExtensions[layer] = EnsureDependencies(info.layerExtensions[layer]);
        }
    }

    return std::move(info);
}

ResultOrError<std::vector<VkPhysicalDevice>> GatherPhysicalDevices(
    VkInstance instance,
    const VulkanFunctions& vkFunctions) {
    uint32_t count = 0;
    VkResult result =
        VkResult::WrapUnsafe(vkFunctions.EnumeratePhysicalDevices(instance, &count, nullptr));
    if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
        return DAWN_INTERNAL_ERROR("vkEnumeratePhysicalDevices");
    }

    std::vector<VkPhysicalDevice> physicalDevices(count);
    DAWN_TRY(CheckVkSuccess(
        vkFunctions.EnumeratePhysicalDevices(instance, &count, physicalDevices.data()),
        "vkEnumeratePhysicalDevices"));

    return std::move(physicalDevices);
}

ResultOrError<VulkanDeviceInfo> GatherDeviceInfo(const Adapter& adapter) {
    VulkanDeviceInfo info = {};
    VkPhysicalDevice physicalDevice = adapter.GetPhysicalDevice();
    const VulkanGlobalInfo& globalInfo = adapter.GetVulkanInstance()->GetGlobalInfo();
    const VulkanFunctions& vkFunctions = adapter.GetVulkanInstance()->GetFunctions();

    // Query the device properties first to get the ICD's `apiVersion`
    vkFunctions.GetPhysicalDeviceProperties(physicalDevice, &info.properties);

    // Gather info about device memory.
    {
        VkPhysicalDeviceMemoryProperties memory;
        vkFunctions.GetPhysicalDeviceMemoryProperties(physicalDevice, &memory);

        info.memoryTypes.assign(memory.memoryTypes, memory.memoryTypes + memory.memoryTypeCount);
        info.memoryHeaps.assign(memory.memoryHeaps, memory.memoryHeaps + memory.memoryHeapCount);
    }

    // Gather info about device queue families
    {
        uint32_t count = 0;
        vkFunctions.GetPhysicalDeviceQueueFamilyProperties(physicalDevice, &count, nullptr);

        info.queueFamilies.resize(count);
        vkFunctions.GetPhysicalDeviceQueueFamilyProperties(physicalDevice, &count,
                                                           info.queueFamilies.data());
    }

    // Gather the info about the device layers
    {
        uint32_t count = 0;
        VkResult result = VkResult::WrapUnsafe(
            vkFunctions.EnumerateDeviceLayerProperties(physicalDevice, &count, nullptr));
        if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
            return DAWN_INTERNAL_ERROR("vkEnumerateDeviceLayerProperties");
        }

        info.layers.resize(count);
        DAWN_TRY(CheckVkSuccess(
            vkFunctions.EnumerateDeviceLayerProperties(physicalDevice, &count, info.layers.data()),
            "vkEnumerateDeviceLayerProperties"));
    }

    // Gather the info about the device extensions
    {
        uint32_t count = 0;
        VkResult result = VkResult::WrapUnsafe(vkFunctions.EnumerateDeviceExtensionProperties(
            physicalDevice, nullptr, &count, nullptr));
        if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
            return DAWN_INTERNAL_ERROR("vkEnumerateDeviceExtensionProperties");
        }

        std::vector<VkExtensionProperties> extensionsProperties;
        extensionsProperties.resize(count);
        DAWN_TRY(CheckVkSuccess(vkFunctions.EnumerateDeviceExtensionProperties(
                                    physicalDevice, nullptr, &count, extensionsProperties.data()),
                                "vkEnumerateDeviceExtensionProperties"));

        std::unordered_map<std::string, DeviceExt> knownExts = CreateDeviceExtNameMap();

        for (const VkExtensionProperties& extension : extensionsProperties) {
            auto it = knownExts.find(extension.extensionName);
            if (it != knownExts.end()) {
                info.extensions.set(it->second, true);
            }
        }

        MarkPromotedExtensions(&info.extensions, info.properties.apiVersion);
        info.extensions =
            EnsureDependencies(info.extensions, globalInfo.extensions, info.properties.apiVersion);
    }

    // Gather general and extension features and properties
    //
    // Use vkGetPhysicalDevice{Features,Properties}2 if required to gather information about
    // the extensions. DeviceExt::GetPhysicalDeviceProperties2 is guaranteed to be available
    // because these extensions (transitively) depend on it in `EnsureDependencies`
    VkPhysicalDeviceFeatures2 features2 = {};
    features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
    features2.pNext = nullptr;
    PNextChainBuilder featuresChain(&features2);

    VkPhysicalDeviceProperties2 properties2 = {};
    properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
    features2.pNext = nullptr;
    PNextChainBuilder propertiesChain(&properties2);

    if (info.extensions[DeviceExt::ShaderFloat16Int8]) {
        featuresChain.Add(&info.shaderFloat16Int8Features,
                          VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES_KHR);
    }

    if (info.extensions[DeviceExt::_16BitStorage]) {
        featuresChain.Add(&info._16BitStorageFeatures,
                          VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES);
    }

    if (info.extensions[DeviceExt::SubgroupSizeControl]) {
        featuresChain.Add(&info.subgroupSizeControlFeatures,
                          VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES_EXT);
        propertiesChain.Add(&info.subgroupSizeControlProperties,
                            VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES_EXT);
    }

    if (info.extensions[DeviceExt::DriverProperties]) {
        propertiesChain.Add(&info.driverProperties,
                            VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES);
    }

    // If we have DeviceExt::GetPhysicalDeviceProperties2, use features2 and properties2 so
    // that features no covered by VkPhysicalDevice{Features,Properties} can be queried.
    //
    // Note that info.properties has already been filled at the start of this function to get
    // `apiVersion`.
    ASSERT(info.properties.apiVersion != 0);
    if (info.extensions[DeviceExt::GetPhysicalDeviceProperties2]) {
        vkFunctions.GetPhysicalDeviceProperties2(physicalDevice, &properties2);
        vkFunctions.GetPhysicalDeviceFeatures2(physicalDevice, &features2);
        info.features = features2.features;
    } else {
        ASSERT(features2.pNext == nullptr && properties2.pNext == nullptr);
        vkFunctions.GetPhysicalDeviceFeatures(physicalDevice, &info.features);
    }

    // TODO(cwallez@chromium.org): gather info about formats

    return std::move(info);
}

ResultOrError<VulkanSurfaceInfo> GatherSurfaceInfo(const Adapter& adapter, VkSurfaceKHR surface) {
    VulkanSurfaceInfo info = {};

    VkPhysicalDevice physicalDevice = adapter.GetPhysicalDevice();
    const VulkanFunctions& vkFunctions = adapter.GetVulkanInstance()->GetFunctions();

    // Get the surface capabilities
    DAWN_TRY(CheckVkSuccess(vkFunctions.GetPhysicalDeviceSurfaceCapabilitiesKHR(
                                physicalDevice, surface, &info.capabilities),
                            "vkGetPhysicalDeviceSurfaceCapabilitiesKHR"));

    // Query which queue families support presenting this surface
    {
        size_t nQueueFamilies = adapter.GetDeviceInfo().queueFamilies.size();
        info.supportedQueueFamilies.resize(nQueueFamilies, false);

        for (uint32_t i = 0; i < nQueueFamilies; ++i) {
            VkBool32 supported = VK_FALSE;
            DAWN_TRY(CheckVkSuccess(vkFunctions.GetPhysicalDeviceSurfaceSupportKHR(
                                        physicalDevice, i, surface, &supported),
                                    "vkGetPhysicalDeviceSurfaceSupportKHR"));

            info.supportedQueueFamilies[i] = (supported == VK_TRUE);
        }
    }

    // Gather supported formats
    {
        uint32_t count = 0;
        VkResult result = VkResult::WrapUnsafe(vkFunctions.GetPhysicalDeviceSurfaceFormatsKHR(
            physicalDevice, surface, &count, nullptr));
        if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
            return DAWN_INTERNAL_ERROR("vkGetPhysicalDeviceSurfaceFormatsKHR");
        }

        info.formats.resize(count);
        DAWN_TRY(CheckVkSuccess(vkFunctions.GetPhysicalDeviceSurfaceFormatsKHR(
                                    physicalDevice, surface, &count, info.formats.data()),
                                "vkGetPhysicalDeviceSurfaceFormatsKHR"));
    }

    // Gather supported presents modes
    {
        uint32_t count = 0;
        VkResult result = VkResult::WrapUnsafe(vkFunctions.GetPhysicalDeviceSurfacePresentModesKHR(
            physicalDevice, surface, &count, nullptr));
        if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
            return DAWN_INTERNAL_ERROR("vkGetPhysicalDeviceSurfacePresentModesKHR");
        }

        info.presentModes.resize(count);
        DAWN_TRY(CheckVkSuccess(vkFunctions.GetPhysicalDeviceSurfacePresentModesKHR(
                                    physicalDevice, surface, &count, info.presentModes.data()),
                                "vkGetPhysicalDeviceSurfacePresentModesKHR"));
    }

    return std::move(info);
}

}  // namespace dawn::native::vulkan
