// Copyright 2013 The Flutter 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 <cstdlib>
#include <iostream>
#include <optional>
#include <tuple>
#include <vector>

// Use vulkan.hpp's convenient proc table and resolver.
#define VULKAN_HPP_NO_EXCEPTIONS 1
#define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1
#include "vulkan/vulkan.hpp"
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE

// Convenient reference to vulkan.hpp's global proc table.
auto& d = vk::defaultDispatchLoaderDynamic;

// GLFW needs to be included after Vulkan.
#include "GLFW/glfw3.h"

#include "embedder.h"  // Flutter's Embedder ABI.

static const bool g_enable_validation_layers = true;
// This value is calculated after the window is created.
static double g_pixelRatio = 1.0;
static const size_t kInitialWindowWidth = 800;
static const size_t kInitialWindowHeight = 600;
// Use `VK_PRESENT_MODE_FIFO_KHR` for full vsync (one swap per screen refresh),
// `VK_PRESENT_MODE_MAILBOX_KHR` for continual swap without horizontal tearing,
// or `VK_PRESENT_MODE_IMMEDIATE_KHR` for no vsync.
static const VkPresentModeKHR kPreferredPresentMode = VK_PRESENT_MODE_FIFO_KHR;

static_assert(FLUTTER_ENGINE_VERSION == 1,
              "This Flutter Embedder was authored against the stable Flutter "
              "API at version 1. There has been a serious breakage in the "
              "API. Please read the ChangeLog and take appropriate action "
              "before updating this assertion");

/// Global struct for holding the Window+Vulkan state.
struct {
  GLFWwindow* window;

  std::vector<const char*> enabled_instance_extensions;
  VkInstance instance;
  VkSurfaceKHR surface;

  VkPhysicalDevice physical_device;
  std::vector<const char*> enabled_device_extensions;
  VkDevice device;
  uint32_t queue_family_index;
  VkQueue queue;

  VkCommandPool swapchain_command_pool;
  std::vector<VkCommandBuffer> present_transition_buffers;

  VkFence image_ready_fence;
  VkSemaphore present_transition_semaphore;

  VkSurfaceFormatKHR surface_format;
  VkSwapchainKHR swapchain;
  std::vector<VkImage> swapchain_images;
  uint32_t last_image_index;

  FlutterEngine engine;

  bool resize_pending = false;
} g_state;

void GLFW_ErrorCallback(int error, const char* description) {
  std::cerr << "GLFW Error: (" << error << ") " << description << std::endl;
}

void GLFWcursorPositionCallbackAtPhase(GLFWwindow* window,
                                       FlutterPointerPhase phase,
                                       double x,
                                       double y) {
  FlutterPointerEvent event = {};
  event.struct_size = sizeof(event);
  event.phase = phase;
  event.x = x * g_pixelRatio;
  event.y = y * g_pixelRatio;
  event.timestamp =
      std::chrono::duration_cast<std::chrono::microseconds>(
          std::chrono::high_resolution_clock::now().time_since_epoch())
          .count();
  FlutterEngineSendPointerEvent(g_state.engine, &event, 1);
}

void GLFWcursorPositionCallback(GLFWwindow* window, double x, double y) {
  GLFWcursorPositionCallbackAtPhase(window, FlutterPointerPhase::kMove, x, y);
}

void GLFWmouseButtonCallback(GLFWwindow* window,
                             int key,
                             int action,
                             int mods) {
  if (key == GLFW_MOUSE_BUTTON_1 && action == GLFW_PRESS) {
    double x, y;
    glfwGetCursorPos(window, &x, &y);
    GLFWcursorPositionCallbackAtPhase(window, FlutterPointerPhase::kDown, x, y);
    glfwSetCursorPosCallback(window, GLFWcursorPositionCallback);
  }

  if (key == GLFW_MOUSE_BUTTON_1 && action == GLFW_RELEASE) {
    double x, y;
    glfwGetCursorPos(window, &x, &y);
    GLFWcursorPositionCallbackAtPhase(window, FlutterPointerPhase::kUp, x, y);
    glfwSetCursorPosCallback(window, nullptr);
  }
}

