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