Index: vulkan-game.cpp
===================================================================
--- vulkan-game.cpp	(revision c6fec84f28c9aef958ba52cdea90af362d7d5da8)
+++ vulkan-game.cpp	(revision 90a424f183e0e112f04756dc489dfa92740d280d)
@@ -93,4 +93,6 @@
    createVulkanInstance(validationLayers);
    setupDebugMessenger();
+   createVulkanSurface();
+   pickPhysicalDevice();
 }
 
@@ -230,2 +232,58 @@
    return VK_FALSE;
 }
+
+void VulkanGame::createVulkanSurface() {
+   if (gui->createVulkanSurface(instance, &surface) == RTWO_ERROR) {
+      throw runtime_error("failed to create window surface!");
+   }
+}
+
+void VulkanGame::pickPhysicalDevice() {
+   uint32_t deviceCount = 0;
+   vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr);
+
+   if (deviceCount == 0) {
+      throw runtime_error("failed to find GPUs with Vulkan support!");
+   }
+
+   vector<VkPhysicalDevice> devices(deviceCount);
+   vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data());
+
+   cout << endl << "Graphics cards:" << endl;
+   for (const VkPhysicalDevice& device : devices) {
+      if (isDeviceSuitable(device)) {
+         physicalDevice = device;
+         break;
+      }
+   }
+   cout << endl;
+
+   if (physicalDevice == VK_NULL_HANDLE) {
+      throw runtime_error("failed to find a suitable GPU!");
+   }
+}
+
+bool VulkanGame::isDeviceSuitable(VkPhysicalDevice device) {
+   const vector<const char*> deviceExtensions = {
+      VK_KHR_SWAPCHAIN_EXTENSION_NAME
+   };
+
+   VkPhysicalDeviceProperties deviceProperties;
+   vkGetPhysicalDeviceProperties(device, &deviceProperties);
+
+   cout << "Device: " << deviceProperties.deviceName << endl;
+
+   QueueFamilyIndices indices = VulkanUtils::findQueueFamilies(device, surface);
+   bool extensionsSupported = VulkanUtils::checkDeviceExtensionSupport(device, deviceExtensions);
+   bool swapChainAdequate = false;
+
+   if (extensionsSupported) {
+      SwapChainSupportDetails swapChainSupport = VulkanUtils::querySwapChainSupport(device, surface);
+      swapChainAdequate = !swapChainSupport.formats.empty() && !swapChainSupport.presentModes.empty();
+   }
+
+   VkPhysicalDeviceFeatures supportedFeatures;
+   vkGetPhysicalDeviceFeatures(device, &supportedFeatures);
+
+   return indices.isComplete() && extensionsSupported && swapChainAdequate && supportedFeatures.samplerAnisotropy;
+}
Index: vulkan-game.hpp
===================================================================
--- vulkan-game.hpp	(revision c6fec84f28c9aef958ba52cdea90af362d7d5da8)
+++ vulkan-game.hpp	(revision 90a424f183e0e112f04756dc489dfa92740d280d)
@@ -26,4 +26,6 @@
       VkInstance instance;
       VkDebugUtilsMessengerEXT debugMessenger;
+      VkSurfaceKHR surface;
+      VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
 
       bool initWindow(int width, int height, unsigned char guiFlags);
@@ -35,4 +37,7 @@
       void setupDebugMessenger();
       void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo);
+      void createVulkanSurface();
+      void pickPhysicalDevice();
+      bool isDeviceSuitable(VkPhysicalDevice device);
 
       static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(
Index: vulkan-ref.cpp
===================================================================
--- vulkan-ref.cpp	(revision c6fec84f28c9aef958ba52cdea90af362d7d5da8)
+++ vulkan-ref.cpp	(revision 90a424f183e0e112f04756dc489dfa92740d280d)
@@ -32,4 +32,5 @@
 const int MAX_FRAMES_IN_FLIGHT = 2;
 
+/*** START OF REFACTORED CODE ***/
 #ifdef NDEBUG
    const bool enableValidationLayers = false;
@@ -60,4 +61,5 @@
     vector<VkPresentModeKHR> presentModes;
 };
+/*** END OF REFACTORED CODE ***/
 
 struct Vertex {
@@ -159,8 +161,8 @@
       VkInstance instance;
       VkDebugUtilsMessengerEXT debugMessenger;
+      VkSurfaceKHR surface;
+
+      VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
 /*** END OF REFACTORED CODE ***/
-      VkSurfaceKHR surface;
-
-      VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
       VkDevice device;
 
@@ -312,7 +314,7 @@
          createInstance();
          setupDebugMessenger();
-/*** END OF REFACTORED CODE ***/
          createSurface();
          pickPhysicalDevice();
+/*** END OF REFACTORED CODE ***/
          createLogicalDevice();
          createSwapChain();
@@ -491,5 +493,4 @@
          createInfo.pfnUserCallback = debugCallback;
       }
