// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "flutter/vulkan/vulkan_device.h"

#include <limits>
#include <map>
#include <vector>

#include "flutter/vulkan/vulkan_proc_table.h"
#include "flutter/vulkan/vulkan_surface.h"
#include "flutter/vulkan/vulkan_utilities.h"
#include "third_party/skia/include/gpu/vk/GrVkBackendContext.h"
#include "third_party/skia/src/gpu/vk/GrVkUtil.h"

namespace vulkan {

constexpr auto kVulkanInvalidGraphicsQueueIndex =
    std::numeric_limits<uint32_t>::max();

static uint32_t FindGraphicsQueueIndex(
    const std::vector<VkQueueFamilyProperties>& properties) {
  for (uint32_t i = 0, count = static_cast<uint32_t>(properties.size());
       i < count; i++) {
    if (properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
      return i;
    }
  }
  return kVulkanInvalidGraphicsQueueIndex;
}

VulkanDevice::VulkanDevice(VulkanProcTable& p_vk,
                           VulkanHandle<VkPhysicalDevice> physical_device)
    : vk(p_vk),
      physical_device_(std::move(physical_device)),
      graphics_queue_index_(std::numeric_limits<uint32_t>::max()),
      valid_(false) {
  if (!physical_device_ || !vk.AreInstanceProcsSetup()) {
    return;
  }

  graphics_queue_index_ = FindGraphicsQueueIndex(GetQueueFamilyProperties());

  if (graphics_queue_index_ == kVulkanInvalidGraphicsQueueIndex) {
    FXL_DLOG(INFO) << "Could not find the graphics queue index.";
    return;
  }

  const float priorities[1] = {1.0f};

  const VkDeviceQueueCreateInfo queue_create = {
      .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
      .pNext = nullptr,
      .flags = 0,
      .queueFamilyIndex = graphics_queue_index_,
      .queueCount = 1,
      .pQueuePriorities = priorities,
  };

  const char* extensions[] = {
    VK_KHR_SWAPCHAIN_EXTENSION_NAME,
#if OS_FUCHSIA
    VK_GOOGLE_EXTERNAL_MEMORY_MAGMA_EXTENSION_NAME,
    VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME,
    VK_KHR_EXTERNAL_SEMAPHORE_FUCHSIA_EXTENSION_NAME,
#endif
  };

  auto enabled_layers = DeviceLayersToEnable(vk, physical_device_);

  const char* layers[enabled_layers.size()];

  for (size_t i = 0; i < enabled_layers.size(); i++) {
    layers[i] = enabled_layers[i].c_str();
  }

  const VkDeviceCreateInfo create_info = {
      .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
      .pNext = nullptr,
      .flags = 0,
      .queueCreateInfoCount = 1,
      .pQueueCreateInfos = &queue_create,
      .enabledLayerCount = static_cast<uint32_t>(enabled_layers.size()),
      .ppEnabledLayerNames = layers,
      .enabledExtensionCount = sizeof(extensions) / sizeof(const char*),
      .ppEnabledExtensionNames = extensions,
      .pEnabledFeatures = nullptr,
  };

  VkDevice device = VK_NULL_HANDLE;

  if (VK_CALL_LOG_ERROR(vk.CreateDevice(physical_device_, &create_info, nullptr,
                                        &device)) != VK_SUCCESS) {
    FXL_DLOG(INFO) << "Could not create device.";
    return;
  }

  device_ = {device,
             [this](VkDevice device) { vk.DestroyDevice(device, nullptr); }};

  if (!vk.SetupDeviceProcAddresses(device_)) {
    FXL_DLOG(INFO) << "Could not setup device proc addresses.";
    return;
  }

  VkQueue queue = VK_NULL_HANDLE;

  vk.GetDeviceQueue(device_, graphics_queue_index_, 0, &queue);

  if (queue == VK_NULL_HANDLE) {
    FXL_DLOG(INFO) << "Could not get the device queue handle.";
    return;
  }

  queue_ = queue;

  const VkCommandPoolCreateInfo command_pool_create_info = {
      .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
      .pNext = nullptr,
      .flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
      .queueFamilyIndex = 0,
  };

  VkCommandPool command_pool = VK_NULL_HANDLE;
  if (VK_CALL_LOG_ERROR(vk.CreateCommandPool(device_, &command_pool_create_info,
                                             nullptr, &command_pool)) !=
      VK_SUCCESS) {
    FXL_DLOG(INFO) << "Could not create the command pool.";
    return;
  }

  command_pool_ = {command_pool, [this](VkCommandPool pool) {
                     vk.DestroyCommandPool(device_, pool, nullptr);
                   }};

  valid_ = true;
}

VulkanDevice::~VulkanDevice() {
  FXL_ALLOW_UNUSED_LOCAL(WaitIdle());
}

bool VulkanDevice::IsValid() const {
  return valid_;
}

bool VulkanDevice::WaitIdle() const {
  return VK_CALL_LOG_ERROR(vk.DeviceWaitIdle(device_)) == VK_SUCCESS;
}

const VulkanHandle<VkDevice>& VulkanDevice::GetHandle() const {
  return device_;
}

void VulkanDevice::ReleaseDeviceOwnership() {
  device_.ReleaseOwnership();
}

const VulkanHandle<VkPhysicalDevice>& VulkanDevice::GetPhysicalDeviceHandle()
    const {
  return physical_device_;
}

const VulkanHandle<VkQueue>& VulkanDevice::GetQueueHandle() const {
  return queue_;
}

const VulkanHandle<VkCommandPool>& VulkanDevice::GetCommandPool() const {
  return command_pool_;
}

uint32_t VulkanDevice::GetGraphicsQueueIndex() const {
  return graphics_queue_index_;
}

bool VulkanDevice::GetSurfaceCapabilities(
    const VulkanSurface& surface,
    VkSurfaceCapabilitiesKHR* capabilities) const {
  if (!surface.IsValid() || capabilities == nullptr) {
    return false;
  }

  bool success =
      VK_CALL_LOG_ERROR(vk.GetPhysicalDeviceSurfaceCapabilitiesKHR(
          physical_device_, surface.Handle(), capabilities)) == VK_SUCCESS;

  if (!success) {
    return false;
  }

  // Check if the physical device surface capabilities are valid. If so, there
  // is nothing more to do.
  if (capabilities->currentExtent.width != 0xFFFFFFFF &&
      capabilities->currentExtent.height != 0xFFFFFFFF) {
    return true;
  }

  // Ask the native surface for its size as a fallback.
  SkISize size = surface.GetSize();

  if (size.width() == 0 || size.height() == 0) {
    return false;
  }

  capabilities->currentExtent.width = size.width();
  capabilities->currentExtent.height = size.height();
  return true;
}

bool VulkanDevice::GetPhysicalDeviceFeatures(
    VkPhysicalDeviceFeatures* features) const {
  if (features == nullptr || !physical_device_) {
    return false;
  }
  vk.GetPhysicalDeviceFeatures(physical_device_, features);
  return true;
}

bool VulkanDevice::GetPhysicalDeviceFeaturesSkia(uint32_t* sk_features) const {
  if (sk_features == nullptr) {
    return false;
  }

  VkPhysicalDeviceFeatures features;

  if (!GetPhysicalDeviceFeatures(&features)) {
    return false;
  }

  uint32_t flags = 0;

  if (features.geometryShader) {
    flags |= kGeometryShader_GrVkFeatureFlag;
  }
  if (features.dualSrcBlend) {
    flags |= kDualSrcBlend_GrVkFeatureFlag;
  }
  if (features.sampleRateShading) {
    flags |= kSampleRateShading_GrVkFeatureFlag;
  }

  *sk_features = flags;
  return true;
}

std::vector<VkQueueFamilyProperties> VulkanDevice::GetQueueFamilyProperties()
    const {
  uint32_t count = 0;

  vk.GetPhysicalDeviceQueueFamilyProperties(physical_device_, &count, nullptr);

  std::vector<VkQueueFamilyProperties> properties;
  properties.resize(count, {});

  vk.GetPhysicalDeviceQueueFamilyProperties(physical_device_, &count,
                                            properties.data());

  return properties;
}

bool VulkanDevice::ChooseSurfaceFormat(const VulkanSurface& surface,
                                       VkSurfaceFormatKHR* format) const {
  if (!surface.IsValid() || format == nullptr) {
    return false;
  }

  uint32_t format_count = 0;
  if (VK_CALL_LOG_ERROR(vk.GetPhysicalDeviceSurfaceFormatsKHR(
          physical_device_, surface.Handle(), &format_count, nullptr)) !=
      VK_SUCCESS) {
    return false;
  }

  if (format_count == 0) {
    return false;
  }

  VkSurfaceFormatKHR formats[format_count];
  if (VK_CALL_LOG_ERROR(vk.GetPhysicalDeviceSurfaceFormatsKHR(
          physical_device_, surface.Handle(), &format_count, formats)) !=
      VK_SUCCESS) {
    return false;
  }

  std::map<VkFormat, VkSurfaceFormatKHR> supported_formats;

  for (uint32_t i = 0; i < format_count; i++) {
    GrPixelConfig pixel_config = GrVkFormatToPixelConfig(formats[i].format);
    if (pixel_config != kUnknown_GrPixelConfig) {
      supported_formats[formats[i].format] = formats[i];
    }
  }

  if (supported_formats.size() == 0) {
    return false;
  }

  const std::vector<VkFormat> desired_formats = {
      VK_FORMAT_R8G8B8A8_SRGB,        // kSRGBA_8888_GrPixelConfig
      VK_FORMAT_B8G8R8A8_SRGB,        // kSBGRA_8888_GrPixelConfig
      VK_FORMAT_R16G16B16A16_SFLOAT,  // kRGBA_half_GrPixelConfig
      VK_FORMAT_R8G8B8A8_UNORM,       // kRGBA_8888_GrPixelConfig
      VK_FORMAT_B8G8R8A8_UNORM,       // kBGRA_8888_GrPixelConfig
  };

  // Try to find the first supported format in the list of desired formats.
  for (VkFormat current_format : desired_formats) {
    auto found = supported_formats.find(current_format);
    if (found != supported_formats.end()) {
      *format = found->second;
      return true;
    }
  }

  // None of the desired formats were supported. Return the first supported
  // format even if we don't like it all that much (it has already returned true
  // for GrVkFormatToPixelConfig).
  *format = supported_formats.begin()->second;
  return true;
}

bool VulkanDevice::ChoosePresentMode(const VulkanSurface& surface,
                                     VkPresentModeKHR* present_mode) const {
  if (!surface.IsValid() || present_mode == nullptr) {
    return false;
  }

  // https://github.com/LunarG/VulkanSamples/issues/98 indicates that
  // VK_PRESENT_MODE_FIFO_KHR is preferable on mobile platforms. The problems
  // mentioned in the ticket w.r.t the application being faster that the refresh
  // rate of the screen should not be faced by any Flutter platforms as they are
  // powered by Vsync pulses instead of depending the the submit to block.
  // However, for platforms that don't have VSync providers setup, it is better
  // to fall back to FIFO. For platforms that do have VSync providers, there
  // should be little difference. In case there is a need for a mode other than
  // FIFO, availability checks must be performed here before returning the
  // result. FIFO is always present.
  *present_mode = VK_PRESENT_MODE_FIFO_KHR;
  return true;
}

bool VulkanDevice::QueueSubmit(
    std::vector<VkPipelineStageFlags> wait_dest_pipeline_stages,
    const std::vector<VkSemaphore>& wait_semaphores,
    const std::vector<VkSemaphore>& signal_semaphores,
    const std::vector<VkCommandBuffer>& command_buffers,
    const VulkanHandle<VkFence>& fence) const {
  if (wait_semaphores.size() != wait_dest_pipeline_stages.size()) {
    return false;
  }

  const VkSubmitInfo submit_info = {
      .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
      .pNext = nullptr,
      .waitSemaphoreCount = static_cast<uint32_t>(wait_semaphores.size()),
      .pWaitSemaphores = wait_semaphores.data(),
      .pWaitDstStageMask = wait_dest_pipeline_stages.data(),
      .commandBufferCount = static_cast<uint32_t>(command_buffers.size()),
      .pCommandBuffers = command_buffers.data(),
      .signalSemaphoreCount = static_cast<uint32_t>(signal_semaphores.size()),
      .pSignalSemaphores = signal_semaphores.data(),
  };

  if (VK_CALL_LOG_ERROR(vk.QueueSubmit(queue_, 1, &submit_info, fence)) !=
      VK_SUCCESS) {
    return false;
  }

  return true;
}

}  // namespace vulkan
