• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<!-- markdownlint-disable MD041 -->
2[![Khronos Vulkan][1]][2]
3
4[1]: https://vulkan.lunarg.com/img/Vulkan_100px_Dec16.png "https://www.khronos.org/vulkan/"
5[2]: https://www.khronos.org/vulkan/
6
7# Application Interface to Loader <!-- omit from toc -->
8[![Creative Commons][3]][4]
9
10<!-- Copyright &copy; 2015-2023 LunarG, Inc. -->
11
12[3]: https://i.creativecommons.org/l/by-nd/4.0/88x31.png "Creative Commons License"
13[4]: https://creativecommons.org/licenses/by-nd/4.0/
14
15## Table of Contents <!-- omit from toc -->
16
17- [Overview](#overview)
18- [Interfacing with Vulkan Functions](#interfacing-with-vulkan-functions)
19  - [Vulkan Direct Exports](#vulkan-direct-exports)
20  - [Directly Linking to the Loader](#directly-linking-to-the-loader)
21    - [Dynamic Linking](#dynamic-linking)
22    - [Static Linking](#static-linking)
23  - [Indirectly Linking to the Loader](#indirectly-linking-to-the-loader)
24  - [Best Application Performance Setup](#best-application-performance-setup)
25  - [ABI Versioning](#abi-versioning)
26    - [Windows Dynamic Library Usage](#windows-dynamic-library-usage)
27    - [Linux Dynamic Library Usage](#linux-dynamic-library-usage)
28    - [MacOs Dynamic Library Usage](#macos-dynamic-library-usage)
29  - [Bundling the Loader With An Application](#bundling-the-loader-with-an-application)
30- [Application Layer Usage](#application-layer-usage)
31  - [Meta-Layers](#meta-layers)
32  - [Implicit vs Explicit Layers](#implicit-vs-explicit-layers)
33    - [Override Layer](#override-layer)
34  - [Forcing Layer Source Folders](#forcing-layer-source-folders)
35    - [Exception for Elevated Privileges](#exception-for-elevated-privileges)
36  - [Forcing Layers to be Enabled on Windows, Linux and macOS](#forcing-layers-to-be-enabled-on-windows-linux-and-macos)
37  - [Overall Layer Ordering](#overall-layer-ordering)
38  - [Debugging Possible Layer Issues](#debugging-possible-layer-issues)
39- [Application Usage of Extensions](#application-usage-of-extensions)
40  - [Instance and Device Extensions](#instance-and-device-extensions)
41  - [WSI Extensions](#wsi-extensions)
42  - [Unknown Extensions](#unknown-extensions)
43  - [Filtering Out Unknown Instance Extension Names](#filtering-out-unknown-instance-extension-names)
44- [Physical Device Ordering](#physical-device-ordering)
45
46## Overview
47
48This is the Application-centric view of working with the Vulkan loader.
49For the complete overview of all sections of the loader, please refer
50to the [LoaderInterfaceArchitecture.md](LoaderInterfaceArchitecture.md) file.
51
52## Interfacing with Vulkan Functions
53
54There are several ways Vulkan functions may be interfaced through the loader:
55
56
57### Vulkan Direct Exports
58
59The loader library on Windows, Linux, Android, and macOS will export all core
60Vulkan entry-points and all appropriate Window System Interface (WSI)
61entry-points.
62This is done to make it simpler to get started with Vulkan development.
63When an application links directly to the loader library in this way, the
64Vulkan calls are simple *trampoline* functions that jump to the appropriate
65dispatch table entry for the object they are given.
66
67
68### Directly Linking to the Loader
69
70#### Dynamic Linking
71
72The loader is distributed as a dynamic library (.dll on Windows or .so on Linux
73or .dylib on macOS) which gets installed to the system path for dynamic
74libraries.
75Furthermore, the dynamic library is generally installed to Windows
76systems as part of driver installation and is generally provided on Linux
77through the system package manager.
78This means that applications can usually expect a copy of the loader to be
79present on a system.
80If applications want to be completely sure that a loader is present, they can
81include a loader or runtime installer with their application.
82
83#### Static Linking
84
85In previous versions of the loader, it was possible to statically link the
86loader.
87**This was removed and is no longer possible.**
88The decision to remove static linking was because of changes to the driver
89which made older applications that statically linked unable to find newer
90drivers.
91
92Additionally, static linking posed several problems:
93 - The loader can never be updated without re-linking the application
94 - The possibility that two included libraries could contain different versions
95 of the loader
96   - Could cause conflicts between the different loader versions
97
98The only exception to this is for macOS, but is not supported or tested.
99
100### Indirectly Linking to the Loader
101
102Applications are not required to link directly to the loader library, instead
103they can use the appropriate platform-specific dynamic symbol lookup on the
104loader library to initialize the application's own dispatch table.
105This allows an application to fail gracefully if the loader cannot be found.
106It also provides the fastest mechanism for the application to call Vulkan
107functions.
108An application only needs to query (via system calls such as `dlsym`) the
109address of `vkGetInstanceProcAddr` from the loader library.
110The application then uses `vkGetInstanceProcAddr` to load all functions
111available, such as `vkCreateInstance`, `vkEnumerateInstanceExtensionProperties`
112and `vkEnumerateInstanceLayerProperties` in a platform-independent way.
113
114### Best Application Performance Setup
115
116To get the best possible performance in a Vulkan application, the application
117should set up its own dispatch table for every Vulkan API entry-point.
118For every instance-level Vulkan command in the dispatch table, the function pointer
119should be queried and filled in by using the results of `vkGetInstanceProcAddr`.
120Additionally, for every device-level Vulkan command, the function pointer
121should be queried and filled in using the results of `vkGetDeviceProcAddr`.
122
123*Why do this?*
124
125The answer comes in how the call chain of instance functions are implemented
126versus the call chain of a device functions.
127Remember, a [Vulkan instance is a high-level construct used to provide Vulkan
128system-level information](LoaderInterfaceArchitecture.md#instance-specific).
129Because of this, instance functions need to be broadcast to every available
130driver on the system.
131The following diagram shows an approximate view of an instance call chain with
132three enabled layers:
133
134![Instance Call Chain](./images/loader_instance_chain.png)
135
136This is also how a Vulkan device function call chain looks if queried
137using `vkGetInstanceProcAddr`.
138On the other hand, a device function doesn't need to worry about the broadcast
139because it knows specifically which associated driver and which associated
140physical device the call should terminate at.
141Because of this, the loader doesn't need to get involved between any enabled
142layers and the driver.
143Thus, using a loader-exported Vulkan device function, the call chain
144in the same scenario as above would look like:
145
146![Loader Device Call Chain](./images/loader_device_chain_loader.png)
147
148An even better solution would be for an application to perform a
149`vkGetDeviceProcAddr` call on all device functions.
150This further optimizes the call chain by removing the loader all-together under
151most scenarios:
152
153![Application Device Call Chain](./images/loader_device_chain_app.png)
154
155Also, notice if no layers are enabled, the application function pointers point
156**directly to the driver**.
157With many function calls, the lack of indirection in each adds up to non-trivial
158performance savings.
159
160**NOTE:** There are some device functions which still require the loader to
161intercept them with a *trampoline* and *terminator*.
162There are very few of these, but they are typically functions which the loader
163wraps with its own data.
164In those cases, even the device call chain will continue to look like the
165instance call chain.
166One example of a device function requiring a *terminator* is
167`vkCreateSwapchainKHR`.
168For that function, the loader needs to potentially convert the KHR_surface
169object into an driver-specific KHR_surface object prior to passing down the rest
170of the function's information to the driver.
171
172Remember:
173 * `vkGetInstanceProcAddr` is used to query instance and physical device
174   functions, but can query all functions.
175 * `vkGetDeviceProcAddr` is only used to query device functions.
176
177
178### ABI Versioning
179
180The Vulkan loader library will be distributed in various ways including Vulkan
181SDKs, OS package distributions and Independent Hardware Vendor (IHV) driver
182packages.
183These details are beyond the scope of this document.
184However, the name and versioning of the Vulkan loader library is specified so
185an app can link to the correct Vulkan ABI library version.
186ABI backwards compatibility is guaranteed for all versions with the same major
187number (e.g. 1.0 and 1.1).
188
189#### Windows Dynamic Library Usage
190
191On Windows, the loader library encodes the ABI version in its name such that
192multiple ABI incompatible versions of the loader can peacefully coexist on a
193given system.
194The Vulkan loader library file name is `vulkan-<ABI version>.dll`.
195For example, for Vulkan version 1.X on Windows the library filename is
196`vulkan-1.dll`.
197This library file can typically be found in the `windows\system32`
198directory (on 64-bit Windows installs, the 32-bit version of the loader with
199the same name can be found in the `windows\sysWOW64` directory).
200
201#### Linux Dynamic Library Usage
202
203For Linux, shared libraries are versioned based on a suffix.
204Thus, the ABI number is not encoded in the base of the library filename as on
205Windows.
206
207On Linux, applications that have a hard dependency on Vulkan should request
208linking to the unversioned name `libvulkan.so` in their build system.
209For example by importing the CMake target `Vulkan::Vulkan` or by using the
210output of `pkg-config --cflags --libs vulkan` as compiler flags.
211As usual for Linux libraries, the compiler and linker will resolve this to
212a dependency on the correct versioned SONAME, currently `libvulkan.so.1`.
213Linux applications that load Vulkan-Loader dynamically at runtime do not
214benefit from this mechanism, and should instead make sure to pass the
215versioned name such as `libvulkan.so.1` to `dlopen()`, to ensure that they
216load a compatible version.
217
218#### MacOs Dynamic Library Usage
219
220MacOs linking is similar to Linux, with the exception being that the standard
221dynamic library is named `libvulkan.dylib` and the ABI versioned library is
222currently named `libvulkan.1.dylib`.
223
224
225### Bundling the Loader With An Application
226
227The Khronos loader is typically installed on platforms either in a
228platform-specific way (i.e. packages on Linux) or as part of a driver install
229(i.e. using the Vulkan Runtime installer on Windows).
230Applications or engines may desire to install the Vulkan loader locally to their
231execution tree as part of their own installation process.
232This may be because providing the specific loader:
233
234 1) Guarantees certain Vulkan API exports are available in the loader
235 2) Ensures certain loader behavior is well-known
236 3) Provides consistency across user installation
237
238However, this is **strongly discouraged** because:
239
240 1) The packaged loader may not be compatible with future driver revisions
241(this can be especially true on Windows where driver install locations can
242change during updates to the OS)
243 2) It can prevent the application/engine from taking advantage of new Vulkan
244API version/extension exports
245 3) The application/engine will miss out on important loader bug-fixes
246 4) The packaged loader will not contain useful feature updates (like
247improved loader debugability)
248
249Of course, even if an application/engine does initially release with a specific
250version of the Khronos loader, it may chose to update or remove that loader at
251some point in the future.
252This could be due to the exposure of needed functionality in the loader as time
253progresses.
254But, that relies upon end-users correctly performing whatever update process is
255necessary at that future time which may result in different behavior across
256different user's systems.
257
258One better alternative, at least on Windows, is to package the Vulkan Runtime
259installer for the desired version of the Vulkan loader with your product.
260Then, the installation process can use that to ensure the end-user's system
261is up to date.
262The Runtime installer will detect the version already installed and will only
263install a newer runtime if necessary.
264
265Another alternative is to write the application so it can fallback to earlier
266versions of Vulkan yet display a warning indicating functionality is disabled
267until the user updates their system to a specific runtime/driver.
268
269
270## Application Layer Usage
271
272Applications desiring Vulkan functionality beyond what Vulkan drivers
273on their system already expose, may use various layers to augment the API.
274A layer cannot add new Vulkan core API entry-points that are not exposed in
275Vulkan.h.
276However, layers may offer implementations of extensions that introduce
277additional entry-points beyond what is available without those layers.
278These additional extension entry-points can be queried through the Vulkan
279extension interface.
280
281A common use of layers is for API validation which can be enabled during
282application development and left out when releasing the application.
283This allows easy control of the overhead resulting from enabling validation of
284the application's usage of the API, which wasn't always possible in previous
285graphics APIs.
286
287To find out what layers are available to an application, use
288`vkEnumerateInstanceLayerProperties`.
289This will report all layers that have been discovered by the loader.
290The loader looks in various locations to find layers on the system.
291For more information see the
292[Layer discovery](LoaderLayerInterface.md#layer-discovery)
293section in the
294[LoaderLayerInterface.md document](LoaderLayerInterface.md) document.
295
296To enable specific layers, simply pass the names of the layers to
297enable in the `ppEnabledLayerNames` field of the `VkInstanceCreateInfo` during
298a call to `vkCreateInstance`.
299Once done, the layers that have been enabled will be active for all Vulkan functions
300using the created `VkInstance`, and any of its child objects.
301
302**NOTE:** Layer ordering is important in several cases since some layers
303interact with each other.
304Be careful when enabling layers as this may be the case.
305See the [Overall Layer Ordering](#overall-layer-ordering) section for more
306information.
307
308The following code section shows how to go about enabling the
309`VK_LAYER_KHRONOS_validation` layer.
310
311```
312char *instance_layers[] = {
313    "VK_LAYER_KHRONOS_validation"
314};
315const VkApplicationInfo app = {
316    .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
317    .pNext = NULL,
318    .pApplicationName = "TEST_APP",
319    .applicationVersion = 0,
320    .pEngineName = "TEST_ENGINE",
321    .engineVersion = 0,
322    .apiVersion = VK_API_VERSION_1_0,
323};
324VkInstanceCreateInfo inst_info = {
325    .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
326    .pNext = NULL,
327    .pApplicationInfo = &app,
328    .enabledLayerCount = 1,
329    .ppEnabledLayerNames = (const char *const *)instance_layers,
330    .enabledExtensionCount = 0,
331    .ppEnabledExtensionNames = NULL,
332};
333err = vkCreateInstance(&inst_info, NULL, &demo->inst);
334if (VK_ERROR_LAYER_NOT_PRESENT == err) {
335  // Couldn't find the validation layer
336}
337```
338
339At `vkCreateInstance` and `vkCreateDevice`, the loader constructs call chains
340that include the application specified (enabled) layers.
341Order is important in the `ppEnabledLayerNames` array; array element 0 is the
342topmost (closest to the application) layer inserted in the chain and the last
343array element is closest to the driver.
344See the [Overall Layer Ordering](#overall-layer-ordering) section for more
345information on layer ordering.
346
347**NOTE:** *Device Layers Are Now Deprecated*
348> `vkCreateDevice` originally was able to select layers in a similar manner to
349`vkCreateInstance`.
350> This led to the concept of "instance layers" and "device layers".
351> It was decided by Khronos to deprecate the "device layer" functionality and
352> only consider "instance layers".
353> Therefore, `vkCreateDevice` will use the layers specified at
354`vkCreateInstance`.
355> Because of this, the following items have been deprecated:
356> * `VkDeviceCreateInfo` fields:
357>   * `ppEnabledLayerNames`
358>   * `enabledLayerCount`
359> * The `vkEnumerateDeviceLayerProperties` function
360
361
362### Meta-Layers
363
364Meta-layers are layers which contain an ordered list of other layers to enable.
365This is to allow grouping layers together in a specified order so that they can
366interact properly.
367Originally, this was used to group together the individual Vulkan Validation
368layers in the proper order to avoid conflicts.
369It was necessary because instead of a single Validation layer, validation was
370split into multiple component layers.
371The new `VK_LAYER_KHRONOS_validation` layer pulled everything into a single
372layer, dropping the need for meta layers.
373While not necessary for validation anymore, VkConfig does use meta layers to
374group layers together based on user's preferences.
375More can be found out about this functionality through both the
376[VkConfig documentation](https://github.com/LunarG/VulkanTools/blob/main/vkconfig/README.md)
377and the section later on the [Override Layer](#override-layer).
378
379Meta-layers are detailed more in the
380[Meta-Layers](LoaderLayerInterface.md#meta-layers) section of the
381[LoaderLayerInterface.md](LoaderLayerInterface.md) file in this folder.
382
383
384### Implicit vs Explicit Layers
385
386![Different Types of Layers](./images/loader_layer_order.png)
387
388Explicit layers are layers which are enabled by an application (e.g. with the
389vkCreateInstance function as mentioned previously).
390
391Implicit layers are enabled automatically by their very existence, unless
392requiring an additional manual enable step, unlike explicit layers that must be
393enabled explicitly.
394For example, certain application environments (e.g. Steam or an automotive
395infotainment system) may have layers which they always want enabled for all
396applications that they start.
397Other implicit layers may be for all applications started on a given system
398(e.g. layers that overlay frames-per-second).
399
400Implicit layers have an additional requirement over explicit layers in that
401they require being able to be disabled by an environmental variable.
402This is due to the fact that they are not visible to the application and could
403cause issues.
404A good principle to keep in mind would be to define both an enable and disable
405environment variable so the users can deterministically enable the
406functionality.
407On Desktop platforms (Windows, Linux, and macOS), these enable/disable settings
408are defined in the layer's JSON file.
409
410Discovery of system-installed implicit and explicit layers is described later
411in the [Layer discovery](LoaderLayerInterface.md#layer-discovery)
412section in the
413[LoaderLayerInterface.md](LoaderLayerInterface.md) document.
414
415Implicit and explicit layers may be found in different locations based on the
416underlying operating system.
417The table below details more information:
418
419<table style="width:100%">
420  <tr>
421    <th>Operating System</th>
422    <th>Implicit Layer Identification</th>
423  </tr>
424  <tr>
425    <td>Windows</td>
426    <td>Implicit layers are located in a different Windows registry location
427        than explicit layers.</td>
428  </tr>
429  <tr>
430    <td>Linux</td>
431    <td>Implicit layers are located in a different directory location than
432        explicit layers.</td>
433  </tr>
434  <tr>
435    <td>Android</td>
436    <td>There is **No Support For Implicit Layers** on Android.</td>
437  </tr>
438  <tr>
439    <td>macOS</td>
440    <td>Implicit layers are located in a different directory location than
441        explicit layers.</td>
442  </tr>
443</table>
444
445
446#### Override Layer
447
448The "Override Layer" is a special implicit meta-layer created by the
449[VkConfig](https://github.com/LunarG/VulkanTools/blob/main/vkconfig/README.md)
450tool and available by default when the tool is running.
451Once VkConfig exits, the override layer is removed, and the system should
452return to standard Vulkan behavior.
453Whenever the override layer is present in the layer search path, the loader will
454pull it into the layer call stack with the standard implicit layers along with
455all layers contained in the list of layers to load.
456This allows an end-user or developer to easily force on any number of layers
457and settings via VkConfig.
458
459The override layer is discussed more in the
460[Override Meta-Layer](LoaderLayerInterface.md#override-meta-layer) section of the
461[LoaderLayerInterface.md](LoaderLayerInterface.md) file in this folder.
462
463
464### Forcing Layer Source Folders
465
466Developers may need to use special, pre-production layers, without modifying
467the system-installed layers.
468
469This can be accomplished in one of two ways:
470
471 1. Selecting specific layer paths using the
472[VkConfig](https://github.com/LunarG/VulkanTools/blob/main/vkconfig/README.md)
473tool shipped with the Vulkan SDK.
474 2. Directing the loader to look for layers in specific files and/or folders by using the
475`VK_LAYER_PATH` and/or `VK_IMPLICIT_LAYER_PATH` environment variables.
476
477The `VK_LAYER_PATH` and `VK_IMPLICIT_LAYER_PATH` environment variables can contain multiple
478paths separated by the operating-system specific path separator.
479On Windows, this is a semicolon (`;`), while on Linux and macOS it is a colon
480(`:`).
481
482If `VK_LAYER_PATH` exists, the files and/or folders listed will be scanned for explicit
483layer manifest files.
484Implicit layer discovery is unaffected by this environment variable.
485
486If `VK_IMPLICIT_LAYER_PATH` exists, the files and/or folders listed will be scanned for
487implicit layer manifest files.
488Explicit layer discovery is unaffected by this environment variable.
489
490Each directory listed in `VK_LAYER_PATH` and `VK_IMPLICIT_LAYER_PATH` should be the full
491pathname of a folder containing layer manifest files.
492
493See the
494[Table of Debug Environment Variables](LoaderInterfaceArchitecture.md#table-of-debug-environment-variables)
495in the [LoaderInterfaceArchitecture.md document](LoaderInterfaceArchitecture.md)
496for more details.
497
498
499#### Exception for Elevated Privileges
500
501For security reasons, `VK_LAYER_PATH` and `VK_IMPLICIT_LAYER_PATH` are ignored if running
502with elevated privileges.
503Because of this, the environment variables can only be used for applications that do not
504use elevated privileges.
505
506For more information see
507[Elevated Privilege Caveats](LoaderInterfaceArchitecture.md#elevated-privilege-caveats)
508in the top-level
509[LoaderInterfaceArchitecture.md][LoaderInterfaceArchitecture.md] document.
510
511
512### Forcing Layers to be Enabled on Windows, Linux and macOS
513
514Developers may want to enable layers that are not enabled by the given
515application they are using.
516
517This can be also be accomplished in one of two ways:
518
519 1. Selecting specific layers using the
520[VkConfig](https://github.com/LunarG/VulkanTools/blob/main/vkconfig/README.md)
521tool shipped with the Vulkan SDK.
522 2. Directing the loader to look for additional layers by name using the
523`VK_INSTANCE_LAYERS` environment variable.
524
525Both can be used to enable additional layers which are not specified (enabled)
526by the application at `vkCreateInstance`.
527
528The `VK_INSTANCE_LAYERS` environment variable is a list of layer names to enable
529separated by the operating-system specific path separator.
530On Windows, this is a semicolon (`;`), while on Linux and macOS it is a colon
531(`:`).
532The order of the names is relevant with the first layer name in the list being
533the top-most layer (closest to the application) and the last layer name in the
534list being the bottom-most layer (closest to the driver).
535See the [Overall Layer Ordering](#overall-layer-ordering) section for more
536information.
537
538Application specified layers and user specified layers (via environment
539variables) are aggregated and duplicates removed by the loader when enabling
540layers.
541Layers specified via environment variable are top-most (closest to the
542application) while layers specified by the application are bottom-most.
543
544An example of using these environment variables to activate the validation
545layer `VK_LAYER_KHRONOS_validation` on Linux or macOS is as follows:
546
547```
548> $ export VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation
549```
550
551See the
552[Table of Debug Environment Variables](LoaderInterfaceArchitecture.md#table-of-debug-environment-variables)
553in the [LoaderInterfaceArchitecture.md document](LoaderInterfaceArchitecture.md)
554for more details.
555
556
557### Overall Layer Ordering
558
559The overall ordering of all layers by the loader based on the above looks
560as follows:
561
562![Loader Layer Ordering](./images/loader_layer_order_calls.png)
563
564Ordering may also be important internally to the list of explicit layers.
565Some layers may be dependent on other behavior being implemented before
566or after the loader calls it.
567For example: An overlay layer may want to use `VK_LAYER_KHRONOS_validation`
568to verify that the overlay layer is behaving appropriately.
569This requires putting the overlay layer closer to the application so that the
570validation layer can intercept any Vulkan API calls the overlay layer needs to
571make to function.
572
573
574### Debugging Possible Layer Issues
575
576If it is possible that a layer is causing issues, there are several things that
577can be tried which are documented in the
578[Debugging Possible Layer Issues](LoaderDebugging.md#debugging-possible-layer-issues)
579section of the [LoaderDebugging.mg](LoaderDebugging.md) document in the docs
580folder.
581
582
583## Application Usage of Extensions
584
585Extensions are optional functionality provided by a layer, the loader, or a
586driver.
587Extensions can modify the behavior of the Vulkan API and need to be specified
588and registered with Khronos.
589These extensions can be implemented by a Vulkan driver, the loader, or a layer
590to expose functionality not available in the core API.
591Information about various extensions can be found in the Vulkan Spec, and
592vulkan.h header file.
593
594
595### Instance and Device Extensions
596
597As hinted at in the
598[Instance Versus Device](LoaderInterfaceArchitecture.md#instance-versus-device)
599section of the main
600[LoaderInterfaceArchitecture.md](LoaderInterfaceArchitecture.md) document,
601there are two types of extensions:
602 * Instance Extensions
603 * Device Extensions
604
605An instance extension modifies existing behavior or implements new behavior on
606instance-level objects, such as `VkInstance` and `VkPhysicalDevice`.
607A device extension does the same for device-level objects, such as `VkDevice`,
608`VkQueue`, and `VkCommandBuffer` as well as any children of those objects.
609
610It is **very** important to know what the type of an extension is because
611instance  extensions must be enabled with `vkCreateInstance` while device
612extensions are enabled with `vkCreateDevice`.
613
614When calling `vkEnumerateInstanceExtensionProperties` and
615`vkEnumerateDeviceExtensionProperties`, the loader discovers and aggregates all
616extensions of their respective type from layers (both explicit and implicit),
617drivers, and the loader before reporting them to the application.
618
619Looking at `vulkan.h`, both functions are very similar,
620for example, the `vkEnumerateInstanceExtensionProperties` prototype looks as
621follows:
622
623```
624VkResult
625   vkEnumerateInstanceExtensionProperties(
626      const char *pLayerName,
627      uint32_t *pPropertyCount,
628      VkExtensionProperties *pProperties);
629```
630
631While the `vkEnumerateDeviceExtensionProperties` prototype looks like:
632
633```
634VkResult
635   vkEnumerateDeviceExtensionProperties(
636      VkPhysicalDevice physicalDevice,
637      const char *pLayerName,
638      uint32_t *pPropertyCount,
639      VkExtensionProperties *pProperties);
640```
641
642The "pLayerName" parameter in these functions is used to select either a single
643layer or the Vulkan platform implementation.
644If "pLayerName" is NULL, extensions from Vulkan implementation components
645(including loader, implicit layers, and drivers) are enumerated.
646If "pLayerName" is equal to a discovered layer module name then only extensions
647from that layer (which may be implicit or explicit) are enumerated.
648
649**Note:** While device layers are deprecated, the instance enabled layers are
650still present in the device call-chain.
651
652Duplicate extensions (e.g. an implicit layer and driver might report support for
653the same extension) are eliminated by the loader.
654For duplicates, the driver version is reported and the layer version is culled.
655
656Also, extensions **must be enabled** (in `vkCreateInstance` or `vkCreateDevice`)
657before the functions associated with the extensions can be used.
658If an extension function is queried using either `vkGetInstanceProcAddr` or
659`vkGetDeviceProcAddr`, but the extension has not been enabled, undefined behavior
660could result.
661The Validation layers will catch this invalid API usage.
662
663
664### WSI Extensions
665
666Khronos-approved WSI extensions are available and provide Windows System
667Integration support for various execution environments.
668It is important to understand that some WSI extensions are valid for all
669targets, but others are particular to a given execution environment (and
670loader).
671This Khronos loader (currently targeting Windows, Linux, macOS, Stadia, and
672Fuchsia) only enables and directly exports those WSI extensions that are
673appropriate to the current environment.
674For the most part, the selection is done in the loader using compile-time
675preprocessor flags.
676All versions of the Khronos loader currently expose at least the following WSI
677extension support:
678- VK_KHR_surface
679- VK_KHR_swapchain
680- VK_KHR_display
681
682In addition, each of the following OS targets for the loader support target-
683specific extensions:
684
685| Windowing System | Extensions available                       |
686| ---------------- | ------------------------------------------ |
687| Windows          | VK_KHR_win32_surface                       |
688| Linux (Wayland)  | VK_KHR_wayland_surface                     |
689| Linux (X11)      | VK_KHR_xcb_surface and VK_KHR_xlib_surface |
690| macOS (MoltenVK) | VK_MVK_macos_surface                       |
691| QNX (Screen)     | VK_QNX_screen_surface                      |
692
693It is important to understand that while the loader may support the various
694entry-points for these extensions, there is a handshake required to actually
695use them:
696* At least one physical device must support the extension(s)
697* The application must use such a physical device when creating a logical
698device
699* The application must request the extension(s) be enabled while creating the
700instance or logical device (this depends on whether or not the given extension
701works with an instance or a device)
702
703Only then can the WSI extension be properly used in a Vulkan program.
704
705
706### Unknown Extensions
707
708With the ability to expand Vulkan so easily, extensions will be created that
709the loader knows nothing about.
710If the extension is a device extension, the loader will pass the unknown
711entry-point down the device call chain ending with the appropriate
712driver entry-points.
713The same thing will happen if the extension is an instance extension which
714takes a physical device parameter as its first component.
715However, for all other instance extensions the loader will fail to load it.
716
717*But why doesn't the loader support unknown instance extensions?*
718<br/>
719Let's look again at the instance call chain:
720
721![Instance call chain](./images/loader_instance_chain.png)
722
723Notice that for a normal instance function call, the loader has to handle
724passing along the function call to the available drivers.
725If the loader has no idea of the parameters or return value of the instance
726call, it can't properly pass information along to the drivers.
727There may be ways to do this, which will be explored in the future.
728However, for now, the loader does not support instance extensions which don't
729expose entry points that take a physical device as their first parameter.
730
731Because the device call-chain does not normally pass through the loader
732*terminator*, this is not a problem for device extensions.
733Additionally, since a physical device is associated with one driver, the loader
734can use a generic *terminator* pointing to one driver.
735This is because both of these extensions terminate directly in the
736driver they are associated with.
737
738*Is this a big problem?*
739<br/>
740No!
741Most extension functionality only affects either a physical or logical device
742and not an instance.
743Thus, the overwhelming majority of extensions should be supported with direct
744loader support.
745
746### Filtering Out Unknown Instance Extension Names
747
748In some cases, a driver may support instance extensions that are not supported
749by the loader.
750For the above reasons, the loader will filter out the names of these unknown
751instance extensions when an application calls
752`vkEnumerateInstanceExtensionProperties`.
753Additionally, this behavior will cause the loader to emit an error during
754`vkCreateInstance` if the application still attempts to use one of these
755extensions.
756The intent is to protect applications so that they don't inadvertently use
757functionality which could lead to a crash.
758
759On the other hand, if the extension must be forced on, the filtering may be
760disabled by defining the `VK_LOADER_DISABLE_INST_EXT_FILTER` environment
761variable to a non-zero number.
762This will effectively disable the loader's filtering of instance extension
763names.
764
765## Physical Device Ordering
766
767Prior to the 1.3.204 loader, physical devices on Linux could be returned in an
768inconsistent order.
769To remedy this, the Vulkan loader will now sort devices once they have been
770received from the drivers (before returning the information to any enabled
771layers) in the following fashion:
772 * Sort based on device type (Discrete, Integrated, Virtual, all others)
773 * Sort internal to the types based on PCI information (Domain, Bus, Device, and
774   Function).
775
776This allows for a consistent physical device order from run to run on the same
777system, unless the actual underlying hardware changes.
778
779A new environment variable is defined to give users the ability to force a
780specific device, `VK_LOADER_DEVICE_SELECT`.
781This environment variable should be set to the desired devices hex value for
782Vendor Id and Device Id (as returned from `vkGetPhysicalDeviceProperties` in
783the `VkPhysicalDeviceProperties` structure).
784It should look like the following:
785
786```
787set VK_LOADER_DEVICE_SELECT=0x10de:0x1f91
788```
789
790This will force on the device with a vendor ID of "0x10de" and a device ID
791of "0x1f91".
792If that device is not found, this is simply ignored.
793
794All device selection work done in the loader can be disabled by setting the
795environment variable `VK_LOADER_DISABLE_SELECT` to a non-zero value.
796This is intended for debug purposes to narrow down any issues with the loader
797device selection mechanism, but can be used by others.
798
799[Return to the top-level LoaderInterfaceArchitecture.md file.](LoaderInterfaceArchitecture.md)
800