mirror of
https://github.com/openharmony/third_party_vulkan-loader.git
synced 2026-07-19 17:13:36 -04:00
Re-arrange/update loader docs
Update the loader documentation in the following ways:
1. Move documentation to new "docs" folder"
2. Split LoaderAndLayerInterface.md into multiple docs to focus
on target audience:
- Top-Level LoaderInterfaceArchitecture.md
- Applications LoaderApplicationInterface.md
- Layers LoaderLayerInterface.md
- ICDs LoaderImplementationInterface.md
3. Upload newer images and their corresponding original Inkscape files.
4. Cleanup and update sections on Linux directory search
5. Add new sections to detail items missing
- VkConfig
- Handling undef Fuchsia
6. Language cleanup
Thanks to @charles-lunarg and @smcv for feedback and various section language
corrections.
This commit is contained in:
@@ -0,0 +1,703 @@
|
||||
<!-- markdownlint-disable MD041 -->
|
||||
[![Khronos Vulkan][1]][2]
|
||||
|
||||
[1]: https://vulkan.lunarg.com/img/Vulkan_100px_Dec16.png "https://www.khronos.org/vulkan/"
|
||||
[2]: https://www.khronos.org/vulkan/
|
||||
|
||||
# Application Interface to Loader
|
||||
[![Creative Commons][3]][4]
|
||||
|
||||
<!-- Copyright © 2015-2021 LunarG, Inc. -->
|
||||
|
||||
[3]: https://i.creativecommons.org/l/by-nd/4.0/88x31.png "Creative Commons License"
|
||||
[4]: https://creativecommons.org/licenses/by-nd/4.0/
|
||||
|
||||
## Table of Contents
|
||||
|
||||
* [Overview](#overview)
|
||||
* [Interfacing with Vulkan Functions](#interfacing-with-vulkan-functions)
|
||||
* [Vulkan Direct Exports](#vulkan-direct-exports)
|
||||
* [Directly Linking to the Loader](#directly-linking-to-the-loader)
|
||||
* [Dynamic Linking](#dynamic-linking)
|
||||
* [Static Linking](#static-linking)
|
||||
* [Indirectly Linking to the Loader](#indirectly-linking-to-the-loader)
|
||||
* [Best Application Performance Setup](#best-application-performance-setup)
|
||||
* [ABI Versioning](#abi-versioning)
|
||||
* [Windows Dynamic Library Usage](#windows-dynamic-library-usage)
|
||||
* [Linux Dynamic Library Usage](#linux-dynamic-library-usage)
|
||||
* [MacOs Dynamic Library Usage](#macos-dynamic-library-usage)
|
||||
* [Application Layer Usage](#application-layer-usage)
|
||||
* [Meta-Layers](#meta-layers)
|
||||
* [Implicit vs Explicit Layers](#implicit-vs-explicit-layers)
|
||||
* [Override Layer](#override-layer)
|
||||
* [Forcing Layer Source Folders](#forcing-layer-source-folders)
|
||||
* [Exception for Elevated Privileges](#exception-for-elevated-privileges)
|
||||
* [Forcing Layers to be Enabled](#forcing-layers-to-be-enabled)
|
||||
* [Overall Layer Ordering](#overall-layer-ordering)
|
||||
* [Application Usage of Extensions](#application-usage-of-extensions)
|
||||
* [Instance and Device Extensions](#instance-and-device-extensions)
|
||||
* [WSI Extensions](#wsi-extensions)
|
||||
* [Unknown Extensions](#unknown-extensions)
|
||||
|
||||
## Overview
|
||||
|
||||
This is the Application-centric view of working with the Vulkan loader.
|
||||
For the complete overview of all sections of the loader, please refer
|
||||
to the [LoaderInterfaceArchitecture.md](LoaderInterfaceArchitecture.md) file.
|
||||
|
||||
## Interfacing with Vulkan Functions
|
||||
|
||||
There are several ways Vulkan functions may be interfaced through the loader:
|
||||
|
||||
|
||||
### Vulkan Direct Exports
|
||||
|
||||
The loader library on Windows, Linux, Android, and macOS will export all core
|
||||
Vulkan entry-points and all appropriate Window System Interface (WSI)
|
||||
entry-points.
|
||||
This is done to make it simpler to get started with Vulkan development.
|
||||
When an application links directly to the loader library in this way, the
|
||||
Vulkan calls are simple *trampoline* functions that jump to the appropriate
|
||||
dispatch table entry for the object they are given.
|
||||
|
||||
|
||||
### Directly Linking to the Loader
|
||||
|
||||
#### Dynamic Linking
|
||||
|
||||
The loader is distributed as a dynamic library (.dll on Windows or .so on Linux
|
||||
or .dylib on macOS) which gets installed to the system path for dynamic
|
||||
libraries.
|
||||
Furthermore, the dynamic library is generally installed to Windows
|
||||
systems as part of driver installation and is generally provided on Linux
|
||||
through the system package manager.
|
||||
This means that applications can usually expect a copy of the loader to be
|
||||
present on a system.
|
||||
If applications want to be completely sure that a loader is present, they can
|
||||
include a loader or runtime installer with their application.
|
||||
|
||||
#### Static Linking
|
||||
|
||||
In previous versions of the loader, it was possible to statically link the
|
||||
loader.
|
||||
**This was removed and is no longer possible.**
|
||||
The decision to remove static linking was because of changes to the driver
|
||||
which made older applications that statically linked unable to find newer
|
||||
drivers.
|
||||
|
||||
Additionally, static linking posed several problems:
|
||||
- The loader can never be updated without re-linking the application
|
||||
- The possibility that two included libraries could contain different versions
|
||||
of the loader
|
||||
- Could cause conflicts between the different loader versions
|
||||
|
||||
The only exception to this is for macOS, but is not supported or tested.
|
||||
|
||||
### Indirectly Linking to the Loader
|
||||
|
||||
Applications are not required to link directly to the loader library, instead
|
||||
they can use the appropriate platform-specific dynamic symbol lookup on the
|
||||
loader library to initialize the application's own dispatch table.
|
||||
This allows an application to fail gracefully if the loader cannot be found.
|
||||
It also provides the fastest mechanism for the application to call Vulkan
|
||||
functions.
|
||||
An application only needs to query (via system calls such as `dlsym`) the
|
||||
address of `vkGetInstanceProcAddr` from the loader library.
|
||||
The application then uses `vkGetInstanceProcAddr` to load all functions
|
||||
available, such as `vkCreateInstance`, `vkEnumerateInstanceExtensionProperties`
|
||||
and `vkEnumerateInstanceLayerProperties` in a platform-independent way.
|
||||
|
||||
### Best Application Performance Setup
|
||||
|
||||
To get the best possible performance in a Vulkan application, the application
|
||||
should set up its own dispatch table for every Vulkan API entry-point.
|
||||
For every instance-level Vulkan command in the dispatch table, the function pointer
|
||||
should be queried and filled in by using the results of `vkGetInstanceProcAddr`.
|
||||
Additionally, for every device-level Vulkan command, the function pointer
|
||||
should be queried and filled in using the resulsts of `vkGetDeviceProcAddr`.
|
||||
|
||||
*Why do this?*
|
||||
|
||||
The answer comes in how the call chain of instance functions are implemented
|
||||
versus the call chain of a device functions.
|
||||
Remember, a [Vulkan instance is a high-level construct used to provide Vulkan
|
||||
system-level information](LoaderInterfaceArchitecture.md#instance-specific).
|
||||
Because of this, instance functions need to be broadcast to every available
|
||||
implementation on the system.
|
||||
The following diagram shows an approximate view of an instance call chain with
|
||||
three enabled layers:
|
||||
|
||||

|
||||
|
||||
This is also how a Vulkan device function call chain looks if queried
|
||||
using `vkGetInstanceProcAddr`.
|
||||
On the other hand, a device function doesn't need to worry about the broadcast
|
||||
because it knows specifically which associated implementation and which
|
||||
associated physical device the call should terminate at.
|
||||
Because of this, the loader doesn't need to get involved between any enabled
|
||||
layers and the implementation.
|
||||
Thus, using a loader-exported Vulkan device function, the call chain
|
||||
in the same scenario as above would look like:
|
||||
|
||||

|
||||
|
||||
An even better solution would be for an application to perform a
|
||||
`vkGetDeviceProcAddr` call on all device functions.
|
||||
This further optimizes the call chain by removing the loader all-together under
|
||||
most scenarios:
|
||||
|
||||

|
||||
|
||||
Also, notice if no layers are enabled, the application function pointers point
|
||||
**directly to the implementation**.
|
||||
With many function calls, the lack of indirection in each adds up to non-trivial
|
||||
performance savings.
|
||||
|
||||
**NOTE:** There are some device functions which still require the loader to
|
||||
intercept them with a *trampoline* and *terminator*.
|
||||
There are very few of these, but they are typically functions which the loader
|
||||
wraps with its own data.
|
||||
In those cases, even the device call chain will continue to look like the
|
||||
instance call chain.
|
||||
One example of a device function requiring a *terminator* is
|
||||
`vkCreateSwapchainKHR`.
|
||||
For that function, the loader needs to potentially convert the KHR_surface
|
||||
object into an implementation-specific KHR_surface object prior to passing down
|
||||
the rest of the function's information to the implementation.
|
||||
|
||||
Remember:
|
||||
* `vkGetInstanceProcAddr` is used to query instance and physical device
|
||||
functions, but can query all functions.
|
||||
* `vkGetDeviceProcAddr` is only used to query device functions.
|
||||
|
||||
|
||||
### ABI Versioning
|
||||
|
||||
The Vulkan loader library will be distributed in various ways including Vulkan
|
||||
SDKs, OS package distributions and Independent Hardware Vendor (IHV) driver
|
||||
packages.
|
||||
These details are beyond the scope of this document.
|
||||
However, the name and versioning of the Vulkan loader library is specified so
|
||||
an app can link to the correct Vulkan ABI library version.
|
||||
ABI backwards compatibility is guaranteed for all versions with the same major
|
||||
number (e.g. 1.0 and 1.1).
|
||||
|
||||
#### Windows Dynamic Library Usage
|
||||
|
||||
On Windows, the loader library encodes the ABI version in its name such that
|
||||
multiple ABI incompatible versions of the loader can peacefully coexist on a
|
||||
given system.
|
||||
The Vulkan loader library file name is `vulkan-<ABI version>.dll`.
|
||||
For example, for Vulkan version 1.X on Windows the library filename is
|
||||
`vulkan-1.dll`.
|
||||
This library file can typically be found in the `windows\system32`
|
||||
directory (on 64-bit Windows installs, the 32-bit version of the loader with
|
||||
the same name can be found in the `windows\sysWOW64` directory).
|
||||
|
||||
#### Linux Dynamic Library Usage
|
||||
|
||||
For Linux, shared libraries are versioned based on a suffix.
|
||||
Thus, the ABI number is not encoded in the base of the library filename as on
|
||||
Windows.
|
||||
|
||||
On Linux, applications that have a hard dependency on Vulkan should request
|
||||
linking to the unversioned name `libvulkan.so` in their build system.
|
||||
For example by importing the CMake target `Vulkan::Vulkan` or by using the
|
||||
output of `pkg-config --cflags --libs vulkan` as compiler flags.
|
||||
As usual for Linux libraries, the compiler and linker will resolve this to
|
||||
a dependency on the correct versioned SONAME, currently `libvulkan.so.1`.
|
||||
Linux applications that load Vulkan-Loader dynamically at runtime do not
|
||||
benefit from this mechanism, and should instead make sure to pass the
|
||||
versioned name such as `libvulkan.so.1` to `dlopen()`, to ensure that they
|
||||
load a compatible version.
|
||||
|
||||
#### MacOs Dynamic Library Usage
|
||||
|
||||
MacOs linking is similar to Linux, with the exception being that the standard
|
||||
dynamic library is named `libvulkan.dylib` and the ABI versioned library is
|
||||
currently named `libvulkan.1.dylib`.
|
||||
|
||||
|
||||
## Application Layer Usage
|
||||
|
||||
Applications desiring Vulkan functionality beyond what Vulkan implementations
|
||||
on their system already expose, may use various layers to augment the API.
|
||||
A layer cannot add new Vulkan core API entry-points that are not exposed in
|
||||
Vulkan.h.
|
||||
However, layers may offer implementations of extensions that introduce
|
||||
additional entry-points beyond what is available without those layers.
|
||||
These additional extension entry-points can be queried through the Vulkan
|
||||
extension interface.
|
||||
|
||||
A common use of layers is for API validation which can be enabled during
|
||||
application development and left out when releasing the application.
|
||||
This allows easy control of the overhead resulting from enabling validation of
|
||||
the application's usage of the API, which wasn't always possible in previous
|
||||
graphics APIs.
|
||||
|
||||
To find out what layers are available to an application, use
|
||||
`vkEnumerateInstanceLayerProperties`.
|
||||
This will report all layers that have been discovered by the loader.
|
||||
The loader looks in various locations to find layers on the system.
|
||||
For more information see the
|
||||
[Layer discovery](LoaderLayerInterface.md#layer-discovery)
|
||||
section in the
|
||||
[LoaderLayerInterface.md document](LoaderLayerInterface.md) document.
|
||||
|
||||
To enable specific layers, simply pass the names of the layers to
|
||||
enable in the `ppEnabledLayerNames` field of the `VkInstanceCreateInfo` during
|
||||
a call to `vkCreateInstance`.
|
||||
Once done, the layers that have been enabled will be active for all Vulkan functions
|
||||
using the created `VkInstance`, and any of its child objects.
|
||||
|
||||
**NOTE:** Layer ordering is important in several cases since some layers
|
||||
interact with each other.
|
||||
Be careful when enabling layers as this may be the case.
|
||||
See the [Overall Layer Ordering](#overall-layer-ordering) section for more
|
||||
information.
|
||||
|
||||
The following code section shows how to go about enabling the
|
||||
`VK_LAYER_KHRONOS_validation` layer.
|
||||
|
||||
```
|
||||
char *instance_layers[] = {
|
||||
"VK_LAYER_KHRONOS_validation"
|
||||
};
|
||||
const VkApplicationInfo app = {
|
||||
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
|
||||
.pNext = NULL,
|
||||
.pApplicationName = "TEST_APP",
|
||||
.applicationVersion = 0,
|
||||
.pEngineName = "TEST_ENGINE",
|
||||
.engineVersion = 0,
|
||||
.apiVersion = VK_API_VERSION_1_0,
|
||||
};
|
||||
VkInstanceCreateInfo inst_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
|
||||
.pNext = NULL,
|
||||
.pApplicationInfo = &app,
|
||||
.enabledLayerCount = 1,
|
||||
.ppEnabledLayerNames = (const char *const *)instance_layers,
|
||||
.enabledExtensionCount = 0,
|
||||
.ppEnabledExtensionNames = NULL,
|
||||
};
|
||||
err = vkCreateInstance(&inst_info, NULL, &demo->inst);
|
||||
if (VK_ERROR_LAYER_NOT_PRESENT == err) {
|
||||
// Couldn't find the validation layer
|
||||
}
|
||||
```
|
||||
|
||||
At `vkCreateInstance` and `vkCreateDevice`, the loader constructs call chains
|
||||
that include the application specified (enabled) layers.
|
||||
Order is important in the `ppEnabledLayerNames` array; array element 0 is the
|
||||
topmost (closest to the application) layer inserted in the chain and the last
|
||||
array element is closest to the driver.
|
||||
See the [Overall Layer Ordering](#overall-layer-ordering) section for more
|
||||
information on layer ordering.
|
||||
|
||||
**NOTE:** *Device Layers Are Now Deprecated*
|
||||
> `vkCreateDevice` originally was able to select layers in a similar manner to
|
||||
`vkCreateInstance`.
|
||||
> This led to the concept of "instance layers" and "device layers".
|
||||
> It was decided by Khronos to deprecate the "device layer" functionality and
|
||||
> only consider "instance layers".
|
||||
> Therefore, `vkCreateDevice` will use the layers specified at
|
||||
`vkCreateInstance`.
|
||||
> Because of this, the following items have been deprecated:
|
||||
> * `VkDeviceCreateInfo` fields:
|
||||
> * `ppEnabledLayerNames`
|
||||
> * `enabledLayerCount`
|
||||
> * The `vkEnumerateDeviceLayerProperties` function
|
||||
|
||||
|
||||
### Meta-Layers
|
||||
|
||||
Meta-layers are layers which contain an ordered list of other layers to enable.
|
||||
This is to allow grouping layers together in a specified order so that they can
|
||||
interact properly.
|
||||
Originally, this was used to group together the individual Vulkan Validation
|
||||
layers in the proper order to avoid conflicts.
|
||||
It was necessary because instead of a single Validation layer, validation was
|
||||
split into multiple component layers.
|
||||
The new `VK_LAYER_KHRONOS_validation` layer pulled everything into a single
|
||||
layer, dropping the need for meta layers.
|
||||
While not necessary for validation anymore, VkConfig does use meta layers to
|
||||
group layers together based on user's preferences.
|
||||
More can be found out about this functionality through both the
|
||||
[VkConfig documentation](https://github.com/LunarG/VulkanTools/blob/master/vkconfig/README.md)
|
||||
and the section later on the [Override Layer](#override-layer).
|
||||
|
||||
Meta-layers are detailed more in the
|
||||
[Meta-Layers](LoaderLayerInterface.md#meta-layers) section of the
|
||||
[LoaderLayerInterface.md](LoaderLayerInterface.md) file in this folder.
|
||||
|
||||
|
||||
### Implicit vs Explicit Layers
|
||||
|
||||

|
||||
|
||||
Explicit layers are layers which are enabled by an application (e.g. with the
|
||||
vkCreateInstance function as mentioned previously).
|
||||
|
||||
Implicit layers are enabled automatically by their very existence, unless
|
||||
requiring an additional manual enable step, unlike explicit layers that must be
|
||||
enabled explicitly.
|
||||
For example, certain application environments (e.g. Steam or an automotive
|
||||
infotainment system) may have layers which they always want enabled for all
|
||||
applications that they start.
|
||||
Other implicit layers may be for all applications started on a given system
|
||||
(e.g. layers that overlay frames-per-second).
|
||||
|
||||
Implicit layers have an additional requirement over explicit layers in that
|
||||
they require being able to be disabled by an environmental variable.
|
||||
This is due to the fact that they are not visible to the application and could
|
||||
cause issues.
|
||||
A good principle to keep in mind would be to define both an enable and disable
|
||||
environment variable so the users can deterministically enable the
|
||||
functionality.
|
||||
On Desktop platforms (Windows, Linux, and macOS), these enable/disable settings
|
||||
are defined in the layer's JSON file.
|
||||
|
||||
Discovery of system-installed implicit and explicit layers is described later
|
||||
in the [Layer discovery](LoaderLayerInterface#layer-discovery)
|
||||
section in the
|
||||
[LoaderLayerInterface.md](LoaderLayerInterface.md) document.
|
||||
|
||||
Implicit and explicit layers may be found in different locations based on the
|
||||
underlying operating system.
|
||||
The table below details more information:
|
||||
|
||||
<table style="width:100%">
|
||||
<tr>
|
||||
<th>Operating System</th>
|
||||
<th>Implicit Layer Identification</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Windows</td>
|
||||
<td>Implicit layers are located in a different Windows registry location
|
||||
than explicit layers.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Linux</td>
|
||||
<td>Implicit layers are located in a different directory location than
|
||||
explicit layers.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Android</td>
|
||||
<td>There is **No Support For Implicit Layers** on Android.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>macOS</td>
|
||||
<td>Implicit layers are located in a different directory location than
|
||||
explicit layers.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
#### Override Layer
|
||||
|
||||
The "Override Layer" is a special implicit meta-layer created by the
|
||||
[VkConfig](https://github.com/LunarG/VulkanTools/blob/master/vkconfig/README.md)
|
||||
tool and available by default when the tool is running.
|
||||
Once VkConfig exits, the override layer is removed, and the system should
|
||||
return to standard Vulkan behavior.
|
||||
Whenever the override layer is present in the layer search path, the loader will
|
||||
pull it into the layer call stack with the standard implicit layers along with
|
||||
all layers contained in the list of layers to load.
|
||||
This allows an end-user or developer to easily force on any number of layers
|
||||
and settings via VkConfig.
|
||||
|
||||
The override layer is discussed more in the
|
||||
[Override Meta-Layer](LoaderLayerInterface.md#override-meta-layer) section of the
|
||||
[LoaderLayerInterface.md](LoaderLayerInterface.md) file in this folder.
|
||||
|
||||
|
||||
### Forcing Layer Source Folders
|
||||
|
||||
Developers may need to use special, pre-production layers, without modifying
|
||||
the system-installed layers.
|
||||
|
||||
This can be accomplished in one of two ways:
|
||||
|
||||
1. Selecting specific layer paths using the
|
||||
[VkConfig](https://github.com/LunarG/VulkanTools/blob/master/vkconfig/README.md)
|
||||
tool shipped with the Vulkan SDK.
|
||||
2. Directing the loader to look for layers in specific folders by using the
|
||||
`VK_LAYER_PATH` environment variable.
|
||||
|
||||
The `VK_LAYER_PATH` environment variable can contain multiple paths separated by
|
||||
the operating-system specific path separator.
|
||||
On Windows, this is a semicolon (`;`), while on Linux and macOS it is a colon
|
||||
(`:`).
|
||||
|
||||
If `VK_LAYER_PATH` exists, the folders listed in it will be scanned for explicit
|
||||
layer manifest files.
|
||||
Implicit layer discovery is unaffected by this environment variable.
|
||||
Each directory listed should be the full pathname of a folder containing layer
|
||||
manifest files.
|
||||
|
||||
See the
|
||||
[Table of Debug Environment Variables](LoaderInterfaceArchitecture.md#table-of-debug-environment-variables)
|
||||
in the [LoaderInterfaceArchitecture.md document](LoaderInterfaceArchitecture.md)
|
||||
for more details.
|
||||
|
||||
|
||||
#### Exception for Elevated Privileges
|
||||
|
||||
For security reasons, `VK_LAYER_PATH` is ignored if running with elevated
|
||||
privileges.
|
||||
Because of this, `VK_LAYER_PATH` can only be used for applications that do not
|
||||
use elevated privileges.
|
||||
|
||||
For more information see
|
||||
[Elevated Privilege Caveats](LoaderInterfaceArchitecture.md#elevated-privilege-caveats)
|
||||
in the top-level
|
||||
[LoaderInterfaceArchitecture.md][LoaderInterfaceArchitecture.md] document.
|
||||
|
||||
|
||||
### Forcing Layers to be Enabled on Windows, Linux and macOS
|
||||
|
||||
Developers may want to enable layers that are not enabled by the given
|
||||
application they are using.
|
||||
|
||||
This can be also be accomplished in one of two ways:
|
||||
|
||||
1. Selecting specific layers using the
|
||||
[VkConfig](https://github.com/LunarG/VulkanTools/blob/master/vkconfig/README.md)
|
||||
tool shipped with the Vulkan SDK.
|
||||
2. Directing the loader to look for additional layers by name using the
|
||||
`VK_INSTANCE_LAYERS` environment variable.
|
||||
|
||||
Both can be used to enable additional layers which are not specified (enabled)
|
||||
by the application at `vkCreateInstance`.
|
||||
|
||||
The `VK_INSTANCE_LAYERS` environment variable is a list of layer names to enable
|
||||
separated by the operating-system specific path separator.
|
||||
On Windows, this is a semicolon (`;`), while on Linux and macOS it is a colon
|
||||
(`:`).
|
||||
The order of the names is relevant with the first layer name in the list being
|
||||
the top-most layer (closest to the application) and the last layer name in the
|
||||
list being the bottom-most layer (closest to the driver).
|
||||
See the [Overall Layer Ordering](#overall-layer-ordering) section for more
|
||||
information.
|
||||
|
||||
Application specified layers and user specified layers (via environment
|
||||
variables) are aggregated and duplicates removed by the loader when enabling
|
||||
layers.
|
||||
Layers specified via environment variable are top-most (closest to the
|
||||
application) while layers specified by the application are bottom-most.
|
||||
|
||||
An example of using these environment variables to activate the validation
|
||||
layer `VK_LAYER_KHRONOS_validation` on Linux or macOS is as follows:
|
||||
|
||||
```
|
||||
> $ export VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation
|
||||
```
|
||||
|
||||
See the
|
||||
[Table of Debug Environment Variables](LoaderInterfaceArchitecture.md#table-of-debug-environment-variables)
|
||||
in the [LoaderInterfaceArchitecture.md document](LoaderInterfaceArchitecture.md)
|
||||
for more details.
|
||||
|
||||
|
||||
### Overall Layer Ordering
|
||||
|
||||
The overall ordering of all layers by the loader based on the above looks
|
||||
as follows:
|
||||
|
||||

|
||||
|
||||
Ordering may also be important internally to the list of explicit layers.
|
||||
Some layers may be dependent on other behavior being implemented before
|
||||
or after the loader calls it.
|
||||
For example: An overlay layer may want to use `VK_LAYER_KHRONOS_validation`
|
||||
to verify that the overlay layer is behaving appropriately.
|
||||
This requires putting the overlay layer closer to the application so that the
|
||||
validation layer can intercept any Vulkan API calls the overlay layer needs to
|
||||
make to function.
|
||||
|
||||
## Application Usage of Extensions
|
||||
|
||||
Extensions are optional functionality provided by a layer, the loader, or an
|
||||
implementation.
|
||||
Extensions can modify the behavior of the Vulkan API and need to be specified
|
||||
and registered with Khronos.
|
||||
These extensions can be implemented by a Vulkan implementation, the loader, or a
|
||||
layer to expose functionality not available in the core API.
|
||||
Information about various extensions can be found in the Vulkan Spec, and
|
||||
vulkan.h header file.
|
||||
|
||||
|
||||
### Instance and Device Extensions
|
||||
|
||||
As hinted at in the
|
||||
[Instance Versus Device](LoaderInterfaceArchitecture.md#instance-versus-device)
|
||||
section of the main
|
||||
[LoaderInterfaceArchitecture.md](LoaderInterfaceArchitecture.md) document,
|
||||
there are two types of extensions:
|
||||
* Instance Extensions
|
||||
* Device Extensions
|
||||
|
||||
An instance extension modifies existing behavior or implements new behavior on
|
||||
instance-level objects, such as `VkInstance` and `VkPhysicalDevice`.
|
||||
A device extension does the same for device-level objects, such as `VkDevice`,
|
||||
`VkQueue`, and `VkCommandBuffer` as well as any children of those objects.
|
||||
|
||||
It is **very** important to know what the type of an extension is because
|
||||
instance extensions must be enabled with `vkCreateInstance` while device
|
||||
extensions are enabled with `vkCreateDevice`.
|
||||
|
||||
When calling `vkEnumerateInstanceExtensionProperties` and
|
||||
`vkEnumerateDeviceExtensionProperties`, the loader discovers and aggregates all
|
||||
extensions of their respective type from layers (both explicit and implicit),
|
||||
implementations, and the loader before reporting them to the application.
|
||||
|
||||
Looking at `vulkan.h`, both functions are very similar,
|
||||
for example, the `vkEnumerateInstanceExtensionProperties` prototype looks as
|
||||
follows:
|
||||
|
||||
```
|
||||
VkResult
|
||||
vkEnumerateInstanceExtensionProperties(
|
||||
const char *pLayerName,
|
||||
uint32_t *pPropertyCount,
|
||||
VkExtensionProperties *pProperties);
|
||||
```
|
||||
|
||||
While the `vkEnumerateDeviceExtensionProperties` prototype looks like:
|
||||
|
||||
```
|
||||
VkResult
|
||||
vkEnumerateDeviceExtensionProperties(
|
||||
VkPhysicalDevice physicalDevice,
|
||||
const char *pLayerName,
|
||||
uint32_t *pPropertyCount,
|
||||
VkExtensionProperties *pProperties);
|
||||
```
|
||||
|
||||
The "pLayerName" parameter in these functions is used to select either a single
|
||||
layer or the Vulkan platform implementation.
|
||||
If "pLayerName" is NULL, extensions from Vulkan implementation components
|
||||
(including loader, implicit layers, and implementations) are enumerated.
|
||||
If "pLayerName" is equal to a discovered layer module name then only extensions
|
||||
from that layer (which may be implicit or explicit) are enumerated.
|
||||
|
||||
**Note:** While device layers are deprecated, the instance enabled layers are
|
||||
still present in the device call-chain.
|
||||
|
||||
Duplicate extensions (e.g. an implicit layer and implementation might report
|
||||
support for the same extension) are eliminated by the loader.
|
||||
For duplicates, the implementation version is reported and the layer version is
|
||||
culled.
|
||||
|
||||
Also, extensions **must be enabled** (in `vkCreateInstance` or `vkCreateDevice`)
|
||||
before the functions associated with the extensions can be used.
|
||||
If an extension function is queried using either `vkGetInstanceProcAddr` or
|
||||
`vkGetDeviceProcAddr`, but the extension has not been enabled, undefined behavior
|
||||
could result.
|
||||
The Validation layers will catch this invalid API usage.
|
||||
|
||||
|
||||
### WSI Extensions
|
||||
|
||||
Khronos-approved WSI extensions are available and provide Windows System
|
||||
Integration support for various execution environments.
|
||||
It is important to understand that some WSI extensions are valid for all
|
||||
targets, but others are particular to a given execution environment (and
|
||||
loader).
|
||||
This desktop loader (currently targeting Windows, Linux, and macOS) only
|
||||
enables and directly exports those WSI extensions that are appropriate to the
|
||||
current environment.
|
||||
For the most part, the selection is done in the loader using compile-time
|
||||
preprocessor flags.
|
||||
All versions of the desktop loader currently expose at least the following WSI
|
||||
extension support:
|
||||
- VK_KHR_surface
|
||||
- VK_KHR_swapchain
|
||||
- VK_KHR_display
|
||||
|
||||
In addition, each of the following OS targets for the loader support target-
|
||||
specific extensions:
|
||||
|
||||
| Windowing System | Extensions available |
|
||||
|----------------|--------------------|
|
||||
| Windows | VK_KHR_win32_surface |
|
||||
| Linux (Wayland) | VK_KHR_wayland_surface |
|
||||
| Linux (X11) | VK_KHR_xcb_surface and VK_KHR_xlib_surface |
|
||||
| macOS (MoltenVK) | VK_MVK_macos_surface |
|
||||
| QNX (Screen) | VK_QNX_screen_surface |
|
||||
|
||||
It is important to understand that while the loader may support the various
|
||||
entry-points for these extensions, there is a handshake required to actually
|
||||
use them:
|
||||
* At least one physical device must support the extension(s)
|
||||
* The application must use such a physical device when creating a logical
|
||||
device
|
||||
* The application must request the extension(s) be enabled while creating the
|
||||
instance or logical device (this depends on whether or not the given extension
|
||||
works with an instance or a device)
|
||||
|
||||
Only then can the WSI extension be properly used in a Vulkan program.
|
||||
|
||||
|
||||
### Unknown Extensions
|
||||
|
||||
With the ability to expand Vulkan so easily, extensions will be created that
|
||||
the loader knows nothing about.
|
||||
If the extension is a device extension, the loader will pass the unknown
|
||||
entry-point down the device call chain ending with the appropriate
|
||||
implementation entry-points.
|
||||
The same thing will happen if the extension is an instance extension which
|
||||
takes a physical device parameter as its first component.
|
||||
However, for all other instance extensions the loader will fail to load it.
|
||||
|
||||
*But why doesn't the loader support unknown instance extensions?*
|
||||
<br/>
|
||||
Let's look again at the instance call chain:
|
||||
|
||||

|
||||
|
||||
Notice that for a normal instance function call, the loader has to handle
|
||||
passing along the function call to the available implementations.
|
||||
If the loader has no idea of the parameters or return value of the instance
|
||||
call, it can't properly pass information along to the implementations.
|
||||
There may be ways to do this, which will be explored in the future.
|
||||
However, for now, the loader does not support instance extensions which don't
|
||||
expose entry points that take a physical device as their first parameter.
|
||||
|
||||
Because the device call-chain does not normally pass through the loader
|
||||
*terminator*, this is not a problem for device extensions.
|
||||
Additionally, since a physical device is associated with one implementation, we
|
||||
can use a generic *terminator* pointing to one implementation.
|
||||
This is because both of these extensions terminate directly in the
|
||||
implementation they are associated with.
|
||||
|
||||
*Is this a big problem?*
|
||||
<br/>
|
||||
No!
|
||||
Most extension functionality only affects either a physical or logical device
|
||||
and not an instance.
|
||||
Thus, the overwhelming majority of extensions should be supported with direct
|
||||
loader support.
|
||||
|
||||
### Filtering Out Unknown Instance Extension Names
|
||||
|
||||
In some cases, an implementation may support instance extensions that are not
|
||||
supported by the loader.
|
||||
For the above reasons, the loader will filter out the names of these unknown
|
||||
instance extensions when an application calls
|
||||
`vkEnumerateInstanceExtensionProperties`.
|
||||
Additionally, this behavior will cause the loader to emit an error during
|
||||
`vkCreateInstance` if the application still attempts to use one of these
|
||||
extensions.
|
||||
The intent is to protect applications so that they don't inadvertently use
|
||||
functionality which could lead to a crash.
|
||||
|
||||
On the other hand, if the extension must be forced on, the filtering may be
|
||||
disabled by defining the `VK_LOADER_DISABLE_INST_EXT_FILTER` environment
|
||||
variable to a non-zero number.
|
||||
This will effectively disable the loader's filtering of instance extension
|
||||
names.
|
||||
|
||||
|
||||
[Return to the top-level LoaderInterfaceArchitecture.md file.](LoaderInterfaceArchitecture.md)
|
||||
Reference in New Issue
Block a user