33. Extended Functionality

Additional functionality may be provided by layers or extensions. A layer cannot add or modify Vulkan commands, while an extension may do so.

The set of layers to enable is specified when creating an instance, and those layers are able to intercept any Vulkan command dispatched to that instance or any of its child objects.

Extensions can operate at either the instance or device extension scope. Enabled instance extensions are able to affect the operation of the instance and any of its child objects, while device extensions may only be available on a subset of physical devices, must be individually enabled per-device, and only affect the operation of the devices where they are enabled.

Note

Examples of these might be:

  • Whole API validation is an example of a layer.

  • Debug capabilities might make a good instance extension.

  • A layer that provides implementation-specific performance telemetry and analysis could be a layer that is only active for devices created from compatible physical devices.

  • Functions to allow an application to use additional implementation features beyond the core would be a good candidate for a device extension.

33.1. Layers

When a layer is enabled, it inserts itself into the call chain for Vulkan commands the layer is interested in. A common use of layers is to validate application behavior during development. For example, the implementation will not check that Vulkan enums used by the application fall within allowed ranges. Instead, a validation layer would do those checks and flag issues. This avoids a performance penalty during production use of the application because those layers would not be enabled in production.

Vulkan layers may wrap object handles (i.e. return a different handle value to the application than that generated by the implementation). This is generally discouraged, as it increases the probability of incompatibilities with new extensions. The validation layers wrap handles in order to track the proper use and destruction of each object. See the “Vulkan Loader Specification and Architecture Overview” document for additional information.

To query the available layers, call:

VkResult vkEnumerateInstanceLayerProperties(
    uint32_t*                                   pPropertyCount,
    VkLayerProperties*                          pProperties);
  • pPropertyCount is a pointer to an integer related to the number of layer properties available or queried, as described below.

  • pProperties is either NULL or a pointer to an array of VkLayerProperties structures.

If pProperties is NULL, then the number of layer properties available is returned in pPropertyCount. Otherwise, pPropertyCount must point to a variable set by the user to the number of elements in the pProperties array, and on return the variable is overwritten with the number of structures actually written to pProperties. If pPropertyCount is less than the number of layer properties available, at most pPropertyCount structures will be written. If pPropertyCount is smaller than the number of layers available, VK_INCOMPLETE will be returned instead of VK_SUCCESS, to indicate that not all the available layer properties were returned.

The list of available layers may change at any time due to actions outside of the Vulkan implementation, so two calls to vkEnumerateInstanceLayerProperties with the same parameters may return different results, or retrieve different pPropertyCount values or pProperties contents. Once an instance has been created, the layers enabled for that instance will continue to be enabled and valid for the lifetime of that instance, even if some of them become unavailable for future instances.

Valid Usage (Implicit)
  • pPropertyCount must be a valid pointer to a uint32_t value

  • If the value referenced by pPropertyCount is not 0, and pProperties is not NULL, pProperties must be a valid pointer to an array of pPropertyCount VkLayerProperties structures

Return Codes
Success
  • VK_SUCCESS

  • VK_INCOMPLETE

Failure
  • VK_ERROR_OUT_OF_HOST_MEMORY

  • VK_ERROR_OUT_OF_DEVICE_MEMORY

The VkLayerProperties structure is defined as:

typedef struct VkLayerProperties {
    char        layerName[VK_MAX_EXTENSION_NAME_SIZE];
    uint32_t    specVersion;
    uint32_t    implementationVersion;
    char        description[VK_MAX_DESCRIPTION_SIZE];
} VkLayerProperties;
  • layerName is a null-terminated UTF-8 string specifying the name of the layer. Use this name in the ppEnabledLayerNames array passed in the VkInstanceCreateInfo structure to enable this layer for an instance.

  • specVersion is the Vulkan version the layer was written to, encoded as described in the API Version Numbers and Semantics section.

  • implementationVersion is the version of this layer. It is an integer, increasing with backward compatible changes.

  • description is a null-terminated UTF-8 string providing additional details that can be used by the application to identify the layer.

To enable a layer, the name of the layer should be added to the ppEnabledLayerNames member of VkInstanceCreateInfo when creating a VkInstance.

Loader implementations may provide mechanisms outside the Vulkan API for enabling specific layers. Layers enabled through such a mechanism are implicitly enabled, while layers enabled by including the layer name in the ppEnabledLayerNames member of VkInstanceCreateInfo are explicitly enabled. Except where otherwise specified, implicitly enabled and explicitly enabled layers differ only in the way they are enabled. Explicitly enabling a layer that is implicitly enabled has no additional effect.

33.1.1. Device Layer Deprecation

Previous versions of this specification distinguished between instance and device layers. Instance layers were only able to intercept commands that operate on VkInstance and VkPhysicalDevice, except they were not able to intercept vkCreateDevice. Device layers were enabled for individual devices when they were created, and could only intercept commands operating on that device or its child objects.

