// 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 <chrono>
#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(vk::Instance(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;
}
