Index: vulkan-game.cpp
===================================================================
--- vulkan-game.cpp	(revision a6f68333e3e494e2e7baf6960f8d915391cd4acd)
+++ vulkan-game.cpp	(revision f133da0e6c0bd2262bec5cd74873703ddb01e55b)
@@ -5,4 +5,6 @@
 #include "consts.hpp"
 #include "logger.hpp"
+
+#include "vulkan-utils.hpp"
 
 using namespace std;
@@ -44,11 +46,4 @@
    }
 
-   SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0);
-   SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
-
-   SDL_RenderClear(renderer);
-
-   SDL_RenderPresent(renderer);
-
    initVulkan();
    mainLoop();
@@ -81,8 +76,21 @@
    cout << "Actual window size: (" << gui->getWindowWidth() << ", " << gui->getWindowHeight() << ")" << endl;
 
+   renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
+   if (renderer == nullptr) {
+      cout << "Renderer could not be created!" << endl;
+      cout << gui->getError() << endl;
+      return RTWO_ERROR;
+   }
+
    return RTWO_SUCCESS;
 }
 
 void VulkanGame::initVulkan() {
+   const vector<const char*> validationLayers = {
+      "VK_LAYER_KHRONOS_validation"
+   };
+
+   createVulkanInstance(validationLayers);
+   setupDebugMessenger();
 }
 
@@ -90,4 +98,6 @@
    UIEvent e;
    bool quit = false;
+
+   SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
 
    while (!quit) {
@@ -123,10 +133,99 @@
          }
       }
+
+      SDL_RenderClear(renderer);
+      SDL_RenderPresent(renderer);
    }
 }
 
 void VulkanGame::cleanup() {
+   if (ENABLE_VALIDATION_LAYERS) {
+      VulkanUtils::destroyDebugUtilsMessengerEXT(instance, debugMessenger, nullptr);
+   }
+   vkDestroyInstance(instance, nullptr);
+
+   SDL_DestroyRenderer(renderer);
+   renderer = nullptr;
+
    gui->destroyWindow();
    gui->shutdown();
    delete gui;
 }
+
+void VulkanGame::createVulkanInstance(const vector<const char*> &validationLayers) {
+   if (ENABLE_VALIDATION_LAYERS && !VulkanUtils::checkValidationLayerSupport(validationLayers)) {
+      throw runtime_error("validation layers requested, but not available!");
+   }
+
+   VkApplicationInfo appInfo = {};
+   appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
+   appInfo.pApplicationName = "Vulkan Game";
+   appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
+   appInfo.pEngineName = "No Engine";
+   appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
+   appInfo.apiVersion = VK_API_VERSION_1_0;
+
+   VkInstanceCreateInfo createInfo = {};
+   createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
+   createInfo.pApplicationInfo = &appInfo;
+
+   vector<const char*> extensions = gui->getRequiredExtensions();
+   if (ENABLE_VALIDATION_LAYERS) {
+      extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
+   }
+
+   createInfo.enabledExtensionCount = static_cast<uint32_t>(extensions.size());
+   createInfo.ppEnabledExtensionNames = extensions.data();
+
+   cout << endl << "Extensions:" << endl;
+   for (const char* extensionName : extensions) {
+      cout << extensionName << endl;
+   }
+   cout << endl;
+
+   VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo;
+   if (ENABLE_VALIDATION_LAYERS) {
+      createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
+      createInfo.ppEnabledLayerNames = validationLayers.data();
+
+      populateDebugMessengerCreateInfo(debugCreateInfo);
+      createInfo.pNext = &debugCreateInfo;
+   } else {
+      createInfo.enabledLayerCount = 0;
+
+      createInfo.pNext = nullptr;
+   }
+
+   if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) {
+      throw runtime_error("failed to create instance!");
+   }
+}
+
+void VulkanGame::setupDebugMessenger() {
+   if (!ENABLE_VALIDATION_LAYERS) return;
+
+   VkDebugUtilsMessengerCreateInfoEXT createInfo;
+   populateDebugMessengerCreateInfo(createInfo);
+
+   if (VulkanUtils::createDebugUtilsMessengerEXT(instance, &createInfo, nullptr, &debugMessenger) != VK_SUCCESS) {
+      throw runtime_error("failed to set up debug messenger!");
+   }
+}
+
+void VulkanGame::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.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;
+}
+
+VKAPI_ATTR VkBool32 VKAPI_CALL VulkanGame::debugCallback(
+      VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
+      VkDebugUtilsMessageTypeFlagsEXT messageType,
+      const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
+      void* pUserData) {
+   cerr << "validation layer: " << pCallbackData->pMessage << endl;
+
+   return VK_FALSE;
+}