void GLFWKeyCallback(GLFWwindow* window,
                     int key,
                     int scancode,
                     int action,
                     int mods) {
  if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
    glfwSetWindowShouldClose(window, GLFW_TRUE);
  }
}

void GLFWframebufferSizeCallback(GLFWwindow* window, int width, int height) {
  g_state.resize_pending = true;

  FlutterWindowMetricsEvent event = {};
  event.struct_size = sizeof(event);
  event.width = width;
  event.height = height;
  event.pixel_ratio = g_pixelRatio;
  FlutterEngineSendWindowMetricsEvent(g_state.engine, &event);
}

void PrintUsage() {
  std::cerr
      << "usage: embedder_example_vulkan <path to project> <path to icudtl.dat>"
      << std::endl;
}

bool InitializeSwapchain() {
  if (g_state.resize_pending) {
    g_state.resize_pending = false;
    d.vkDestroySwapchainKHR(g_state.device, g_state.swapchain, nullptr);

    d.vkQueueWaitIdle(g_state.queue);
    d.vkResetCommandPool(g_state.device, g_state.swapchain_command_pool,
                         VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
  }

  /// --------------------------------------------------------------------------
  /// Choose an image format that can be presented to the surface, preferring
  /// the common BGRA+sRGB if available.
  /// --------------------------------------------------------------------------

  uint32_t format_count;
  d.vkGetPhysicalDeviceSurfaceFormatsKHR(
      g_state.physical_device, g_state.surface, &format_count, nullptr);
  std::vector<VkSurfaceFormatKHR> formats(format_count);
  d.vkGetPhysicalDeviceSurfaceFormatsKHR(
      g_state.physical_device, g_state.surface, &format_count, formats.data());
  assert(!formats.empty());  // Shouldn't be possible.

  g_state.surface_format = formats[0];
  for (const auto& format : formats) {
    if (format.format == VK_FORMAT_B8G8R8A8_UNORM &&
        format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
      g_state.surface_format = format;
    }
  }

  /// --------------------------------------------------------------------------
  /// Choose the presentable image size that's as close as possible to the
  /// window size.
  /// --------------------------------------------------------------------------

  VkExtent2D extent;

  VkSurfaceCapabilitiesKHR surface_capabilities;
  d.vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
      g_state.physical_device, g_state.surface, &surface_capabilities);

  if (surface_capabilities.currentExtent.width != UINT32_MAX) {
    // If the surface reports a specific extent, we must use it.
    extent = surface_capabilities.currentExtent;
  } else {
    // `glfwGetWindowSize` returns the window size in screen coordinates, so we
    // instead use `glfwGetFramebufferSize` to get the size in pixels in order
    // to properly support high DPI displays.
    int width, height;
    glfwGetFramebufferSize(g_state.window, &width, &height);

    VkExtent2D actual_extent = {
        .width = static_cast<uint32_t>(width),
        .height = static_cast<uint32_t>(height),
    };
    actual_extent.width =
        std::max(surface_capabilities.minImageExtent.width,
                 std::min(surface_capabilities.maxImageExtent.width,
                          actual_extent.width));
    actual_extent.height =
        std::max(surface_capabilities.minImageExtent.height,
                 std::min(surface_capabilities.maxImageExtent.height,
                          actual_extent.height));
  }

  /// --------------------------------------------------------------------------
  /// Choose the present mode.
  /// --------------------------------------------------------------------------

  uint32_t mode_count;
  d.vkGetPhysicalDeviceSurfacePresentModesKHR(
      g_state.physical_device, g_state.surface, &mode_count, nullptr);
  std::vector<VkPresentModeKHR> modes(mode_count);
  d.vkGetPhysicalDeviceSurfacePresentModesKHR(
      g_state.physical_device, g_state.surface, &mode_count, modes.data());
  assert(!formats.empty());  // Shouldn't be possible.

  // If the preferred mode isn't available, just choose the first one.
  VkPresentModeKHR present_mode = modes[0];
  for (const auto& mode : modes) {
    if (mode == kPreferredPresentMode) {
      present_mode = mode;
      break;
    }
  }

  /// --------------------------------------------------------------------------
  /// Create the swapchain.
  /// --------------------------------------------------------------------------

  VkSwapchainCreateInfoKHR info = {
      .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
      .surface = g_state.surface,
      .minImageCount = surface_capabilities.minImageCount + 1,
      .imageFormat = g_state.surface_format.format,
      .imageColorSpace = g_state.surface_format.colorSpace,
      .imageExtent = extent,
      .imageArrayLayers = 1,
      .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
      .imageSharingMode = VK_SHARING_MODE_EXCLUSIVE,
      .queueFamilyIndexCount = 0,
      .pQueueFamilyIndices = nullptr,
      .preTransform = surface_capabilities.currentTransform,
      .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
      .presentMode = present_mode,
      .clipped = true,
  };
  if (d.vkCreateSwapchainKHR(g_state.device, &info, nullptr,
                             &g_state.swapchain) != VK_SUCCESS) {
    return false;
  }

  /// --------------------------------------------------------------------------
  /// Fetch swapchain images.
  /// --------------------------------------------------------------------------

  uint32_t image_count;
  d.vkGetSwapchainImagesKHR(g_state.device, g_state.swapchain, &image_count,
                            nullptr);
  g_state.swapchain_images.resize(image_count);
  d.vkGetSwapchainImagesKHR(g_state.device, g_state.swapchain, &image_count,
                            g_state.swapchain_images.data());

  /// --------------------------------------------------------------------------
  /// Record a command buffer for each of the images to be executed prior to
  /// presenting.
  /// --------------------------------------------------------------------------

  g_state.present_transition_buffers.resize(g_state.swapchain_images.size());

  VkCommandBufferAllocateInfo buffers_info = {
      .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
      .commandPool = g_state.swapchain_command_pool,
      .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
      .commandBufferCount =
          static_cast<uint32_t>(g_state.present_transition_buffers.size()),
  };
  d.vkAllocateCommandBuffers(g_state.device, &buffers_info,
                             g_state.present_transition_buffers.data());

  for (size_t i = 0; i < g_state.swapchain_images.size(); i++) {
    auto image = g_state.swapchain_images[i];
    auto buffer = g_state.present_transition_buffers[i];

    VkCommandBufferBeginInfo begin_info = {
        .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO};
    d.vkBeginCommandBuffer(buffer, &begin_info);

    // Flutter Engine hands back the image after writing to it
    VkImageMemoryBarrier barrier = {
        .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
        .srcAccessMask = 0,
        .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT,
        .oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
        .newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
        .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
        .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
        .image = image,
        .subresourceRange = {
            .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
            .baseMipLevel = 0,
            .levelCount = 1,
            .baseArrayLayer = 0,
            .layerCount = 1,
        }};
    d.vkCmdPipelineBarrier(
        buffer,                                         // commandBuffer
        VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,  // srcStageMask
        VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,           // dstStageMask
        0,                                              // dependencyFlags
        0,                                              // memoryBarrierCount
        nullptr,                                        // pMemoryBarriers
        0,        // bufferMemoryBarrierCount
        nullptr,  // pBufferMemoryBarriers
        1,        // imageMemoryBarrierCount
        &barrier  // pImageMemoryBarriers
    );

    d.vkEndCommandBuffer(buffer);
  }

  return true;  // \o/
}

