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