-      /*** END OF REFACTORED CODE ***/
 
       void createSurface() {
@@ -560,4 +561,5 @@
          return requiredExtensions.empty();
       }
+/*** END OF REFACTORED CODE ***/
 
       void createLogicalDevice() {
@@ -661,4 +663,5 @@
       }
 
+/*** START OF REFACTORED CODE ***/
       SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device) {
          SwapChainSupportDetails details;
@@ -684,4 +687,5 @@
          return details;
       }
+/*** END OF REFACTORED CODE ***/
 
       VkSurfaceFormatKHR chooseSwapSurfaceFormat(const vector<VkSurfaceFormatKHR>& availableFormats) {
@@ -1034,4 +1038,5 @@
       }
 
+/*** START OF REFACTORED CODE ***/
       QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device) {
          QueueFamilyIndices indices;
@@ -1065,4 +1070,5 @@
          return indices;
       }
+/*** END OF REFACTORED CODE ***/
 
       void createDepthResources() {
Index: vulkan-utils.cpp
===================================================================
--- vulkan-utils.cpp	(revision c6fec84f28c9aef958ba52cdea90af362d7d5da8)
+++ vulkan-utils.cpp	(revision 90a424f183e0e112f04756dc489dfa92740d280d)
@@ -1,3 +1,6 @@
 #include "vulkan-utils.hpp"
+
+#include <set>
+#include <string>
 
 bool VulkanUtils::checkValidationLayerSupport(const vector<const char*> &validationLayers) {
@@ -48,2 +51,74 @@
    }
 }
+
+QueueFamilyIndices VulkanUtils::findQueueFamilies(VkPhysicalDevice device, VkSurfaceKHR surface) {
+   QueueFamilyIndices indices;
+
+   uint32_t queueFamilyCount = 0;
+   vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
+
+   vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
+   vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());
+
+   int i = 0;
+   for (const auto& queueFamily : queueFamilies) {
+      if (queueFamily.queueCount > 0 && queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) {
+         indices.graphicsFamily = i;
+      }
+
+      VkBool32 presentSupport = false;
+      vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, &presentSupport);
+
+      if (queueFamily.queueCount > 0 && presentSupport) {
+         indices.presentFamily = i;
+      }
+
+      if (indices.isComplete()) {
+         break;
+      }
+
+      i++;
+   }
+
+   return indices;
+}
+
+bool VulkanUtils::checkDeviceExtensionSupport(VkPhysicalDevice device, const vector<const char*>& deviceExtensions) {
+   uint32_t extensionCount;
+   vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr);
+
+   vector<VkExtensionProperties> availableExtensions(extensionCount);
+   vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, availableExtensions.data());
+
+   set<string> requiredExtensions(deviceExtensions.begin(), deviceExtensions.end());
+
+   for (const auto& extension : availableExtensions) {
+      requiredExtensions.erase(extension.extensionName);
+   }
+
+   return requiredExtensions.empty();
+}
+
+SwapChainSupportDetails VulkanUtils::querySwapChainSupport(VkPhysicalDevice device, VkSurfaceKHR surface) {
+   SwapChainSupportDetails details;
+
+   vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &details.capabilities);
+
+   uint32_t formatCount;
+   vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, nullptr);
+
+   if (formatCount != 0) {
+      details.formats.resize(formatCount);
+      vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, details.formats.data());
+   }
+
+   uint32_t presentModeCount;
+   vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, nullptr);
+
+   if (presentModeCount != 0) {
+      details.presentModes.resize(presentModeCount);
+      vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, details.presentModes.data());
+   }
+
+   return details;
+}
Index: vulkan-utils.hpp
===================================================================
--- vulkan-utils.hpp	(revision c6fec84f28c9aef958ba52cdea90af362d7d5da8)
+++ vulkan-utils.hpp	(revision 90a424f183e0e112f04756dc489dfa92740d280d)
@@ -2,4 +2,5 @@
 #define _VULKAN_UTILS_H
 
+#include <optional>
 #include <vector>
 
@@ -7,4 +8,19 @@
 
 using namespace std;
+
+struct QueueFamilyIndices {
+   optional<uint32_t> graphicsFamily;
+   optional<uint32_t> presentFamily;
+
+   bool isComplete() {
+      return graphicsFamily.has_value() && presentFamily.has_value();
+   }
+};
+
+struct SwapChainSupportDetails {
+   VkSurfaceCapabilitiesKHR capabilities;
+   vector<VkSurfaceFormatKHR> formats;
+   vector<VkPresentModeKHR> presentModes;
+};
 
 class VulkanUtils {
@@ -20,4 +36,8 @@
             VkDebugUtilsMessengerEXT debugMessenger,
             const VkAllocationCallbacks* pAllocator);
+
+      static QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device, VkSurfaceKHR surface);
+      static bool checkDeviceExtensionSupport(VkPhysicalDevice device, const vector<const char*>& deviceExtensions);
+      static SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device, VkSurfaceKHR surface);
 };
 
