1# Vulkan guide {#vulkan_guide} 2 3[TOC] 4 5This guide is intended to fill the gaps between the official [Vulkan 6resources](https://www.khronos.org/vulkan/) and the rest of the GLFW 7documentation and is not a replacement for either. It assumes some familiarity 8with Vulkan concepts like loaders, devices, queues and surfaces and leaves it to 9the Vulkan documentation to explain the details of Vulkan functions. 10 11To develop for Vulkan you should download the [LunarG Vulkan 12SDK](https://vulkan.lunarg.com/) for your platform. Apart from headers and link 13libraries, they also provide the validation layers necessary for development. 14 15The [Vulkan Tutorial](https://vulkan-tutorial.com/) has more information on how 16to use GLFW and Vulkan. The [Khronos Vulkan 17Samples](https://github.com/KhronosGroup/Vulkan-Samples) also use GLFW, although 18with a small framework in between. 19 20For details on a specific Vulkan support function, see the @ref vulkan. There 21are also guides for the other areas of the GLFW API. 22 23 - @ref intro_guide 24 - @ref window_guide 25 - @ref context_guide 26 - @ref monitor_guide 27 - @ref input_guide 28 29 30## Finding the Vulkan loader {#vulkan_loader} 31 32GLFW itself does not ever need to be linked against the Vulkan loader. 33 34By default, GLFW will load the Vulkan loader dynamically at runtime via its standard name: 35`vulkan-1.dll` on Windows, `libvulkan.so.1` on Linux and other Unix-like systems and 36`libvulkan.1.dylib` on macOS. 37 38@macos GLFW will also look up and search the `Frameworks` subdirectory of your 39application bundle. 40 41If your code is using a Vulkan loader with a different name or in a non-standard location 42you will need to direct GLFW to it. Pass your version of `vkGetInstanceProcAddr` to @ref 43glfwInitVulkanLoader before initializing GLFW and it will use that function for all Vulkan 44entry point retrieval. This prevents GLFW from dynamically loading the Vulkan loader. 45 46```c 47glfwInitVulkanLoader(vkGetInstanceProcAddr); 48``` 49 50@macos To make your application be redistributable you will need to set up the application 51bundle according to the LunarG SDK documentation. This is explained in more detail in the 52[SDK documentation for macOS](https://vulkan.lunarg.com/doc/sdk/latest/mac/getting_started.html). 53 54 55## Including the Vulkan header file {#vulkan_include} 56 57To have GLFW include the Vulkan header, define @ref GLFW_INCLUDE_VULKAN before including 58the GLFW header. 59 60```c 61#define GLFW_INCLUDE_VULKAN 62#include <GLFW/glfw3.h> 63``` 64 65If you instead want to include the Vulkan header from a custom location or use 66your own custom Vulkan header then do this before the GLFW header. 67 68```c 69#include <path/to/vulkan.h> 70#include <GLFW/glfw3.h> 71``` 72 73Unless a Vulkan header is included, either by the GLFW header or above it, the following 74GLFW functions will not be declared, as depend on Vulkan types. 75 76 - @ref glfwInitVulkanLoader 77 - @ref glfwGetInstanceProcAddress 78 - @ref glfwGetPhysicalDevicePresentationSupport 79 - @ref glfwCreateWindowSurface 80 81The `VK_USE_PLATFORM_*_KHR` macros do not need to be defined for the Vulkan part 82of GLFW to work. Define them only if you are using these extensions directly. 83 84 85## Querying for Vulkan support {#vulkan_support} 86 87If you are linking directly against the Vulkan loader then you can skip this 88section. The canonical desktop loader library exports all Vulkan core and 89Khronos extension functions, allowing them to be called directly. 90 91If you are loading the Vulkan loader dynamically instead of linking directly 92against it, you can check for the availability of a loader and ICD with @ref 93glfwVulkanSupported. 94 95```c 96if (glfwVulkanSupported()) 97{ 98 // Vulkan is available, at least for compute 99} 100``` 101 102This function returns `GLFW_TRUE` if the Vulkan loader and any minimally 103functional ICD was found. 104 105If one or both were not found, calling any other Vulkan related GLFW function 106will generate a @ref GLFW_API_UNAVAILABLE error. 107 108 109### Querying Vulkan function pointers {#vulkan_proc} 110 111To load any Vulkan core or extension function from the found loader, call @ref 112glfwGetInstanceProcAddress. To load functions needed for instance creation, 113pass `NULL` as the instance. 114 115```c 116PFN_vkCreateInstance pfnCreateInstance = (PFN_vkCreateInstance) 117 glfwGetInstanceProcAddress(NULL, "vkCreateInstance"); 118``` 119 120Once you have created an instance, you can load from it all other Vulkan core 121functions and functions from any instance extensions you enabled. 122 123```c 124PFN_vkCreateDevice pfnCreateDevice = (PFN_vkCreateDevice) 125 glfwGetInstanceProcAddress(instance, "vkCreateDevice"); 126``` 127 128This function in turn calls `vkGetInstanceProcAddr`. If that fails, the 129function falls back to a platform-specific query of the Vulkan loader (i.e. 130`dlsym` or `GetProcAddress`). If that also fails, the function returns `NULL`. 131For more information about `vkGetInstanceProcAddr`, see the Vulkan 132documentation. 133 134Vulkan also provides `vkGetDeviceProcAddr` for loading device-specific versions 135of Vulkan function. This function can be retrieved from an instance with @ref 136glfwGetInstanceProcAddress. 137 138```c 139PFN_vkGetDeviceProcAddr pfnGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr) 140 glfwGetInstanceProcAddress(instance, "vkGetDeviceProcAddr"); 141``` 142 143Device-specific functions may execute a little faster, due to not having to 144dispatch internally based on the device passed to them. For more information 145about `vkGetDeviceProcAddr`, see the Vulkan documentation. 146 147 148## Querying required Vulkan extensions {#vulkan_ext} 149 150To do anything useful with Vulkan you need to create an instance. If you want 151to use Vulkan to render to a window, you must enable the instance extensions 152GLFW requires to create Vulkan surfaces. 153 154To query the instance extensions required, call @ref 155glfwGetRequiredInstanceExtensions. 156 157```c 158uint32_t count; 159const char** extensions = glfwGetRequiredInstanceExtensions(&count); 160``` 161 162These extensions must all be enabled when creating instances that are going to 163be passed to @ref glfwGetPhysicalDevicePresentationSupport and @ref 164glfwCreateWindowSurface. The set of extensions will vary depending on platform 165and may also vary depending on graphics drivers and other factors. 166 167If it fails it will return `NULL` and GLFW will not be able to create Vulkan 168window surfaces. You can still use Vulkan for off-screen rendering and compute 169work. 170 171If successful the returned array will always include `VK_KHR_surface`, so if 172you don't require any additional extensions you can pass this list directly to 173the `VkInstanceCreateInfo` struct. 174 175```c 176VkInstanceCreateInfo ici; 177 178memset(&ici, 0, sizeof(ici)); 179ici.enabledExtensionCount = count; 180ici.ppEnabledExtensionNames = extensions; 181... 182``` 183 184Additional extensions may be required by future versions of GLFW. You should 185check whether any extensions you wish to enable are already in the returned 186array, as it is an error to specify an extension more than once in the 187`VkInstanceCreateInfo` struct. 188 189@macos MoltenVK is (as of July 2022) not yet a fully conformant implementation 190of Vulkan. As of Vulkan SDK 1.3.216.0, this means you must also enable the 191`VK_KHR_portability_enumeration` instance extension and set the 192`VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR` bit in the instance creation 193info flags for MoltenVK to show up in the list of physical devices. For more 194information, see the Vulkan and MoltenVK documentation. 195 196 197## Querying for Vulkan presentation support {#vulkan_present} 198 199Not every queue family of every Vulkan device can present images to surfaces. 200To check whether a specific queue family of a physical device supports image 201presentation without first having to create a window and surface, call @ref 202glfwGetPhysicalDevicePresentationSupport. 203 204```c 205if (glfwGetPhysicalDevicePresentationSupport(instance, physical_device, queue_family_index)) 206{ 207 // Queue family supports image presentation 208} 209``` 210 211The `VK_KHR_surface` extension additionally provides the 212`vkGetPhysicalDeviceSurfaceSupportKHR` function, which performs the same test on 213an existing Vulkan surface. 214 215 216## Creating the window {#vulkan_window} 217 218Unless you will be using OpenGL or OpenGL ES with the same window as Vulkan, 219there is no need to create a context. You can disable context creation with the 220[GLFW_CLIENT_API](@ref GLFW_CLIENT_API_hint) hint. 221 222```c 223glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); 224GLFWwindow* window = glfwCreateWindow(640, 480, "Window Title", NULL, NULL); 225``` 226 227See @ref context_less for more information. 228 229 230## Creating a Vulkan window surface {#vulkan_surface} 231 232You can create a Vulkan surface (as defined by the `VK_KHR_surface` extension) 233for a GLFW window with @ref glfwCreateWindowSurface. 234 235```c 236VkSurfaceKHR surface; 237VkResult err = glfwCreateWindowSurface(instance, window, NULL, &surface); 238if (err) 239{ 240 // Window surface creation failed 241} 242``` 243 244If an OpenGL or OpenGL ES context was created on the window, the context has 245ownership of the presentation on the window and a Vulkan surface cannot be 246created. 247 248It is your responsibility to destroy the surface. GLFW does not destroy it for 249you. Call `vkDestroySurfaceKHR` function from the same extension to destroy it. 250 251