title: GLFW - Vulkan not supported
body: <p>I've been following the Vulkan tutorial at <a href="https://vulkan-tutorial.com/" rel="noreferrer">https://vulkan-tutorial.com/</a> and I've been having issues with the section on <a href="https://vulkan-tutorial.com/Drawing_a_triangle/Presentation/Window_surface" rel="noreferrer">setting up the window surface</a>. Upon completing the section and testing nothing had broken, I found I was getting an error on the following GLFW call:</p>
  
  <p><code>glfwCreateWindowSurface(instance, window, nullptr, &amp;surface);</code></p>
  
  <p>It was returning -3. A quick bit of research revealed this was the error for <code>VK_ERROR_INITIALIZATION_FAILED</code>, which I then discovered meant the Vulkan loader was not being found. Upon testing, sure enough, I found that <code>glfwVulkanSupported()</code> was returning <code>GLFW_FALSE</code>. However, I cannot figure out why. I am using the LunarG Vulkan SDK 1.0.65.1, from <a href="https://vulkan.lunarg.com/" rel="noreferrer">here</a>, and x64 GLFW 3.2.1 from <a href="http://www.glfw.org/download.html" rel="noreferrer">here</a>. As far as I can tell, this should be working; searching the web gives no useful results. Vulkan programs such as <code>cube.exe</code>, which comes with the SDK, work fine.</p>
  
  <p>Thanks :)</p>
  
  <p>Code:</p>
  
  <pre><code>#define GLFW_INCLUDE_VULKAN
  #include &lt;GLFW/glfw3.h&gt;
  #include &lt;iostream&gt;
  #include &lt;stdexcept&gt;
  #include &lt;functional&gt;
  #include &lt;vector&gt;
  #include &lt;string.h&gt;
  #include &lt;set&gt;
  #include &lt;string&gt;
  
  VkResult CreateDebugReportCallbackEXT(
          VkInstance instance,
          const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
          const VkAllocationCallbacks *pAllocator,
          VkDebugReportCallbackEXT *pCallback){
      auto func = (PFN_vkCreateDebugReportCallbackEXT) vkGetInstanceProcAddr(instance, "vkCreateDebugReportCallbackEXT");
      if (func != nullptr){
          return func(instance, pCreateInfo, pAllocator, pCallback);
      }
      else{
          return VK_ERROR_EXTENSION_NOT_PRESENT;
      }
  }
  
  void DestroyDebugReportCallbackEXT(
          VkInstance instance,
          VkDebugReportCallbackEXT callback,
          const VkAllocationCallbacks *pAllocator){
      auto func = (PFN_vkDestroyDebugReportCallbackEXT) vkGetInstanceProcAddr(instance, "vkDestroyDebugReportCallbackEXT");
      if (func != nullptr){
          func(instance, callback, pAllocator);
      }
  }
  
  struct QueueFamilyIndices {
      int graphicsFamily = -1;
      int presentFamily = -1;
      bool isComplete() {
          return graphicsFamily &gt;= 0 &amp;&amp; presentFamily &gt;= 0;
      }
  };
  
  
  class CraftmineApplication {
      public:
          void run(){
              initVulkan();
              initWindow();
              mainLoop();
              cleanup();
          }
  
      private:
          GLFWwindow *window;
          VkInstance instance;
          VkDebugReportCallbackEXT callback;
          VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
          VkDevice device;
          VkQueue graphicsQueue;
          VkSurfaceKHR surface;
          VkQueue presentQueue;
  
          const int WIDTH = 1920;
          const int HEIGHT = 1080;
  
          const std::vector&lt;const char*&gt; validationLayers = {
              "VK_LAYER_LUNARG_standard_validation"
          };
  
  #ifdef NDEBUG
          const bool enableValidationLayers = false;
  #else
          const bool enableValidationLayers = true;
  #endif
  
          static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(
                  VkDebugReportFlagsEXT flags,
                  VkDebugReportObjectTypeEXT objType,
                  uint64_t obj,
                  size_t location,
                  int32_t code,
                  const char *layerPrefix,
                  const char *msg,
                  void *userData){
              std::cerr &lt;&lt; "Validation layer: " &lt;&lt; msg &lt;&lt; std::endl;
  
              return VK_FALSE;
          }
  
          QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device) {
              QueueFamilyIndices indices;
              uint32_t queueFamilyCount = 0;
              vkGetPhysicalDeviceQueueFamilyProperties(device, &amp;queueFamilyCount, nullptr);
  
              std::vector&lt;VkQueueFamilyProperties&gt; queueFamilies(queueFamilyCount);
              vkGetPhysicalDeviceQueueFamilyProperties(device, &amp;queueFamilyCount, queueFamilies.data());
  
              int i = 0;
              for (const auto &amp;queueFamily : queueFamilies) {
                  VkBool32 presentSupport = false;
                  vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, &amp;presentSupport);
  
                  if (queueFamily.queueCount &gt; 0 &amp;&amp; queueFamily.queueFlags &amp; VK_QUEUE_GRAPHICS_BIT) {
                      indices.graphicsFamily = i;
                  }
  
                  if (queueFamily.queueCount &gt; 0 &amp;&amp; presentSupport) {
                      indices.presentFamily = i;
                  }
  
                  if (indices.isComplete()) {
                      break;
                  }
  
                  i++;
              }
  
              return indices;
          }
  
          void createInstance(){
              if (enableValidationLayers &amp;&amp; !checkValidationLayerSupport())
                  throw std::runtime_error("Validation layers requested, but not available!");
  
              VkApplicationInfo appInfo = {};
              appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
              appInfo.pApplicationName = "Craftmine";
              appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
              appInfo.pEngineName = "";
              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 = &amp;appInfo;
  
              if (enableValidationLayers){
                  createInfo.enabledLayerCount = static_cast&lt;uint32_t&gt;(validationLayers.size());
                  createInfo.ppEnabledLayerNames = validationLayers.data();
              }
              else{
                  createInfo.enabledLayerCount = 0;
              }
  
              auto extensions = getRequriedExtensions();
  
              createInfo.enabledExtensionCount = static_cast&lt;uint32_t&gt;(extensions.size());
              createInfo.ppEnabledExtensionNames = extensions.data();
  
              uint32_t extensionCount = 0;
              vkEnumerateInstanceExtensionProperties(nullptr, &amp;extensionCount, nullptr);
              std::vector&lt;VkExtensionProperties&gt; vulkan_extensions(extensionCount);
              vkEnumerateInstanceExtensionProperties(nullptr, &amp;extensionCount, vulkan_extensions.data());
  
              bool extensionsPresent = true;
  
              for (int i = 0; i &lt; extensions.size(); i++) {
                  const char *extNeeded = extensions[i];
                  bool found = false;
                  for (const VkExtensionProperties &amp;extension : vulkan_extensions){
                      if(!strcmp(extNeeded,extension.extensionName)){
                          found = true;
                          break;
                      }
                  }
                  if(!found){
                      extensionsPresent = false;
                      break;
                  }
              }
  
              if (!extensionsPresent)
                  throw std::runtime_error("Not all required window extensions present!");
  
  
              if(vkCreateInstance(&amp;createInfo, nullptr, &amp;instance) != VK_SUCCESS)
                  throw std::runtime_error("Failed to create instance!");
          }
  
          void initWindow(){
              glfwInit();
  
              glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
              glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
  
              window = glfwCreateWindow(WIDTH, HEIGHT, "Craftmine", nullptr, nullptr);
          }
  
          void initVulkan(){
              createInstance();
              setupDebugCallback();
              createSurface();
              pickPhysicalDevice();
              createLogicalDevice();
          }
  
          void createSurface() {
              if(glfwVulkanSupported() != GLFW_TRUE) throw std::runtime_error("No Vulkan!");
              if (glfwCreateWindowSurface(instance, window, nullptr, &amp;surface) != VK_SUCCESS)
                  throw std::runtime_error("Failed to create window surface!");
  
          }
  
          void createLogicalDevice() {
              QueueFamilyIndices indices = findQueueFamilies(physicalDevice);
  
              std::vector&lt;VkDeviceQueueCreateInfo&gt; queueCreateInfos;
              std::set&lt;int&gt; uniqueQueueFamilies = { indices.graphicsFamily, indices.presentFamily };
  
              float queuePriority = 1.0f;
  
              for (int queueFamily : uniqueQueueFamilies) {
                  VkDeviceQueueCreateInfo queueCreateInfo = {};
                  queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
                  queueCreateInfo.queueFamilyIndex = queueFamily;
                  queueCreateInfo.queueCount = 1;
                  queueCreateInfo.pQueuePriorities = &amp;queuePriority;
                  queueCreateInfos.push_back(queueCreateInfo);
              }
  
              VkPhysicalDeviceFeatures deviceFeatures = {};
  
              VkDeviceCreateInfo createInfo = {};
              createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
  
              createInfo.pQueueCreateInfos = queueCreateInfos.data();
              createInfo.queueCreateInfoCount = static_cast&lt;uint32_t&gt;(queueCreateInfos.size());
  
              createInfo.pEnabledFeatures = &amp;deviceFeatures;
  
              createInfo.enabledExtensionCount = 0;
  
              if (enableValidationLayers) {
                  createInfo.enabledLayerCount = static_cast&lt;uint32_t&gt;(validationLayers.size());
                  createInfo.ppEnabledLayerNames = validationLayers.data();
              }
              else {
                  createInfo.enabledLayerCount = 0;
              }
  
              if (vkCreateDevice(physicalDevice, &amp;createInfo, nullptr, &amp;device) != VK_SUCCESS) {
                  throw std::runtime_error("Failed to create logical device!");
              }
  
              vkGetDeviceQueue(device, indices.graphicsFamily, 0, &amp;graphicsQueue);
              vkGetDeviceQueue(device, indices.presentFamily, 0, &amp;presentQueue);
          }
  
          void pickPhysicalDevice() {
              uint32_t deviceCount = 0;
              vkEnumeratePhysicalDevices(instance, &amp;deviceCount, nullptr);
              if (deviceCount == 0)
                  throw std::runtime_error("Failed to find GPUs with Vulkan support!");
  
              std::vector&lt;VkPhysicalDevice&gt; devices(deviceCount);
              vkEnumeratePhysicalDevices(instance, &amp;deviceCount, devices.data());
  
              int currentMaxScore = 0;
              for (const auto &amp;device : devices) {
                  if (getDeviceScore(device) &gt; currentMaxScore) {
                      physicalDevice = device;
                  }
              }
  
              if (physicalDevice == VK_NULL_HANDLE) {
                  throw std::runtime_error("Failed to find a suitable GPU!");
              }
          }
  
          int getDeviceScore(VkPhysicalDevice device) {
              VkPhysicalDeviceProperties deviceProperties;
              VkPhysicalDeviceFeatures deviceFeatures;
              vkGetPhysicalDeviceProperties(device, &amp;deviceProperties);
              vkGetPhysicalDeviceFeatures(device, &amp;deviceFeatures);
  
              QueueFamilyIndices indices = findQueueFamilies(device);
  
              if (!indices.isComplete()) return 0;
  
              int score = 1;
              score += deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU;
              // If unsuitable return 0
  
              return score;
          }
  
          void setupDebugCallback(){
              if (!enableValidationLayers) return;
  
              VkDebugReportCallbackCreateInfoEXT createInfo = {};
              createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT;
              createInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT;
              createInfo.pfnCallback = debugCallback;
  
              if(CreateDebugReportCallbackEXT(instance, &amp;createInfo, nullptr, &amp;callback) != VK_SUCCESS){
                  throw std::runtime_error("Failed to set up debug callback!");
              }
          }
  
          void mainLoop(){
              while (!glfwWindowShouldClose(window)){
                  glfwPollEvents();
              }
          }
  
          void cleanup(){
              vkDestroyDevice(device, nullptr);
              DestroyDebugReportCallbackEXT(instance, callback, nullptr);
              vkDestroySurfaceKHR(instance, surface, nullptr);
              vkDestroyInstance(instance, nullptr);
              glfwDestroyWindow(window);
              glfwTerminate();
          }
  
          bool checkValidationLayerSupport(){
              uint32_t layerCount;
              vkEnumerateInstanceLayerProperties(&amp;layerCount, nullptr);
  
              std::vector&lt;VkLayerProperties&gt; availableLayers(layerCount);
              vkEnumerateInstanceLayerProperties(&amp;layerCount, availableLayers.data());
  
              for (const char *layerName : validationLayers){
                  bool layerFound = false;
  
                  for (const VkLayerProperties &amp;layerProperties : availableLayers){
                      if (!strcmp(layerName, layerProperties.layerName)){
                          layerFound = true;
                          break;
                      }
                  }
  
                  if (!layerFound)
                      return false;
              }
  
              return true;
          }
  
          std::vector&lt;const char*&gt; getRequriedExtensions() {
              uint32_t glfwExtensionCount = 0;
              const char** glfwExtensions;
              glfwExtensions = glfwGetRequiredInstanceExtensions(&amp;glfwExtensionCount);
  
              std::vector&lt;const char*&gt; extensions(glfwExtensions, glfwExtensions + glfwExtensionCount);
  
              if (enableValidationLayers){
                  extensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
              }
  
              return extensions;
          }
  };
  
  int main(){
      CraftmineApplication app;
  
      try{
          app.run();
      }catch(const std::runtime_error &amp;e){
          std::cerr &lt;&lt; e.what() &lt;&lt; std::endl;
          return EXIT_FAILURE;
      }
  
      return EXIT_SUCCESS;
  }
  </code></pre>