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