FlutterVulkanImage FlutterGetNextImageCallback(
    void* user_data,
    const FlutterFrameInfo* frame_info) {
  // If the GLFW framebuffer has been resized, discard the swapchain and create
  // a new one.
  if (g_state.resize_pending) {
    InitializeSwapchain();
  }

  d.vkAcquireNextImageKHR(g_state.device, g_state.swapchain, UINT64_MAX,
                          nullptr, g_state.image_ready_fence,
                          &g_state.last_image_index);

  // Flutter Engine expects the image to be available for transitioning and
  // attaching immediately, and so we need to force a host sync here before
  // returning.
  d.vkWaitForFences(g_state.device, 1, &g_state.image_ready_fence, true,
                    UINT64_MAX);
  d.vkResetFences(g_state.device, 1, &g_state.image_ready_fence);

  return {
      .struct_size = sizeof(FlutterVulkanImage),
      .image = reinterpret_cast<uint64_t>(
          g_state.swapchain_images[g_state.last_image_index]),
      .format = g_state.surface_format.format,
  };
}

bool FlutterPresentCallback(void* user_data, const FlutterVulkanImage* image) {
  VkPipelineStageFlags stage_flags =
      VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
  VkSubmitInfo submit_info = {
      .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
      .waitSemaphoreCount = 0,
      .pWaitSemaphores = nullptr,
      .pWaitDstStageMask = &stage_flags,
      .commandBufferCount = 1,
      .pCommandBuffers =
          &g_state.present_transition_buffers[g_state.last_image_index],
      .signalSemaphoreCount = 1,
      .pSignalSemaphores = &g_state.present_transition_semaphore,
  };
  d.vkQueueSubmit(g_state.queue, 1, &submit_info, nullptr);

  VkPresentInfoKHR present_info = {
      .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
      .waitSemaphoreCount = 1,
      .pWaitSemaphores = &g_state.present_transition_semaphore,
      .swapchainCount = 1,
      .pSwapchains = &g_state.swapchain,
      .pImageIndices = &g_state.last_image_index,
  };
  VkResult result = d.vkQueuePresentKHR(g_state.queue, &present_info);

  // If the swapchain is no longer compatible with the surface, discard the
  // swapchain and create a new one.
  if (result == VK_SUBOPTIMAL_KHR || result == VK_ERROR_OUT_OF_DATE_KHR) {
    InitializeSwapchain();
  }
  d.vkQueueWaitIdle(g_state.queue);

  return result == VK_SUCCESS;
}

