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` environment variable.
476
477The `VK_LAYER_PATH` environment variable can contain multiple paths separated by
478the 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.
485Each directory listed should be the full pathname of a folder containing layer
486manifest files.
487
488See the
489[Table of Debug Environment Variables](LoaderInterfaceArchitecture.md#table-of-debug-environment-variables)
490in the [LoaderInterfaceArchitecture.md document](LoaderInterfaceArchitecture.md)
491for more details.
492
493
494#### Exception for Elevated Privileges
495
496For security reasons, `VK_LAYER_PATH` is ignored if running with elevated
497privileges.
498Because of this, `VK_LAYER_PATH` can only be used for applications that do not
499use elevated privileges.
500
501For more information see
502[Elevated Privilege Caveats](LoaderInterfaceArchitecture.md#elevated-privilege-caveats)
503in the top-level
504[LoaderInterfaceArchitecture.md][LoaderInterfaceArchitecture.md] document.
505
506
507### Forcing Layers to be Enabled on Windows, Linux and macOS
508
509Developers may want to enable layers that are not enabled by the given
510application they are using.
511
512This can be also be accomplished in one of two ways:
513
514 1. Selecting specific layers using the
515[VkConfig](https://github.com/LunarG/VulkanTools/blob/main/vkconfig/README.md)
516tool shipped with the Vulkan SDK.
517 2. Directing the loader to look for additional layers by name using the
518`VK_INSTANCE_LAYERS` environment variable.
519
520Both can be used to enable additional layers which are not specified (enabled)
521by the application at `vkCreateInstance`.
522
523The `VK_INSTANCE_LAYERS` environment variable is a list of layer names to enable
524separated by the operating-system specific path separator.
525On Windows, this is a semicolon (`;`), while on Linux and macOS it is a colon
526(`:`).
527The order of the names is relevant with the first layer name in the list being
528the top-most layer (closest to the application) and the last layer name in the
529list being the bottom-most layer (closest to the driver).
530See the [Overall Layer Ordering](#overall-layer-ordering) section for more
531information.
532
533Application specified layers and user specified layers (via environment
534variables) are aggregated and duplicates removed by the loader when enabling
535layers.
536Layers specified via environment variable are top-most (closest to the
537application) while layers specified by the application are bottom-most.
538
539An example of using these environment variables to activate the validation
540layer `VK_LAYER_KHRONOS_validation` on Linux or macOS is as follows:
541
542```
543> $ export VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation
544```
545
546See the
547[Table of Debug Environment Variables](LoaderInterfaceArchitecture.md#table-of-debug-environment-variables)
548in the [LoaderInterfaceArchitecture.md document](LoaderInterfaceArchitecture.md)
549for more details.
550
551
552### Overall Layer Ordering
553
554The overall ordering of all layers by the loader based on the above looks
555as follows:
556
557![Loader Layer Ordering](./images/loader_layer_order_calls.png)
558
559Ordering may also be important internally to the list of explicit layers.
560Some layers may be dependent on other behavior being implemented before
561or after the loader calls it.
562For example: An overlay layer may want to use `VK_LAYER_KHRONOS_validation`
563to verify that the overlay layer is behaving appropriately.
564This requires putting the overlay layer closer to the application so that the
565validation layer can intercept any Vulkan API calls the overlay layer needs to
566make to function.
567
568
569### Debugging Possible Layer Issues
570
571If it is possible that a layer is causing issues, there are several things that
572can be tried which are documented in the
573[Debugging Possible Layer Issues](LoaderDebugging.md#debugging-possible-layer-issues)
574section of the [LoaderDebugging.mg](LoaderDebugging.md) document in the docs
575folder.
576
577
578## Application Usage of Extensions
579
580Extensions are optional functionality provided by a layer, the loader, or a
581driver.
582Extensions can modify the behavior of the Vulkan API and need to be specified
583and registered with Khronos.
584These extensions can be implemented by a Vulkan driver, the loader, or a layer
585to expose functionality not available in the core API.
586Information about various extensions can be found in the Vulkan Spec, and
587vulkan.h header file.
588
589
590### Instance and Device Extensions
591
592As hinted at in the
593[Instance Versus Device](LoaderInterfaceArchitecture.md#instance-versus-device)
594section of the main
595[LoaderInterfaceArchitecture.md](LoaderInterfaceArchitecture.md) document,
596there are two types of extensions:
597 * Instance Extensions
598 * Device Extensions
599
600An instance extension modifies existing behavior or implements new behavior on
601instance-level objects, such as `VkInstance` and `VkPhysicalDevice`.
602A device extension does the same for device-level objects, such as `VkDevice`,
603`VkQueue`, and `VkCommandBuffer` as well as any children of those objects.
604
605It is **very** important to know what the type of an extension is because
606instance  extensions must be enabled with `vkCreateInstance` while device
607extensions are enabled with `vkCreateDevice`.
608
609When calling `vkEnumerateInstanceExtensionProperties` and
610`vkEnumerateDeviceExtensionProperties`, the loader discovers and aggregates all
611extensions of their respective type from layers (both explicit and implicit),
612drivers, and the loader before reporting them to the application.
613
614Looking at `vulkan.h`, both functions are very similar,
615for example, the `vkEnumerateInstanceExtensionProperties` prototype looks as
616follows:
617
618```
619VkResult
620   vkEnumerateInstanceExtensionProperties(
621      const char *pLayerName,
622      uint32_t *pPropertyCount,
623      VkExtensionProperties *pProperties);
624```
625
626While the `vkEnumerateDeviceExtensionProperties` prototype looks like:
627
628```
629VkResult
630   vkEnumerateDeviceExtensionProperties(
631      VkPhysicalDevice physicalDevice,
632      const char *pLayerName,
633      uint32_t *pPropertyCount,
634      VkExtensionProperties *pProperties);
635```
636
637The "pLayerName" parameter in these functions is used to select either a single
638layer or the Vulkan platform implementation.
639If "pLayerName" is NULL, extensions from Vulkan implementation components
640(including loader, implicit layers, and drivers) are enumerated.
641If "pLayerName" is equal to a discovered layer module name then only extensions
642from that layer (which may be implicit or explicit) are enumerated.
643
644**Note:** While device layers are deprecated, the instance enabled layers are
645still present in the device call-chain.
646
647Duplicate extensions (e.g. an implicit layer and driver might report support for
648the same extension) are eliminated by the loader.
649For duplicates, the driver version is reported and the layer version is culled.
650
651Also, extensions **must be enabled** (in `vkCreateInstance` or `vkCreateDevice`)
652before the functions associated with the extensions can be used.
653If an extension function is queried using either `vkGetInstanceProcAddr` or
654`vkGetDeviceProcAddr`, but the extension has not been enabled, undefined behavior
655could result.
656The Validation layers will catch this invalid API usage.
657
658
659### WSI Extensions
660
661Khronos-approved WSI extensions are available and provide Windows System
662Integration support for various execution environments.
663It is important to understand that some WSI extensions are valid for all
664targets, but others are particular to a given execution environment (and
665loader).
666This Khronos loader (currently targeting Windows, Linux, macOS, Stadia, and
667Fuchsia) only enables and directly exports those WSI extensions that are
668appropriate to the current environment.
669For the most part, the selection is done in the loader using compile-time
670preprocessor flags.
671All versions of the Khronos loader currently expose at least the following WSI
672extension support:
673- VK_KHR_surface
674- VK_KHR_swapchain
675- VK_KHR_display
676
677In addition, each of the following OS targets for the loader support target-
678specific extensions:
679
680| Windowing System | Extensions available                       |
681| ---------------- | ------------------------------------------ |
682| Windows          | VK_KHR_win32_surface                       |
683| Linux (Wayland)  | VK_KHR_wayland_surface                     |
684| Linux (X11)      | VK_KHR_xcb_surface and VK_KHR_xlib_surface |
685| macOS (MoltenVK) | VK_MVK_macos_surface                       |
686| QNX (Screen)     | VK_QNX_screen_surface                      |
687
688It is important to understand that while the loader may support the various
689entry-points for these extensions, there is a handshake required to actually
690use them:
691* At least one physical device must support the extension(s)
692* The application must use such a physical device when creating a logical
693device
694* The application must request the extension(s) be enabled while creating the
695instance or logical device (this depends on whether or not the given extension
696works with an instance or a device)
697
698Only then can the WSI extension be properly used in a Vulkan program.
699
700
701### Unknown Extensions
702
703With the ability to expand Vulkan so easily, extensions will be created that
704the loader knows nothing about.
705If the extension is a device extension, the loader will pass the unknown
706entry-point down the device call chain ending with the appropriate
707driver entry-points.
708The same thing will happen if the extension is an instance extension which
709takes a physical device parameter as its first component.
710However, for all other instance extensions the loader will fail to load it.
711
712*But why doesn't the loader support unknown instance extensions?*
713<br/>
714Let's look again at the instance call chain:
715
716![Instance call chain](./images/loader_instance_chain.png)
717
718Notice that for a normal instance function call, the loader has to handle
719passing along the function call to the available drivers.
720If the loader has no idea of the parameters or return value of the instance
721call, it can't properly pass information along to the drivers.
722There may be ways to do this, which will be explored in the future.
723However, for now, the loader does not support instance extensions which don't
724expose entry points that take a physical device as their first parameter.
725
726Because the device call-chain does not normally pass through the loader
727*terminator*, this is not a problem for device extensions.
728Additionally, since a physical device is associated with one driver, the loader
729can use a generic *terminator* pointing to one driver.
730This is because both of these extensions terminate directly in the
731driver they are associated with.
732
733*Is this a big problem?*
734<br/>
735No!
736Most extension functionality only affects either a physical or logical device
737and not an instance.
738Thus, the overwhelming majority of extensions should be supported with direct
739loader support.
740
741### Filtering Out Unknown Instance Extension Names
742
743In some cases, a driver may support instance extensions that are not supported
744by the loader.
745For the above reasons, the loader will filter out the names of these unknown
746instance extensions when an application calls
747`vkEnumerateInstanceExtensionProperties`.
748Additionally, this behavior will cause the loader to emit an error during
749`vkCreateInstance` if the application still attempts to use one of these
750extensions.
751The intent is to protect applications so that they don't inadvertently use
752functionality which could lead to a crash.
753
754On the other hand, if the extension must be forced on, the filtering may be
755disabled by defining the `VK_LOADER_DISABLE_INST_EXT_FILTER` environment
756variable to a non-zero number.
757This will effectively disable the loader's filtering of instance extension
758names.
759
760## Physical Device Ordering
761
762Prior to the 1.3.204 loader, physical devices on Linux could be returned in an
763inconsistent order.
764To remedy this, the Vulkan loader will now sort devices once they have been
765received from the drivers (before returning the information to any enabled
766layers) in the following fashion:
767 * Sort based on device type (Discrete, Integrated, Virtual, all others)
768 * Sort internal to the types based on PCI information (Domain, Bus, Device, and
769   Function).
770
771This allows for a consistent physical device order from run to run on the same
772system, unless the actual underlying hardware changes.
773
774A new environment variable is defined to give users the ability to force a
775specific device, `VK_LOADER_DEVICE_SELECT`.
776This environment variable should be set to the desired devices hex value for
777Vendor Id and Device Id (as returned from `vkGetPhysicalDeviceProperties` in
778the `VkPhysicalDeviceProperties` structure).
779It should look like the following:
780
781```
782set VK_LOADER_DEVICE_SELECT=0x10de:0x1f91
783```
784
785This will force on the device with a vendor ID of "0x10de" and a device ID
786of "0x1f91".
787If that device is not found, this is simply ignored.
788
789All device selection work done in the loader can be disabled by setting the
790environment variable `VK_LOADER_DISABLE_SELECT` to a non-zero value.
791This is intended for debug purposes to narrow down any issues with the loader
792device selection mechanism, but can be used by others.
793
794[Return to the top-level LoaderInterfaceArchitecture.md file.](LoaderInterfaceArchitecture.md)
795