236 lines
8.3 KiB
Plaintext
236 lines
8.3 KiB
Plaintext
|
/*!
|
||
|
|
||
|
@page vulkan_guide Vulkan guide
|
||
|
|
||
|
@tableofcontents
|
||
|
|
||
|
This guide is intended to fill the gaps between the official [Vulkan
|
||
|
resources](https://www.khronos.org/vulkan/) and the rest of the GLFW
|
||
|
documentation and is not a replacement for either. It assumes some familiarity
|
||
|
with Vulkan concepts like loaders, devices, queues and surfaces and leaves it to
|
||
|
the Vulkan documentation to explain the details of Vulkan functions.
|
||
|
|
||
|
To develop for Vulkan you should download the [LunarG Vulkan
|
||
|
SDK](https://vulkan.lunarg.com/) for your platform. Apart from headers and link
|
||
|
libraries, they also provide the validation layers necessary for development.
|
||
|
|
||
|
The [Vulkan Tutorial](https://vulkan-tutorial.com/) has more information on how
|
||
|
to use GLFW and Vulkan. The [Khronos Vulkan
|
||
|
Samples](https://github.com/KhronosGroup/Vulkan-Samples) also use GLFW, although
|
||
|
with a small framework in between.
|
||
|
|
||
|
For details on a specific Vulkan support function, see the @ref vulkan. There
|
||
|
are also guides for the other areas of the GLFW API.
|
||
|
|
||
|
- @ref intro_guide
|
||
|
- @ref window_guide
|
||
|
- @ref context_guide
|
||
|
- @ref monitor_guide
|
||
|
- @ref input_guide
|
||
|
|
||
|
|
||
|
@section vulkan_loader Linking against the Vulkan loader
|
||
|
|
||
|
By default, GLFW will look for the Vulkan loader on demand at runtime via its
|
||
|
standard name (`vulkan-1.dll` on Windows, `libvulkan.so.1` on Linux and other
|
||
|
Unix-like systems and `libvulkan.1.dylib` on macOS). This means that GLFW does
|
||
|
not need to be linked against the loader. However, it also means that if you
|
||
|
are using the static library form of the Vulkan loader GLFW will either fail to
|
||
|
find it or (worse) use the wrong one.
|
||
|
|
||
|
The @ref GLFW_VULKAN_STATIC CMake option makes GLFW call the Vulkan loader
|
||
|
directly instead of dynamically loading it at runtime. Not linking against the
|
||
|
Vulkan loader will then be a compile-time error.
|
||
|
|
||
|
@macos Because the Vulkan loader and ICD are not installed globally on macOS,
|
||
|
you need to set up the application bundle according to the LunarG SDK
|
||
|
documentation. This is explained in more detail in the
|
||
|
[SDK documentation for macOS](https://vulkan.lunarg.com/doc/sdk/latest/mac/getting_started.html).
|
||
|
|
||
|
|
||
|
@section vulkan_include Including the Vulkan and GLFW header files
|
||
|
|
||
|
To include the Vulkan header, define @ref GLFW_INCLUDE_VULKAN before including
|
||
|
the GLFW header.
|
||
|
|
||
|
@code
|
||
|
#define GLFW_INCLUDE_VULKAN
|
||
|
#include <GLFW/glfw3.h>
|
||
|
@endcode
|
||
|
|
||
|
If you instead want to include the Vulkan header from a custom location or use
|
||
|
your own custom Vulkan header then do this before the GLFW header.
|
||
|
|
||
|
@code
|
||
|
#include <path/to/vulkan.h>
|
||
|
#include <GLFW/glfw3.h>
|
||
|
@endcode
|
||
|
|
||
|
Unless a Vulkan header is included, either by the GLFW header or above it, any
|
||
|
GLFW functions that take or return Vulkan types will not be declared.
|
||
|
|
||
|
The `VK_USE_PLATFORM_*_KHR` macros do not need to be defined for the Vulkan part
|
||
|
of GLFW to work. Define them only if you are using these extensions directly.
|
||
|
|
||
|
|
||
|
@section vulkan_support Querying for Vulkan support
|
||
|
|
||
|
If you are linking directly against the Vulkan loader then you can skip this
|
||
|
section. The canonical desktop loader library exports all Vulkan core and
|
||
|
Khronos extension functions, allowing them to be called directly.
|
||
|
|
||
|
If you are loading the Vulkan loader dynamically instead of linking directly
|
||
|
against it, you can check for the availability of a loader and ICD with @ref
|
||
|
glfwVulkanSupported.
|
||
|
|
||
|
@code
|
||
|
if (glfwVulkanSupported())
|
||
|
{
|
||
|
// Vulkan is available, at least for compute
|
||
|
}
|
||
|
@endcode
|
||
|
|
||
|
This function returns `GLFW_TRUE` if the Vulkan loader and any minimally
|
||
|
functional ICD was found.
|
||
|
|
||
|
If if one or both were not found, calling any other Vulkan related GLFW function
|
||
|
will generate a @ref GLFW_API_UNAVAILABLE error.
|
||
|
|
||
|
|
||
|
@subsection vulkan_proc Querying Vulkan function pointers
|
||
|
|
||
|
To load any Vulkan core or extension function from the found loader, call @ref
|
||
|
glfwGetInstanceProcAddress. To load functions needed for instance creation,
|
||
|
pass `NULL` as the instance.
|
||
|
|
||
|
@code
|
||
|
PFN_vkCreateInstance pfnCreateInstance = (PFN_vkCreateInstance)
|
||
|
glfwGetInstanceProcAddress(NULL, "vkCreateInstance");
|
||
|
@endcode
|
||
|
|
||
|
Once you have created an instance, you can load from it all other Vulkan core
|
||
|
functions and functions from any instance extensions you enabled.
|
||
|
|
||
|
@code
|
||
|
PFN_vkCreateDevice pfnCreateDevice = (PFN_vkCreateDevice)
|
||
|
glfwGetInstanceProcAddress(instance, "vkCreateDevice");
|
||
|
@endcode
|
||
|
|
||
|
This function in turn calls `vkGetInstanceProcAddr`. If that fails, the
|
||
|
function falls back to a platform-specific query of the Vulkan loader (i.e.
|
||
|
`dlsym` or `GetProcAddress`). If that also fails, the function returns `NULL`.
|
||
|
For more information about `vkGetInstanceProcAddr`, see the Vulkan
|
||
|
documentation.
|
||
|
|
||
|
Vulkan also provides `vkGetDeviceProcAddr` for loading device-specific versions
|
||
|
of Vulkan function. This function can be retrieved from an instance with @ref
|
||
|
glfwGetInstanceProcAddress.
|
||
|
|
||
|
@code
|
||
|
PFN_vkGetDeviceProcAddr pfnGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)
|
||
|
glfwGetInstanceProcAddress(instance, "vkGetDeviceProcAddr");
|
||
|
@endcode
|
||
|
|
||
|
Device-specific functions may execute a little bit faster, due to not having to
|
||
|
dispatch internally based on the device passed to them. For more information
|
||
|
about `vkGetDeviceProcAddr`, see the Vulkan documentation.
|
||
|
|
||
|
|
||
|
@section vulkan_ext Querying required Vulkan extensions
|
||
|
|
||
|
To do anything useful with Vulkan you need to create an instance. If you want
|
||
|
to use Vulkan to render to a window, you must enable the instance extensions
|
||
|
GLFW requires to create Vulkan surfaces.
|
||
|
|
||
|
To query the instance extensions required, call @ref
|
||
|
glfwGetRequiredInstanceExtensions.
|
||
|
|
||
|
@code
|
||
|
uint32_t count;
|
||
|
const char** extensions = glfwGetRequiredInstanceExtensions(&count);
|
||
|
@endcode
|
||
|
|
||
|
These extensions must all be enabled when creating instances that are going to
|
||
|
be passed to @ref glfwGetPhysicalDevicePresentationSupport and @ref
|
||
|
glfwCreateWindowSurface. The set of extensions will vary depending on platform
|
||
|
and may also vary depending on graphics drivers and other factors.
|
||
|
|
||
|
If it fails it will return `NULL` and GLFW will not be able to create Vulkan
|
||
|
window surfaces. You can still use Vulkan for off-screen rendering and compute
|
||
|
work.
|
||
|
|
||
|
If successful the returned array will always include `VK_KHR_surface`, so if
|
||
|
you don't require any additional extensions you can pass this list directly to
|
||
|
the `VkInstanceCreateInfo` struct.
|
||
|
|
||
|
@code
|
||
|
VkInstanceCreateInfo ici;
|
||
|
|
||
|
memset(&ici, 0, sizeof(ici));
|
||
|
ici.enabledExtensionCount = count;
|
||
|
ici.ppEnabledExtensionNames = extensions;
|
||
|
...
|
||
|
@endcode
|
||
|
|
||
|
Additional extensions may be required by future versions of GLFW. You should
|
||
|
check whether any extensions you wish to enable are already in the returned
|
||
|
array, as it is an error to specify an extension more than once in the
|
||
|
`VkInstanceCreateInfo` struct.
|
||
|
|
||
|
|
||
|
@section vulkan_present Querying for Vulkan presentation support
|
||
|
|
||
|
Not every queue family of every Vulkan device can present images to surfaces.
|
||
|
To check whether a specific queue family of a physical device supports image
|
||
|
presentation without first having to create a window and surface, call @ref
|
||
|
glfwGetPhysicalDevicePresentationSupport.
|
||
|
|
||
|
@code
|
||
|
if (glfwGetPhysicalDevicePresentationSupport(instance, physical_device, queue_family_index))
|
||
|
{
|
||
|
// Queue family supports image presentation
|
||
|
}
|
||
|
@endcode
|
||
|
|
||
|
The `VK_KHR_surface` extension additionally provides the
|
||
|
`vkGetPhysicalDeviceSurfaceSupportKHR` function, which performs the same test on
|
||
|
an existing Vulkan surface.
|
||
|
|
||
|
|
||
|
@section vulkan_window Creating the window
|
||
|
|
||
|
Unless you will be using OpenGL or OpenGL ES with the same window as Vulkan,
|
||
|
there is no need to create a context. You can disable context creation with the
|
||
|
[GLFW_CLIENT_API](@ref GLFW_CLIENT_API_hint) hint.
|
||
|
|
||
|
@code
|
||
|
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||
|
GLFWwindow* window = glfwCreateWindow(640, 480, "Window Title", NULL, NULL);
|
||
|
@endcode
|
||
|
|
||
|
See @ref context_less for more information.
|
||
|
|
||
|
|
||
|
@section vulkan_surface Creating a Vulkan window surface
|
||
|
|
||
|
You can create a Vulkan surface (as defined by the `VK_KHR_surface` extension)
|
||
|
for a GLFW window with @ref glfwCreateWindowSurface.
|
||
|
|
||
|
@code
|
||
|
VkSurfaceKHR surface;
|
||
|
VkResult err = glfwCreateWindowSurface(instance, window, NULL, &surface);
|
||
|
if (err)
|
||
|
{
|
||
|
// Window surface creation failed
|
||
|
}
|
||
|
@endcode
|
||
|
|
||
|
If an OpenGL or OpenGL ES context was created on the window, the context has
|
||
|
ownership of the presentation on the window and a Vulkan surface cannot be
|
||
|
created.
|
||
|
|
||
|
It is your responsibility to destroy the surface. GLFW does not destroy it for
|
||
|
you. Call `vkDestroySurfaceKHR` function from the same extension to destroy it.
|
||
|
|
||
|
*/
|