Index: Vulkan.cpp
===================================================================
--- Vulkan.cpp	(revision 57d43d021f973604403220624950c82a9c67ae6e)
+++ Vulkan.cpp	(revision c205c3a8a3acc0125b6b0cea26e2879f383b1889)
@@ -1,13 +1,5 @@
-
-////////////////////////////////////////////////////////////
-// Headers
-////////////////////////////////////////////////////////////
-#define GLAD_VULKAN_IMPLEMENTATION
-#include "vulkan.h"
-
-// Include graphics because we use sf::Image for loading images
-#include <SFML/Graphics.hpp>
-
-#include <SFML/Window.hpp>
+#include <vulkan/vulkan.h>
+
+#include <iostream>
 #include <vector>
 #include <limits>
@@ -15,16 +7,24 @@
 #include <cmath>
 
-
-////////////////////////////////////////////////////////////
-// Helper functions
-////////////////////////////////////////////////////////////
-namespace
-{
+#include <SFML/Window.hpp>
+#include <SFML/Graphics.hpp> // Include graphics because we use sf::Image for loading images
+
+#include "vulkan-utils-new.hpp"
+
+using namespace std;
+
+namespace {
+
+   #ifdef NDEBUG
+      const bool ENABLE_VALIDATION_LAYERS = false;
+   #else
+      const bool ENABLE_VALIDATION_LAYERS = true;
+   #endif
+
    typedef float Vec3[3];
    typedef float Matrix[4][4];
 
    // Multiply 2 matrices
-   void matrixMultiply(Matrix& result, const Matrix& left, const Matrix& right)
-   {
+   void matrixMultiply(Matrix& result, const Matrix& left, const Matrix& right) {
       Matrix temp;
 
@@ -39,6 +39,5 @@
 
    // Rotate a matrix around the x-axis
-   void matrixRotateX(Matrix& result, float angle)
-   {
+   void matrixRotateX(Matrix& result, float angle) {
       Matrix matrix = {
           {1.f,   0.f,             0.f,             0.f},
@@ -52,6 +51,5 @@
 
    // Rotate a matrix around the y-axis
-   void matrixRotateY(Matrix& result, float angle)
-   {
+   void matrixRotateY(Matrix& result, float angle) {
       Matrix matrix = {
           { std::cos(angle), 0.f, std::sin(angle), 0.f},
@@ -65,6 +63,5 @@
 
    // Rotate a matrix around the z-axis
-   void matrixRotateZ(Matrix& result, float angle)
-   {
+   void matrixRotateZ(Matrix& result, float angle) {
       Matrix matrix = {
           { std::cos(angle), std::sin(angle), 0.f, 0.f},
@@ -78,6 +75,5 @@
 
    // Construct a lookat view matrix
-   void matrixLookAt(Matrix& result, const Vec3& eye, const Vec3& center, const Vec3& up)
-   {
+   void matrixLookAt(Matrix& result, const Vec3& eye, const Vec3& center, const Vec3& up) {
       // Forward-looking vector
       Vec3 forward = {
@@ -90,6 +86,7 @@
       float factor = 1.0f / std::sqrt(forward[0] * forward[0] + forward[1] * forward[1] + forward[2] * forward[2]);
 
-      for (int i = 0; i < 3; i++)
+      for (int i = 0; i < 3; i++) {
          forward[i] = forward[i] * factor;
+      }
 
       // Side vector (Forward cross product Up)
@@ -128,6 +125,5 @@
 
    // Construct a perspective projection matrix
-   void matrixPerspective(Matrix& result, float fov, float aspect, float nearPlane, float farPlane)
-   {
+   void matrixPerspective(Matrix& result, float fov, float aspect, float nearPlane, float farPlane) {
       const float a = 1.f / std::tan(fov / 2.f);
 
@@ -155,19 +151,14 @@
    // Clamp a value between low and high values
    template<typename T>
-   T clamp(T value, T low, T high)
-   {
+   T clamp(T value, T low, T high) {
       return (value <= low) ? low : ((value >= high) ? high : value);
    }
 
-   // Helper function we pass to GLAD to load Vulkan functions via SFML
-   GLADapiproc getVulkanFunction(const char* name)
-   {
-      return reinterpret_cast<GLADapiproc>(sf::Vulkan::getFunction(name));
-   }
-
-   // Debug we pass to Vulkan to call when it detects warnings or errors
-   VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(VkDebugReportFlagsEXT, VkDebugReportObjectTypeEXT, uint64_t, size_t, int32_t, const char*, const char* pMessage, void*)
-   {
-      sf::err() << pMessage << std::endl;
+   VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(
+         VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
+         VkDebugUtilsMessageTypeFlagsEXT messageType,
+         const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
+         void* pUserData) {
+      cerr << "validation layer: " << pCallbackData->pMessage << endl;
 
       return VK_FALSE;
@@ -176,9 +167,5 @@
 
 
-////////////////////////////////////////////////////////////
-// VulkanExample class
-////////////////////////////////////////////////////////////
-class VulkanExample
-{
+class VulkanExample {
 public:
    // Constructor
@@ -190,5 +177,4 @@
       swapchainOutOfDate(false),
       instance(0),
-      debugReportCallback(0),
       surface(0),
       gpu(0),
@@ -220,7 +206,12 @@
       descriptorPool(0)
    {
+      const vector<const char*> validationLayers = {
+         "VK_LAYER_KHRONOS_validation",
+         "VK_LAYER_LUNARG_monitor"                    // This should show the FPS in the title bar
+      };
+
       // Vulkan setup procedure
-      if (vulkanAvailable) setupInstance();
-      if (vulkanAvailable) setupDebugReportCallback();
+      if (vulkanAvailable) setupInstance(validationLayers);
+      if (vulkanAvailable) setupDebugMessenger();
       if (vulkanAvailable) setupSurface();
       if (vulkanAvailable) setupPhysicalDevice();
@@ -257,9 +248,9 @@
 
    // Destructor
-   ~VulkanExample()
-   {
+   ~VulkanExample() {
       // Wait until there are no pending frames
-      if (device)
+      if (device) {
          vkDeviceWaitIdle(device);
+      }
 
       // Teardown swapchain
@@ -327,6 +318,7 @@
          vkDestroySurfaceKHR(instance, surface, 0);
 
-      if (debugReportCallback)
-         vkDestroyDebugReportCallbackEXT(instance, debugReportCallback, 0);
+      if (ENABLE_VALIDATION_LAYERS) {
+         VulkanUtilsNew::destroyDebugUtilsMessengerEXT(instance, debugMessenger, nullptr);
+      }
 
       if (instance)
@@ -335,6 +327,5 @@
 
    // Cleanup swapchain
-   void cleanupSwapchain()
-   {
+   void cleanupSwapchain() {
       // Swapchain teardown procedure
       for (std::size_t i = 0; i < fences.size(); i++)
@@ -351,6 +342,7 @@
       swapchainFramebuffers.clear();
 
-      if (graphicsPipeline)
+      if (graphicsPipeline) {
          vkDestroyPipeline(device, graphicsPipeline, 0);
+      }
 
       if (renderPass)
@@ -374,11 +366,13 @@
       swapchainImageViews.clear();
 
-      if (swapchain)
+      if (swapchain) { 
          vkDestroySwapchainKHR(device, swapchain, 0);
+      }
    }
 
    // Cleanup and recreate swapchain
-   void recreateSwapchain()
-   {
+   void recreateSwapchain() {
+      cout << "Recreating pipeline..." << endl;
+
       // Wait until there are no pending frames
       vkDeviceWaitIdle(device);
@@ -401,63 +395,14 @@
 
    // Setup Vulkan instance
-   void setupInstance()
-   {
-      // Load bootstrap entry points
-      gladLoadVulkan(0, getVulkanFunction);
-
-      if (!vkCreateInstance)
-      {
-         vulkanAvailable = false;
-         return;
-      }
-
-      // Retrieve the available instance layers
-      uint32_t objectCount = 0;
-
-      std::vector<VkLayerProperties> layers;
-
-      if (vkEnumerateInstanceLayerProperties(&objectCount, 0) != VK_SUCCESS)
-      {
-         vulkanAvailable = false;
-         return;
-      }
-
-      layers.resize(objectCount);
-
-      if (vkEnumerateInstanceLayerProperties(&objectCount, &layers[0]) != VK_SUCCESS)
-      {
-         vulkanAvailable = false;
-         return;
-      }
-
-      // Activate the layers we are interested in
-      std::vector<const char*> validationLayers;
-
-      for (std::size_t i = 0; i < layers.size(); i++)
-      {
-         // VK_LAYER_LUNARG_standard_validation, meta-layer for the following layers:
-         // -- VK_LAYER_GOOGLE_threading
-         // -- VK_LAYER_LUNARG_parameter_validation
-         // -- VK_LAYER_LUNARG_device_limits
-         // -- VK_LAYER_LUNARG_object_tracker
-         // -- VK_LAYER_LUNARG_image
-         // -- VK_LAYER_LUNARG_core_validation
-         // -- VK_LAYER_LUNARG_swapchain
-         // -- VK_LAYER_GOOGLE_unique_objects
-         // These layers perform error checking and warn about bad or sub-optimal Vulkan API usage
-         // VK_LAYER_LUNARG_monitor appends an FPS counter to the window title
-         if (!std::strcmp(layers[i].layerName, "VK_LAYER_LUNARG_standard_validation"))
-         {
-            validationLayers.push_back("VK_LAYER_LUNARG_standard_validation");
-         }
-         else if (!std::strcmp(layers[i].layerName, "VK_LAYER_LUNARG_monitor"))
-         {
-            validationLayers.push_back("VK_LAYER_LUNARG_monitor");
-         }
+   void setupInstance(const vector<const char*>& validationLayers) {
+      if (ENABLE_VALIDATION_LAYERS && !VulkanUtilsNew::checkValidationLayerSupport(validationLayers)) {
+         throw runtime_error("validation layers requested, but not available!");
       }
 
       // Retrieve the extensions we need to enable in order to use Vulkan with SFML
       std::vector<const char*> requiredExtentions = sf::Vulkan::getGraphicsRequiredInstanceExtensions();
-      requiredExtentions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
+      if (ENABLE_VALIDATION_LAYERS) {
+         requiredExtentions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
+      }
 
       // Register our application information
@@ -473,52 +418,44 @@
       instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
       instanceCreateInfo.pApplicationInfo = &applicationInfo;
-      instanceCreateInfo.enabledLayerCount = validationLayers.size();
-      instanceCreateInfo.ppEnabledLayerNames = &validationLayers[0];
+
       instanceCreateInfo.enabledExtensionCount = requiredExtentions.size();
-      instanceCreateInfo.ppEnabledExtensionNames = &requiredExtentions[0];
-
-      // Try to create a Vulkan instance with debug report enabled
-      VkResult result = vkCreateInstance(&instanceCreateInfo, 0, &instance);
-
-      // If an extension is missing, try disabling debug report
-      if (result == VK_ERROR_EXTENSION_NOT_PRESENT)
-      {
-         requiredExtentions.pop_back();
-
-         instanceCreateInfo.enabledExtensionCount = requiredExtentions.size();
-         instanceCreateInfo.ppEnabledExtensionNames = &requiredExtentions[0];
-
-         result = vkCreateInstance(&instanceCreateInfo, 0, &instance);
-      }
-
-      // If instance creation still fails, give up
-      if (result != VK_SUCCESS)
-      {
-         vulkanAvailable = false;
-         return;
-      }
-
-      // Load instance entry points
-      gladLoadVulkan(0, getVulkanFunction);
+      instanceCreateInfo.ppEnabledExtensionNames = requiredExtentions.data();
+
+      VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo;
+      if (ENABLE_VALIDATION_LAYERS) {
+         instanceCreateInfo.enabledLayerCount = validationLayers.size();
+         instanceCreateInfo.ppEnabledLayerNames = validationLayers.data();
+
+         populateDebugMessengerCreateInfo(debugCreateInfo);
+         instanceCreateInfo.pNext = &debugCreateInfo;
+      } else {
+         instanceCreateInfo.enabledLayerCount = 0;
+
+         instanceCreateInfo.pNext = nullptr;
+      }
+
+      if (vkCreateInstance(&instanceCreateInfo, nullptr, &instance) != VK_SUCCESS) {
+         throw runtime_error("failed to create instance!");
+      }
+   }
+
+   void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo) {
+      createInfo = {};
+      createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
+      // createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
+      createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
+      createInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
+      createInfo.pfnUserCallback = debugCallback;
    }
 
    // Setup our debug callback function to be called by Vulkan
-   void setupDebugReportCallback()
-   {
-      // Don't try to register the callback if the extension is not available
-      if (!vkCreateDebugReportCallbackEXT)
-         return;
-
-      // Register for warnings and errors
-      VkDebugReportCallbackCreateInfoEXT debugReportCallbackCreateInfo = VkDebugReportCallbackCreateInfoEXT();
-      debugReportCallbackCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT;
-      debugReportCallbackCreateInfo.flags = VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT | VK_DEBUG_REPORT_ERROR_BIT_EXT;
-      debugReportCallbackCreateInfo.pfnCallback = debugCallback;
-
-      // Create the debug callback
-      if (vkCreateDebugReportCallbackEXT(instance, &debugReportCallbackCreateInfo, 0, &debugReportCallback) != VK_SUCCESS)
-      {
-         vulkanAvailable = false;
-         return;
+   void setupDebugMessenger() {
+      if (!ENABLE_VALIDATION_LAYERS) return;
+
+      VkDebugUtilsMessengerCreateInfoEXT createInfo;
+      populateDebugMessengerCreateInfo(createInfo);
+
+      if (VulkanUtilsNew::createDebugUtilsMessengerEXT(instance, &createInfo, nullptr, &debugMessenger) != VK_SUCCESS) {
+         throw runtime_error("failed to set up debug messenger!");
       }
    }
@@ -613,7 +550,4 @@
          return;
       }
-
-      // Load physical device entry points
-      gladLoadVulkan(gpu, getVulkanFunction);
 
       // Check what depth formats are available and select one
@@ -716,6 +650,6 @@
 
    // Query surface formats and set up swapchain
-   void setupSwapchain()
-   {
+   void setupSwapchain() {
+      cout << "STARTED CALL" << endl;
       // Select a surface format that supports RGBA color format
       uint32_t objectCount = 0;
@@ -723,6 +657,5 @@
       std::vector<VkSurfaceFormatKHR> surfaceFormats;
 
-      if (vkGetPhysicalDeviceSurfaceFormatsKHR(gpu, surface, &objectCount, 0) != VK_SUCCESS)
-      {
+      if (vkGetPhysicalDeviceSurfaceFormatsKHR(gpu, surface, &objectCount, 0) != VK_SUCCESS) {
          vulkanAvailable = false;
          return;
@@ -731,21 +664,15 @@
       surfaceFormats.resize(objectCount);
 
-      if (vkGetPhysicalDeviceSurfaceFormatsKHR(gpu, surface, &objectCount, &surfaceFormats[0]) != VK_SUCCESS)
-      {
-         vulkanAvailable = false;
-         return;
-      }
-
-      if ((surfaceFormats.size() == 1) && (surfaceFormats[0].format == VK_FORMAT_UNDEFINED))
-      {
+      if (vkGetPhysicalDeviceSurfaceFormatsKHR(gpu, surface, &objectCount, &surfaceFormats[0]) != VK_SUCCESS) {
+         vulkanAvailable = false;
+         return;
+      }
+
+      if ((surfaceFormats.size() == 1) && (surfaceFormats[0].format == VK_FORMAT_UNDEFINED)) {
          swapchainFormat.format = VK_FORMAT_B8G8R8A8_UNORM;
          swapchainFormat.colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
-      }
-      else if (!surfaceFormats.empty())
-      {
-         for (std::size_t i = 0; i < surfaceFormats.size(); i++)
-         {
-            if ((surfaceFormats[i].format == VK_FORMAT_B8G8R8A8_UNORM) && (surfaceFormats[i].colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR))
-            {
+      } else if (!surfaceFormats.empty()) {
+         for (std::size_t i = 0; i < surfaceFormats.size(); i++) {
+            if ((surfaceFormats[i].format == VK_FORMAT_B8G8R8A8_UNORM) && (surfaceFormats[i].colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)) {
                swapchainFormat.format = VK_FORMAT_B8G8R8A8_UNORM;
                swapchainFormat.colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
@@ -755,9 +682,8 @@
          }
 
-         if (swapchainFormat.format == VK_FORMAT_UNDEFINED)
+         if (swapchainFormat.format == VK_FORMAT_UNDEFINED) {
             swapchainFormat = surfaceFormats[0];
-      }
-      else
-      {
+         }
+      } else {
          vulkanAvailable = false;
          return;
@@ -767,6 +693,5 @@
       std::vector<VkPresentModeKHR> presentModes;
 
-      if (vkGetPhysicalDeviceSurfacePresentModesKHR(gpu, surface, &objectCount, 0) != VK_SUCCESS)
-      {
+      if (vkGetPhysicalDeviceSurfacePresentModesKHR(gpu, surface, &objectCount, 0) != VK_SUCCESS) {
          vulkanAvailable = false;
          return;
@@ -775,6 +700,5 @@
       presentModes.resize(objectCount);
 
-      if (vkGetPhysicalDeviceSurfacePresentModesKHR(gpu, surface, &objectCount, &presentModes[0]) != VK_SUCCESS)
-      {
+      if (vkGetPhysicalDeviceSurfacePresentModesKHR(gpu, surface, &objectCount, &presentModes[0]) != VK_SUCCESS) {
          vulkanAvailable = false;
          return;
@@ -784,8 +708,6 @@
       VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR;
 
-      for (std::size_t i = 0; i < presentModes.size(); i++)
-      {
-         if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR)
-         {
+      for (std::size_t i = 0; i < presentModes.size(); i++) {
+         if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
             presentMode = presentModes[i];
             break;
@@ -796,6 +718,5 @@
       VkSurfaceCapabilitiesKHR surfaceCapabilities;
 
-      if (vkGetPhysicalDeviceSurfaceCapabilitiesKHR(gpu, surface, &surfaceCapabilities) != VK_SUCCESS)
-      {
+      if (vkGetPhysicalDeviceSurfaceCapabilitiesKHR(gpu, surface, &surfaceCapabilities) != VK_SUCCESS) {
          vulkanAvailable = false;
          return;
@@ -824,6 +745,5 @@
 
       // Create the swapchain
-      if (vkCreateSwapchainKHR(device, &swapchainCreateInfo, 0, &swapchain) != VK_SUCCESS)
-      {
+      if (vkCreateSwapchainKHR(device, &swapchainCreateInfo, 0, &swapchain) != VK_SUCCESS) {
          vulkanAvailable = false;
          return;
@@ -1057,6 +977,5 @@
 
    // Set up pipeline layout
-   void setupPipelineLayout()
-   {
+   void setupPipelineLayout() {
       VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = VkPipelineLayoutCreateInfo();
       pipelineLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
@@ -1065,6 +984,5 @@
 
       // Create pipeline layout
-      if (vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, 0, &pipelineLayout) != VK_SUCCESS)
-      {
+      if (vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, 0, &pipelineLayout) != VK_SUCCESS) {
          vulkanAvailable = false;
          return;
@@ -1073,6 +991,5 @@
 
    // Set up rendering pipeline
-   void setupPipeline()
-   {
+   void setupPipeline() {
       // Set up how the vertex shader pulls data out of our vertex buffer
       VkVertexInputBindingDescription vertexInputBindingDescription = VkVertexInputBindingDescription();
@@ -1199,14 +1116,11 @@
 
       // Create our graphics pipeline
-      if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &graphicsPipelineCreateInfo, 0, &graphicsPipeline) != VK_SUCCESS)
-      {
-         vulkanAvailable = false;
-         return;
+      if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &graphicsPipelineCreateInfo, 0, &graphicsPipeline) != VK_SUCCESS) {
+         vulkanAvailable = false;
       }
    }
 
    // Use our renderpass and swapchain images to create the corresponding framebuffers
-   void setupFramebuffers()
-   {
+   void setupFramebuffers() {
       swapchainFramebuffers.resize(swapchainImageViews.size());
 
@@ -1219,6 +1133,5 @@
       framebufferCreateInfo.layers = 1;
 
-      for (std::size_t i = 0; i < swapchainFramebuffers.size(); i++)
-      {
+      for (std::size_t i = 0; i < swapchainFramebuffers.size(); i++) {
          // Each framebuffer consists of a corresponding swapchain image and the shared depth image
          VkImageView attachments[] = { swapchainImageViews[i], depthImageView };
@@ -1227,6 +1140,5 @@
 
          // Create the framebuffer
-         if (vkCreateFramebuffer(device, &framebufferCreateInfo, 0, &swapchainFramebuffers[i]) != VK_SUCCESS)
-         {
+         if (vkCreateFramebuffer(device, &framebufferCreateInfo, 0, &swapchainFramebuffers[i]) != VK_SUCCESS) {
             vulkanAvailable = false;
             return;
@@ -1236,6 +1148,5 @@
 
    // Set up our command pool
-   void setupCommandPool()
-   {
+   void setupCommandPool() {
       // We want to be able to reset command buffers after submitting them
       VkCommandPoolCreateInfo commandPoolCreateInfo = VkCommandPoolCreateInfo();
@@ -1245,6 +1156,5 @@
 
       // Create our command pool
-      if (vkCreateCommandPool(device, &commandPoolCreateInfo, 0, &commandPool) != VK_SUCCESS)
-      {
+      if (vkCreateCommandPool(device, &commandPoolCreateInfo, 0, &commandPool) != VK_SUCCESS) {
          vulkanAvailable = false;
          return;
@@ -1253,6 +1163,5 @@
 
    // Helper to create a generic buffer with the specified size, usage and memory flags
-   bool createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer& buffer, VkDeviceMemory& memory)
-   {
+   bool createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer& buffer, VkDeviceMemory& memory) {
       // We only have a single queue so we can request exclusive access
       VkBufferCreateInfo bufferCreateInfo = VkBufferCreateInfo();
@@ -1263,6 +1172,7 @@
 
       // Create the buffer, this does not allocate any memory for it yet
-      if (vkCreateBuffer(device, &bufferCreateInfo, 0, &buffer) != VK_SUCCESS)
+      if (vkCreateBuffer(device, &bufferCreateInfo, 0, &buffer) != VK_SUCCESS) {
          return false;
+      }
 
       // Check what kind of memory we need to request from the GPU
@@ -1276,13 +1186,14 @@
       uint32_t memoryType = 0;
 
-      for (; memoryType < memoryProperties.memoryTypeCount; memoryType++)
-      {
+      for (; memoryType < memoryProperties.memoryTypeCount; memoryType++) {
          if ((memoryRequirements.memoryTypeBits & (1 << memoryType)) &&
-            ((memoryProperties.memoryTypes[memoryType].propertyFlags & properties) == properties))
+               ((memoryProperties.memoryTypes[memoryType].propertyFlags & properties) == properties)) {
             break;
-      }
-
-      if (memoryType == memoryProperties.memoryTypeCount)
+         }
+      }
+
+      if (memoryType == memoryProperties.memoryTypeCount) {
          return false;
+      }
 
       VkMemoryAllocateInfo memoryAllocateInfo = VkMemoryAllocateInfo();
@@ -1292,10 +1203,12 @@
 
       // Allocate the memory out of the GPU pool for the required memory type
-      if (vkAllocateMemory(device, &memoryAllocateInfo, 0, &memory) != VK_SUCCESS)
+      if (vkAllocateMemory(device, &memoryAllocateInfo, 0, &memory) != VK_SUCCESS) {
          return false;
+      }
 
       // Bind the allocated memory to our buffer object
-      if (vkBindBufferMemory(device, buffer, memory, 0) != VK_SUCCESS)
+      if (vkBindBufferMemory(device, buffer, memory, 0) != VK_SUCCESS) {
          return false;
+      }
 
       return true;
@@ -1303,6 +1216,5 @@
 
    // Helper to copy the contents of one buffer to another buffer
-   bool copyBuffer(VkBuffer dst, VkBuffer src, VkDeviceSize size)
-   {
+   bool copyBuffer(VkBuffer dst, VkBuffer src, VkDeviceSize size) {
       // Allocate a primary command buffer out of our command pool
       VkCommandBufferAllocateInfo commandBufferAllocateInfo = VkCommandBufferAllocateInfo();
@@ -1314,6 +1226,7 @@
       VkCommandBuffer commandBuffer;
 
-      if (vkAllocateCommandBuffers(device, &commandBufferAllocateInfo, &commandBuffer) != VK_SUCCESS)
+      if (vkAllocateCommandBuffers(device, &commandBufferAllocateInfo, &commandBuffer) != VK_SUCCESS) {
          return false;
+      }
 
       // Begin the command buffer
@@ -1322,6 +1235,5 @@
       commandBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
 
-      if (vkBeginCommandBuffer(commandBuffer, &commandBufferBeginInfo) != VK_SUCCESS)
-      {
+      if (vkBeginCommandBuffer(commandBuffer, &commandBufferBeginInfo) != VK_SUCCESS) {
          vkFreeCommandBuffers(device, commandPool, 1, &commandBuffer);
 
@@ -1345,6 +1257,5 @@
       submitInfo.pCommandBuffers = &commandBuffer;
 
-      if (vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE) != VK_SUCCESS)
-      {
+      if (vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE) != VK_SUCCESS) {
          vkFreeCommandBuffers(device, commandPool, 1, &commandBuffer);
 
@@ -1353,6 +1264,5 @@
 
       // Ensure the command buffer has been processed
-      if (vkQueueWaitIdle(queue) != VK_SUCCESS)
-      {
+      if (vkQueueWaitIdle(queue) != VK_SUCCESS) {
          vkFreeCommandBuffers(device, commandPool, 1, &commandBuffer);
 
@@ -1367,6 +1277,5 @@
 
    // Create our vertex buffer and upload its data
-   void setupVertexBuffer()
-   {
+   void setupVertexBuffer() {
       float vertexData[] = {
          // X      Y      Z     R     G     B     A     U     V
@@ -2376,6 +2285,5 @@
    }
 
-   void draw()
-   {
+   void draw() {
       uint32_t imageIndex = 0;
 
@@ -2383,21 +2291,19 @@
       vkWaitForFences(device, 1, &fences[currentFrame], VK_TRUE, std::numeric_limits<uint64_t>::max());
 
-      {
-         // Get the next image in the swapchain
-         VkResult result = vkAcquireNextImageKHR(device, swapchain, std::numeric_limits<uint64_t>::max(), imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex);
-
-         // Check if we need to re-create the swapchain (e.g. if the window was resized)
-         if (result == VK_ERROR_OUT_OF_DATE_KHR)
-         {
-            recreateSwapchain();
-            swapchainOutOfDate = false;
-            return;
-         }
-
-         if ((result != VK_SUCCESS) && (result != VK_TIMEOUT) && (result != VK_NOT_READY) && (result != VK_SUBOPTIMAL_KHR))
-         {
-            vulkanAvailable = false;
-            return;
-         }
+      // Get the next image in the swapchain
+      VkResult result = vkAcquireNextImageKHR(device, swapchain, std::numeric_limits<uint64_t>::max(), imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex);
+
+      // Check if we need to re-create the swapchain (e.g. if the window was resized)
+      if (result == VK_ERROR_OUT_OF_DATE_KHR) {
+         recreateSwapchain();
+         swapchainOutOfDate = false;
+         return;
+      }
+
+      // && result != VK_TIMEOUT && result != VK_NOT_READY
+      if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) {
+         throw runtime_error("failed to acquire swap chain image!");
+         vulkanAvailable = false;
+         return;
       }
 
@@ -2418,6 +2324,5 @@
       vkResetFences(device, 1, &fences[currentFrame]);
 
-      if (vkQueueSubmit(queue, 1, &submitInfo, fences[currentFrame]) != VK_SUCCESS)
-      {
+      if (vkQueueSubmit(queue, 1, &submitInfo, fences[currentFrame]) != VK_SUCCESS) {
          vulkanAvailable = false;
          return;
@@ -2433,19 +2338,15 @@
       presentInfo.pImageIndices = &imageIndex;
 
-      {
-         // Queue presentation
-         VkResult result = vkQueuePresentKHR(queue, &presentInfo);
-
-         // Check if we need to re-create the swapchain (e.g. if the window was resized)
-         if ((result == VK_ERROR_OUT_OF_DATE_KHR) || (result == VK_SUBOPTIMAL_KHR) || swapchainOutOfDate)
-         {
-            recreateSwapchain();
-            swapchainOutOfDate = false;
-         }
-         else if (result != VK_SUCCESS)
-         {
-            vulkanAvailable = false;
-            return;
-         }
+      // Queue presentation
+      result = vkQueuePresentKHR(queue, &presentInfo);
+
+      // Check if we need to re-create the swapchain (e.g. if the window was resized)
+      if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || swapchainOutOfDate) {
+         recreateSwapchain();
+         swapchainOutOfDate = false;
+      } else if (result != VK_SUCCESS) {
+         throw runtime_error("failed to present swap chain image!");
+         vulkanAvailable = false;
+         return;
       }
 
@@ -2463,6 +2364,5 @@
          // Process events
          sf::Event event;
-         while (window.pollEvent(event))
-         {
+         while (window.pollEvent(event)) {
             // Close window: exit
             if (event.type == sf::Event::Closed)
@@ -2478,6 +2378,5 @@
          }
 
-         if (vulkanAvailable)
-         {
+         if (vulkanAvailable) {
             // Update the uniform buffer (matrices)
             updateUniformBuffer(clock.getElapsedTime().asSeconds());
@@ -2499,5 +2398,5 @@
 
    VkInstance instance;
-   VkDebugReportCallbackEXT debugReportCallback;
+   VkDebugUtilsMessengerEXT debugMessenger;
    VkSurfaceKHR surface;
    VkPhysicalDevice gpu;