Device-only layers are now deprecated, and this specification no longer distinguishes between instance and device layers. Layers are enabled during instance creation, and are able to intercept all commands operating on that instance or any of its child objects. At the time of deprecation there were no known device-only layers and no compelling reason to create one.

In order to maintain compatibility with implementations released prior to device-layer deprecation, applications should still enumerate and enable device layers. The behavior of vkEnumerateDeviceLayerProperties and valid usage of the ppEnabledLayerNames member of VkDeviceCreateInfo maximizes compatibility with applications written to work with the previous requirements.

To enumerate device layers, call:

VkResult vkEnumerateDeviceLayerProperties(
    VkPhysicalDevice                            physicalDevice,
    uint32_t*                                   pPropertyCount,
    VkLayerProperties*                          pProperties);
  • pPropertyCount is a pointer to an integer related to the number of layer properties available or queried.

  • pProperties is either NULL or a pointer to an array of VkLayerProperties structures.

If pProperties is NULL, then the number of layer properties available is returned in pPropertyCount. Otherwise, pPropertyCount must point to a variable set by the user to the number of elements in the pProperties array, and on return the variable is overwritten with the number of structures actually written to pProperties. If pPropertyCount is less than the number of layer properties available, at most pPropertyCount structures will be written. If pPropertyCount is smaller than the number of layers available, VK_INCOMPLETE will be returned instead of VK_SUCCESS, to indicate that not all the available layer properties were returned.

The list of layers enumerated by vkEnumerateDeviceLayerProperties must be exactly the sequence of layers enabled for the instance. The members of VkLayerProperties for each enumerated layer must be the same as the properties when the layer was enumerated by vkEnumerateInstanceLayerProperties.

Valid Usage (Implicit)
  • physicalDevice must be a valid VkPhysicalDevice handle

  • pPropertyCount must be a valid pointer to a uint32_t value

  • If the value referenced by pPropertyCount is not 0, and pProperties is not NULL, pProperties must be a valid pointer to an array of pPropertyCount VkLayerProperties structures

Return Codes
Success
  • VK_SUCCESS

  • VK_INCOMPLETE

Failure
  • VK_ERROR_OUT_OF_HOST_MEMORY

  • VK_ERROR_OUT_OF_DEVICE_MEMORY

The ppEnabledLayerNames and enabledLayerCount members of VkDeviceCreateInfo are deprecated and their values must be ignored by implementations. However, for compatibility, only an empty list of layers or a list that exactly matches the sequence enabled at instance creation time are valid, and validation layers should issue diagnostics for other cases.

Regardless of the enabled layer list provided in VkDeviceCreateInfo, the sequence of layers active for a device will be exactly the sequence of layers enabled when the parent instance was created.

33.2. Extensions

Extensions may define new Vulkan commands, structures, and enumerants. For compilation purposes, the interfaces defined by registered extensions, including new structures and enumerants as well as function pointer types for new commands, are defined in the Khronos-supplied vulkan_core.h together with the core API. However, commands defined by extensions may not be available for static linking - in which case function pointers to these commands should be queried at runtime as described in Command Function Pointers. Extensions may be provided by layers as well as by a Vulkan implementation.

Because extensions may extend or change the behavior of the Vulkan API, extension authors should add support for their extensions to the Khronos validation layers. This is especially important for new commands whose parameters have been wrapped by the validation layers. See the “Vulkan Loader Specification and Architecture Overview” document for additional information.

Note

Valid Usage sections for individual commands and structures do not currently contain which extensions have to be enabled in order to make their use valid, although it might do so in the future. It is defined only in the Valid Usage for Extensions section.

To query the available instance extensions, call:

VkResult vkEnumerateInstanceExtensionProperties(
    const char*                                 pLayerName,
    uint32_t*                                   pPropertyCount,
    VkExtensionProperties*                      pProperties);
  • pLayerName is either NULL or a pointer to a null-terminated UTF-8 string naming the layer to retrieve extensions from.

  • pPropertyCount is a pointer to an integer related to the number of extension properties available or queried, as described below.

  • pProperties is either NULL or a pointer to an array of VkExtensionProperties structures.

When pLayerName parameter is NULL, only extensions provided by the Vulkan implementation or by implicitly enabled layers are returned. When pLayerName is the name of a layer, the instance extensions provided by that layer are returned.

If pProperties is NULL, then the number of extensions properties available is returned in pPropertyCount. Otherwise, pPropertyCount must point to a variable set by the user to the number of elements in the pProperties array, and on return the variable is overwritten with the number of structures actually written to pProperties. If pPropertyCount is less than the number of extension properties available, at most pPropertyCount structures will be written. If pPropertyCount is smaller than the number of extensions available, VK_INCOMPLETE will be returned instead of VK_SUCCESS, to indicate that not all the available properties were returned.

Because the list of available layers may change externally between calls to vkEnumerateInstanceExtensionProperties, two calls may retrieve different results if a pLayerName is available in one call but not in another. The extensions supported by a layer may also change between two calls, e.g. if the layer implementation is replaced by a different version between those calls.