void* FlutterGetInstanceProcAddressCallback(
    void* user_data,
    FlutterVulkanInstanceHandle instance,
    const char* procname) {
  auto* proc = glfwGetInstanceProcAddress(
      reinterpret_cast<VkInstance>(instance), procname);
  return reinterpret_cast<void*>(proc);
}

int main(int argc, char** argv) {
  if (argc != 3) {
    PrintUsage();
    return 1;
  }

  std::string project_path = argv[1];
  std::string icudtl_path = argv[2];

  /// --------------------------------------------------------------------------
  /// Create a GLFW window.
  /// --------------------------------------------------------------------------

  {
    if (!glfwInit()) {
      std::cerr << "Failed to initialize GLFW." << std::endl;
      return EXIT_FAILURE;
    }

    glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
    g_state.window = glfwCreateWindow(kInitialWindowWidth, kInitialWindowHeight,
                                      "Flutter", nullptr, nullptr);
    if (!g_state.window) {
      std::cerr << "Failed to create GLFW window." << std::endl;
      return EXIT_FAILURE;
    }

    int framebuffer_width, framebuffer_height;
    glfwGetFramebufferSize(g_state.window, &framebuffer_width,
                           &framebuffer_height);
    g_pixelRatio = framebuffer_width / kInitialWindowWidth;

    glfwSetErrorCallback(GLFW_ErrorCallback);
  }

  /// --------------------------------------------------------------------------
  /// Dynamically load the Vulkan loader with GLFW and use it to populate GLAD's
  /// proc table.
  /// --------------------------------------------------------------------------

  if (!glfwVulkanSupported()) {
    std::cerr << "GLFW was unable to resolve either a Vulkan loader or a "
                 "compatible physical device!"
              << std::endl;
#if defined(__APPLE__)
    std::cerr
        << "NOTE: Apple platforms don't ship with a Vulkan loader or any "
           "Vulkan drivers. Follow this guide to set up a Vulkan loader on "
           "macOS and use the MoltenVK ICD: "
           "https://vulkan.lunarg.com/doc/sdk/latest/mac/getting_started.html"
        << std::endl;
#endif
    return EXIT_FAILURE;
  }

  VULKAN_HPP_DEFAULT_DISPATCHER.init(glfwGetInstanceProcAddress);

  /// --------------------------------------------------------------------------
  /// Create a Vulkan instance.
  /// --------------------------------------------------------------------------

  {
    uint32_t extension_count;
    const char** glfw_extensions =
        glfwGetRequiredInstanceExtensions(&extension_count);
    g_state.enabled_instance_extensions.resize(extension_count);
    memcpy(g_state.enabled_instance_extensions.data(), glfw_extensions,
           extension_count * sizeof(char*));

    if (g_enable_validation_layers) {
      g_state.enabled_instance_extensions.push_back(
          VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
    }

    std::cout << "Enabling " << g_state.enabled_instance_extensions.size()
              << " instance extensions:" << std::endl;
    for (const auto& extension : g_state.enabled_instance_extensions) {
      std::cout << "  - " << extension << std::endl;
    }

    VkApplicationInfo app_info = {
        .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
        .pNext = nullptr,
        .pApplicationName = "Flutter",
        .applicationVersion = VK_MAKE_VERSION(1, 0, 0),
        .pEngineName = "No Engine",
        .engineVersion = VK_MAKE_VERSION(1, 0, 0),
        .apiVersion = VK_MAKE_VERSION(1, 1, 0),
    };
    VkInstanceCreateInfo info = {};
    info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
    info.flags = 0;
    info.pApplicationInfo = &app_info;
    info.enabledExtensionCount = g_state.enabled_instance_extensions.size();
    info.ppEnabledExtensionNames = g_state.enabled_instance_extensions.data();
    if (g_enable_validation_layers) {
      auto available_layers = vk::enumerateInstanceLayerProperties();

      const char* layer = "VK_LAYER_KHRONOS_validation";
      for (const auto& l : available_layers.value) {
        if (strcmp(l.layerName, layer) == 0) {
          info.enabledLayerCount = 1;
          info.ppEnabledLayerNames = &layer;
          break;
        }
      }
    }

    if (d.vkCreateInstance(&info, nullptr, &g_state.instance) != VK_SUCCESS) {
      std::cerr << "Failed to create Vulkan instance." << std::endl;
      return EXIT_FAILURE;
    }
  }

  // Load instance procs.
  VULKAN_HPP_DEFAULT_DISPATCHER.init(g_state.instance);

  /// --------------------------------------------------------------------------
  /// Create the window surface.
  /// --------------------------------------------------------------------------

  if (glfwCreateWindowSurface(g_state.instance, g_state.window, NULL,
                              &g_state.surface) != VK_SUCCESS) {
    std::cerr << "Failed to create window surface." << std::endl;
    return EXIT_FAILURE;
  }

  /// --------------------------------------------------------------------------
  /// Select a compatible physical device.
  /// --------------------------------------------------------------------------

  {
    uint32_t count;
    d.vkEnumeratePhysicalDevices(g_state.instance, &count, nullptr);
    std::vector<VkPhysicalDevice> physical_devices(count);
    d.vkEnumeratePhysicalDevices(g_state.instance, &count,
                                 physical_devices.data());

    std::cout << "Enumerating " << count << " physical device(s)." << std::endl;

    uint32_t selected_score = 0;
    for (const auto& pdevice : physical_devices) {
      VkPhysicalDeviceProperties properties;
      VkPhysicalDeviceFeatures features;
      d.vkGetPhysicalDeviceProperties(pdevice, &properties);
      d.vkGetPhysicalDeviceFeatures(pdevice, &features);

      std::cout << "Checking device: " << properties.deviceName << std::endl;

      uint32_t score = 0;
      std::vector<const char*> supported_extensions;

      uint32_t qfp_count;
      d.vkGetPhysicalDeviceQueueFamilyProperties(pdevice, &qfp_count, nullptr);
      std::vector<VkQueueFamilyProperties> qfp(qfp_count);
      d.vkGetPhysicalDeviceQueueFamilyProperties(pdevice, &qfp_count,
                                                 qfp.data());
      std::optional<uint32_t> graphics_queue_family;
      for (uint32_t i = 0; i < qfp.size(); i++) {
        // Only pick graphics queues that can also present to the surface.
        // Graphics queues that can't present are rare if not nonexistent, but
        // the spec allows for this, so check it anyways.
        VkBool32 surface_present_supported;
        d.vkGetPhysicalDeviceSurfaceSupportKHR(pdevice, i, g_state.surface,
                                               &surface_present_supported);

        if (!graphics_queue_family.has_value() &&
            qfp[i].queueFlags & VK_QUEUE_GRAPHICS_BIT &&
            surface_present_supported) {
          graphics_queue_family = i;
        }
      }

      // Skip physical devices that don't have a graphics queue.
      if (!graphics_queue_family.has_value()) {
        std::cout << "  - Skipping due to no suitable graphics queues."
                  << std::endl;
        continue;
      }

      // Prefer discrete GPUs.
      if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) {
        score += 1 << 30;
      }

      uint32_t extension_count;
      d.vkEnumerateDeviceExtensionProperties(pdevice, nullptr, &extension_count,
                                             nullptr);
      std::vector<VkExtensionProperties> available_extensions(extension_count);
      d.vkEnumerateDeviceExtensionProperties(pdevice, nullptr, &extension_count,
                                             available_extensions.data());

      bool supports_swapchain = false;
      for (const auto& available_extension : available_extensions) {
        if (strcmp(VK_KHR_SWAPCHAIN_EXTENSION_NAME,
                   available_extension.extensionName) == 0) {
          supports_swapchain = true;
          supported_extensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
        }
        // The spec requires VK_KHR_portability_subset be enabled whenever it's
        // available on a device. It's present on compatibility ICDs like
        // MoltenVK.
        else if (strcmp("VK_KHR_portability_subset",
                        available_extension.extensionName) == 0) {
          supported_extensions.push_back("VK_KHR_portability_subset");
        }

        // Prefer GPUs that support VK_KHR_get_memory_requirements2.
        else if (strcmp(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME,
                        available_extension.extensionName) == 0) {
          score += 1 << 29;
          supported_extensions.push_back(
              VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME);
        }
      }

      // Skip physical devices that don't have swapchain support.
      if (!supports_swapchain) {
        std::cout << "  - Skipping due to lack of swapchain support."
                  << std::endl;
        continue;
      }

      // Prefer GPUs with larger max texture sizes.
      score += properties.limits.maxImageDimension2D;

      if (selected_score < score) {
        std::cout << "  - This is the best device so far. Score: 0x" << std::hex
                  << score << std::dec << std::endl;

        selected_score = score;
        g_state.physical_device = pdevice;
        g_state.enabled_device_extensions = supported_extensions;
        g_state.queue_family_index = graphics_queue_family.value_or(
            std::numeric_limits<uint32_t>::max());
      }
    }

    if (g_state.physical_device == nullptr) {
      std::cerr << "Failed to find a compatible Vulkan physical device."
                << std::endl;
      return EXIT_FAILURE;
    }
  }

  /// --------------------------------------------------------------------------
  /// Create a logical device and a graphics queue handle.
  /// --------------------------------------------------------------------------

  std::cout << "Enabling " << g_state.enabled_device_extensions.size()
            << " device extensions:" << std::endl;
  for (const char* extension : g_state.enabled_device_extensions) {
    std::cout << "  - " << extension << std::endl;
  }

  {
    VkPhysicalDeviceFeatures device_features = {};

    VkDeviceQueueCreateInfo graphics_queue = {};
    graphics_queue.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
    graphics_queue.queueFamilyIndex = g_state.queue_family_index;
    graphics_queue.queueCount = 1;
    float priority = 1.0f;
    graphics_queue.pQueuePriorities = &priority;

    VkDeviceCreateInfo device_info = {};
    device_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
    device_info.enabledExtensionCount =
        g_state.enabled_device_extensions.size();
    device_info.ppEnabledExtensionNames =
        g_state.enabled_device_extensions.data();
    device_info.pEnabledFeatures = &device_features;
    device_info.queueCreateInfoCount = 1;
    device_info.pQueueCreateInfos = &graphics_queue;

    if (d.vkCreateDevice(g_state.physical_device, &device_info, nullptr,
                         &g_state.device) != VK_SUCCESS) {
      std::cerr << "Failed to create Vulkan logical device." << std::endl;
      return EXIT_FAILURE;
    }
  }

  d.vkGetDeviceQueue(g_state.device, g_state.queue_family_index, 0,
                     &g_state.queue);

  /// --------------------------------------------------------------------------
  /// Create sync primitives and command pool to use in the render loop
  /// callbacks.
  /// --------------------------------------------------------------------------

  {
    VkFenceCreateInfo f_info = {.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO};
    d.vkCreateFence(g_state.device, &f_info, nullptr,
                    &g_state.image_ready_fence);

    VkSemaphoreCreateInfo s_info = {
        .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO};
    d.vkCreateSemaphore(g_state.device, &s_info, nullptr,
                        &g_state.present_transition_semaphore);

    VkCommandPoolCreateInfo pool_info = {
        .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
        .queueFamilyIndex = g_state.queue_family_index,
    };
    d.vkCreateCommandPool(g_state.device, &pool_info, nullptr,
                          &g_state.swapchain_command_pool);
  }

  /// --------------------------------------------------------------------------
  /// Create swapchain.
  /// --------------------------------------------------------------------------

  if (!InitializeSwapchain()) {
    std::cerr << "Failed to create swapchain." << std::endl;
    return EXIT_FAILURE;
  }

  /// --------------------------------------------------------------------------
  /// Start Flutter Engine.
  /// --------------------------------------------------------------------------

  {
    FlutterRendererConfig config = {};
    config.type = kVulkan;
    config.vulkan.struct_size = sizeof(config.vulkan);
    config.vulkan.version = VK_MAKE_VERSION(1, 1, 0);
    config.vulkan.instance = g_state.instance;
    config.vulkan.physical_device = g_state.physical_device;
    config.vulkan.device = g_state.device;
    config.vulkan.queue_family_index = g_state.queue_family_index;
    config.vulkan.queue = g_state.queue;
    config.vulkan.enabled_instance_extension_count =
        g_state.enabled_instance_extensions.size();
    config.vulkan.enabled_instance_extensions =
        g_state.enabled_instance_extensions.data();
    config.vulkan.enabled_device_extension_count =
        g_state.enabled_device_extensions.size();
    config.vulkan.enabled_device_extensions =
        g_state.enabled_device_extensions.data();
    config.vulkan.get_instance_proc_address_callback =
        FlutterGetInstanceProcAddressCallback;
    config.vulkan.get_next_image_callback = FlutterGetNextImageCallback;
    config.vulkan.present_image_callback = FlutterPresentCallback;

    // This directory is generated by `flutter build bundle`.
    std::string assets_path = project_path + "/build/flutter_assets";
    FlutterProjectArgs args = {
        .struct_size = sizeof(FlutterProjectArgs),
        .assets_path = assets_path.c_str(),
        .icu_data_path =
            icudtl_path.c_str(),  // Find this in your bin/cache directory.
    };
    FlutterEngineResult result =
        FlutterEngineRun(FLUTTER_ENGINE_VERSION, &config, &args, g_state.window,
                         &g_state.engine);
    if (result != kSuccess || g_state.engine == nullptr) {
      std::cerr << "Failed to start Flutter Engine." << std::endl;
      return EXIT_FAILURE;
    }

    // Trigger a FlutterEngineSendWindowMetricsEvent to communicate the initial
    // size of the window.
    int width, height;
    glfwGetFramebufferSize(g_state.window, &width, &height);
    GLFWframebufferSizeCallback(g_state.window, width, height);
    g_state.resize_pending = false;
  }

  /// --------------------------------------------------------------------------
  /// GLFW render loop.
  /// --------------------------------------------------------------------------

  glfwSetKeyCallback(g_state.window, GLFWKeyCallback);
  glfwSetFramebufferSizeCallback(g_state.window, GLFWframebufferSizeCallback);
  glfwSetMouseButtonCallback(g_state.window, GLFWmouseButtonCallback);

  while (!glfwWindowShouldClose(g_state.window)) {
    glfwWaitEvents();
  }

  /// --------------------------------------------------------------------------
  /// Cleanup.
  /// --------------------------------------------------------------------------

  if (FlutterEngineShutdown(g_state.engine) != kSuccess) {
    std::cerr << "Flutter Engine shutdown failed." << std::endl;
  }

  d.vkDestroyCommandPool(g_state.device, g_state.swapchain_command_pool,
                         nullptr);
  d.vkDestroySemaphore(g_state.device, g_state.present_transition_semaphore,
                       nullptr);
  d.vkDestroyFence(g_state.device, g_state.image_ready_fence, nullptr);

  d.vkDestroyDevice(g_state.device, nullptr);
  d.vkDestroySurfaceKHR(g_state.instance, g_state.surface, nullptr);
  d.vkDestroyInstance(g_state.instance, nullptr);

  glfwDestroyWindow(g_state.window);
  glfwTerminate();

  return 0;
}