Valid Usage (Implicit)
  • If pLayerName is not NULL, pLayerName must be a null-terminated UTF-8 string

  • pPropertyCount must be a valid pointer to a uint32_t value

  • If the value referenced by pPropertyCount is not 0, and pProperties is not NULL, pProperties must be a valid pointer to an array of pPropertyCount VkExtensionProperties structures

Return Codes
Success
  • VK_SUCCESS

  • VK_INCOMPLETE

Failure
  • VK_ERROR_OUT_OF_HOST_MEMORY

  • VK_ERROR_OUT_OF_DEVICE_MEMORY

  • VK_ERROR_LAYER_NOT_PRESENT

To enable an instance extension, the name of the extension should be added to the ppEnabledExtensionNames member of VkInstanceCreateInfo when creating a VkInstance.

Enabling an extension does not change behavior of functionality exposed by the core Vulkan API or any other extension, other than making valid the use of the commands, enums and structures defined by that extension.

To query the extensions available to a given physical device, call:

VkResult vkEnumerateDeviceExtensionProperties(
    VkPhysicalDevice                            physicalDevice,
    const char*                                 pLayerName,
    uint32_t*                                   pPropertyCount,
    VkExtensionProperties*                      pProperties);
  • physicalDevice is the physical device that will be queried.

  • pLayerName is either NULL or a pointer to a null-terminated UTF-8 string naming the layer to retrieve extensions from.

  • pPropertyCount is a pointer to an integer related to the number of extension properties available or queried, and is treated in the same fashion as the vkEnumerateInstanceExtensionProperties::pPropertyCount parameter.

  • pProperties is either NULL or a pointer to an array of VkExtensionProperties structures.

When pLayerName parameter is NULL, only extensions provided by the Vulkan implementation or by implicitly enabled layers are returned. When pLayerName is the name of a layer, the device extensions provided by that layer are returned.

Valid Usage (Implicit)
  • physicalDevice must be a valid VkPhysicalDevice handle

  • If pLayerName is not NULL, pLayerName must be a null-terminated UTF-8 string

  • pPropertyCount must be a valid pointer to a uint32_t value

  • If the value referenced by pPropertyCount is not 0, and pProperties is not NULL, pProperties must be a valid pointer to an array of pPropertyCount VkExtensionProperties structures

Return Codes
Success
  • VK_SUCCESS

  • VK_INCOMPLETE

Failure
  • VK_ERROR_OUT_OF_HOST_MEMORY

  • VK_ERROR_OUT_OF_DEVICE_MEMORY

  • VK_ERROR_LAYER_NOT_PRESENT

The VkExtensionProperties structure is defined as:

typedef struct VkExtensionProperties {
    char        extensionName[VK_MAX_EXTENSION_NAME_SIZE];
    uint32_t    specVersion;
} VkExtensionProperties;
  • extensionName is a null-terminated string specifying the name of the extension.

  • specVersion is the version of this extension. It is an integer, incremented with backward compatible changes.

33.2.1. Instance Extensions and Device Extensions

This section provides some guidelines and rules for when to expose new functionality as an instance extension, as a device extension, or as both. The decision depends on the scope of the new functionality; such as whether it extends instance-level or device-level functionality. All Vulkan commands, structures, and enumerants are considered either instance-level, physical-device-level, or device-level.

New instance-level extension functionality must be structured within an instance extension. New device-level extension functionality may be structured within a device extension. Vulkan 1.0 initially required all new physical-device-level extension functionality to be structured within an instance extension. In order to avoid using an instance extension, which often requires loader support, physical-device-level extension functionality may be implemented within device extensions (which must depend on the VK_KHR_get_physical_device_properties2 extension, or on Vulkan 1.1 or later).

33.3. Extension Dependencies

Some extensions are dependent on other extensions to function. To enable extensions with dependencies, such required extensions must also be enabled through the same API mechanisms when creating an instance with vkCreateInstance or a device with vkCreateDevice. Each extension which has such dependencies documents them in the appendix summarizing that extension.

If an extension is supported (as queried by vkEnumerateInstanceExtensionProperties or vkEnumerateDeviceExtensionProperties), then required extensions of that extension must also be supported for the same instance or physical device.

Any device extension that has an instance extension dependency that is not enabled by vkCreateInstance is considered to be unsupported, hence it must not be returned by vkEnumerateDeviceExtensionProperties for any VkPhysicalDevice child of the instance.

33.4. Extension Compatibility

By default, all extensions are considered compatible with each other and any core API version, unless otherwise stated. Thus enabling such extensions does not otherwise alter the behavior of the application.

Each extension that is mutually exclusive or otherwise incompatible with another extension or set of extensions documents them in the appendix summarizing that extension and has a corresponding Valid Usage statement disallowing enabling such an incompatible combination of extensions at VkInstance creation time or VkDevice creation time, depending on the type of extensions participating in the interaction.