// Copyright 2015-2024 The Khronos Group Inc.
//
// SPDX-License-Identifier: CC-BY-4.0

[[extendingvulkan]]
= Extending Vulkan

New functionality may: be added to Vulkan via either new extensions or new
versions of the core, or new versions of an extension in some cases.

This chapter describes how Vulkan is versioned, how compatibility is
affected between different versions, and compatibility rules that are
followed by the Vulkan Working Group.


[[extendingvulkan-instanceanddevicefunctionality]]
== Instance and Device Functionality

Commands that enumerate instance properties, or that accept a
slink:VkInstance object as a parameter, are considered instance-level
functionality.

Commands that dispatch from a slink:VkDevice object or a child object of a
slink:VkDevice, or take any of them as a parameter, are considered
device-level functionality.
Types defined by a <<extendingvulkan-device-extensions,device extension>>
are also considered device-level functionality.

Commands that dispatch from slink:VkPhysicalDevice, or accept a
slink:VkPhysicalDevice object as a parameter, are considered either
instance-level or device-level functionality depending if the functionality
is specified by an <<extendingvulkan-instance-extensions,instance
extension>> or <<extendingvulkan-device-extensions,device extension>>
respectively.

ifdef::VK_VERSION_1_1,VK_KHR_get_physical_device_properties2[]
Additionally, commands that enumerate physical device properties are
considered device-level functionality.
endif::VK_VERSION_1_1,VK_KHR_get_physical_device_properties2[]

ifdef::VK_VERSION_1_1[]
[NOTE]
.Note
====
Applications usually interface to Vulkan using a loader that implements only
instance-level functionality, passing device-level functionality to
implementations of the full Vulkan API on the system.
In some circumstances, as these may be implemented independently, it is
possible that the loader and device implementations on a given installation
will support different versions.
To allow for this and call out when it happens, the Vulkan specification
enumerates device and instance level functionality separately - they have
<<extendingvulkan-coreversions-queryingversionsupport,independent version
queries>>.
====
endif::VK_VERSION_1_1[]

ifdef::VK_VERSION_1_1,VK_KHR_get_physical_device_properties2[]
[NOTE]
.Note
====
Vulkan 1.0 initially specified new physical device enumeration functionality
as instance-level, requiring it to be included in an instance extension.
As the capabilities of device-level functionality require discovery via
physical device enumeration, this led to the situation where many device
extensions required an instance extension as well.
To alleviate this extra work,
`apiext:VK_KHR_get_physical_device_properties2` (and subsequently Vulkan
1.1) redefined device-level functionality to include physical device
enumeration.
====
endif::VK_VERSION_1_1,VK_KHR_get_physical_device_properties2[]


[[extendingvulkan-coreversions]]
== Core Versions

The Vulkan Specification is regularly updated with bug fixes and
clarifications.
Occasionally new functionality is added to the core and at some point it is
expected that there will be a desire to perform a large, breaking change to
the API.
In order to indicate to developers how and when these changes are made to
the specification, and to provide a way to identify each set of changes, the
Vulkan API maintains a version number.


[[extendingvulkan-coreversions-versionnumbers]]
=== Version Numbers

The Vulkan version number comprises four parts indicating the variant,
major, minor and patch version of the Vulkan API Specification.

The _variant_ indicates the variant of the Vulkan API supported by the
implementation.
ifndef::VKSC_VERSION_1_0[]
This is always 0 for the Vulkan API.
endif::VKSC_VERSION_1_0[]
ifdef::VKSC_VERSION_1_0[]
This is always 1 for the Vulkan SC API.
The Base Vulkan API is variant 0.
endif::VKSC_VERSION_1_0[]

[NOTE]
.Note
====
A non-zero variant indicates the API is a variant of the Vulkan API and
applications will typically need to be modified to run against it.
The variant field was a later addition to the version number, added in
version 1.2.175 of the
ifdef::VKSC_VERSION_1_0[Base Vulkan]
Specification.
ifndef::VKSC_VERSION_1_0[]
As Vulkan uses variant 0, this change is fully backwards compatible with the
previous version number format for Vulkan implementations.
New version number macros have been added for this change and the old macros
deprecated.
For existing applications using the older format and macros, an
implementation with non-zero variant will decode as a very high Vulkan
version.
The high version number should be detectable by applications performing
suitable version checking.
endif::VKSC_VERSION_1_0[]
====

The _major version_ indicates a significant change in the API, which will
encompass a wholly new version of the specification.

The _minor version_ indicates the incorporation of new functionality into
the core specification.

The _patch version_ indicates bug fixes, clarifications, and language
improvements have been incorporated into the specification.

Compatibility guarantees made about versions of the API sharing any of the
same version numbers are documented in
<<extendingvulkan-compatibility-coreversions>>

The version number is used in several places in the API.
In each such use, the version numbers are packed into a 32-bit integer as
follows:

  * The variant is a 3-bit integer packed into bits 31-29.
  * The major version is a 7-bit integer packed into bits 28-22.
  * The minor version number is a 10-bit integer packed into bits 21-12.
  * The patch version number is a 12-bit integer packed into bits 11-0.

[open,refpage='VK_API_VERSION_VARIANT',desc='Extract API variant number',type='defines']
--
dname:VK_API_VERSION_VARIANT extracts the API variant number from a packed
version number:

include::{generated}/api/defines/VK_API_VERSION_VARIANT.adoc[]
--

[open,refpage='VK_API_VERSION_MAJOR',desc='Extract API major version number',type='defines']
--
dname:VK_API_VERSION_MAJOR extracts the API major version number from a
packed version number:

include::{generated}/api/defines/VK_API_VERSION_MAJOR.adoc[]
--

ifndef::VKSC_VERSION_1_0[]
[open,refpage='VK_VERSION_MAJOR',desc='Extract API major version number',type='defines']
--
dname:VK_VERSION_MAJOR extracts the API major version number from a packed
version number:

include::{generated}/api/defines/VK_VERSION_MAJOR.adoc[]
--
endif::VKSC_VERSION_1_0[]

[open,refpage='VK_API_VERSION_MINOR',desc='Extract API minor version number',type='defines']
--
dname:VK_API_VERSION_MINOR extracts the API minor version number from a
packed version number:

include::{generated}/api/defines/VK_API_VERSION_MINOR.adoc[]
--

ifndef::VKSC_VERSION_1_0[]
[open,refpage='VK_VERSION_MINOR',desc='Extract API minor version number',type='defines']
--
dname:VK_VERSION_MINOR extracts the API minor version number from a packed
version number:

include::{generated}/api/defines/VK_VERSION_MINOR.adoc[]
--
endif::VKSC_VERSION_1_0[]

[open,refpage='VK_API_VERSION_PATCH',desc='Extract API patch version number',type='defines']
--
dname:VK_API_VERSION_PATCH extracts the API patch version number from a
packed version number:

include::{generated}/api/defines/VK_API_VERSION_PATCH.adoc[]
--

ifndef::VKSC_VERSION_1_0[]
[open,refpage='VK_VERSION_PATCH',desc='Extract API patch version number',type='defines']
--
dname:VK_VERSION_PATCH extracts the API patch version number from a packed
version number:

include::{generated}/api/defines/VK_VERSION_PATCH.adoc[]
--
endif::VKSC_VERSION_1_0[]

[open,refpage='VK_MAKE_API_VERSION',desc='Construct an API version number',type='defines',xrefs='VkApplicationInfo vkCreateInstance']
--
dname:VK_MAKE_API_VERSION constructs an API version number.

include::{generated}/api/defines/VK_MAKE_API_VERSION.adoc[]

  * pname:variant is the variant number.
  * pname:major is the major version number.
  * pname:minor is the minor version number.
  * pname:patch is the patch version number.
--

ifndef::VKSC_VERSION_1_0[]
[open,refpage='VK_MAKE_VERSION',desc='Construct an API version number',type='defines',xrefs='VkApplicationInfo vkCreateInstance']
--
dname:VK_MAKE_VERSION constructs an API version number.

include::{generated}/api/defines/VK_MAKE_VERSION.adoc[]

  * pname:major is the major version number.
  * pname:minor is the minor version number.
  * pname:patch is the patch version number.
--
endif::VKSC_VERSION_1_0[]

[open,refpage='VK_API_VERSION_1_0',desc='Return API version number for Vulkan 1.0',type='defines',xrefs='vkCreateInstance vkGetPhysicalDeviceProperties']
--
dname:VK_API_VERSION_1_0 returns the API version number for Vulkan 1.0.0.

include::{generated}/api/defines/VK_API_VERSION_1_0.adoc[]
--

ifdef::VK_VERSION_1_1[]
[open,refpage='VK_API_VERSION_1_1',desc='Return API version number for Vulkan 1.1',type='defines',xrefs='vkCreateInstance vkGetPhysicalDeviceProperties']
--
dname:VK_API_VERSION_1_1 returns the API version number for Vulkan 1.1.0.

include::{generated}/api/defines/VK_API_VERSION_1_1.adoc[]
--
endif::VK_VERSION_1_1[]

ifdef::VK_VERSION_1_2[]
[open,refpage='VK_API_VERSION_1_2',desc='Return API version number for Vulkan 1.2',type='defines',xrefs='vkCreateInstance vkGetPhysicalDeviceProperties']
--
dname:VK_API_VERSION_1_2 returns the API version number for Vulkan 1.2.0.

include::{generated}/api/defines/VK_API_VERSION_1_2.adoc[]
--
endif::VK_VERSION_1_2[]

ifdef::VK_VERSION_1_3[]
[open,refpage='VK_API_VERSION_1_3',desc='Return API version number for Vulkan 1.3',type='defines',xrefs='vkCreateInstance vkGetPhysicalDeviceProperties']
--
dname:VK_API_VERSION_1_3 returns the API version number for Vulkan 1.3.0.

include::{generated}/api/defines/VK_API_VERSION_1_3.adoc[]
--
endif::VK_VERSION_1_3[]

ifdef::VKSC_VERSION_1_0[]
[open,refpage='VKSC_API_VARIANT',desc='Returns the API variant number for Vulkan SC',type='defines']
--
dname:VKSC_API_VARIANT returns the API variant number for Vulkan SC.

include::{generated}/api/defines/VKSC_API_VARIANT.adoc[]
--

[open,refpage='VKSC_API_VERSION_1_0',desc='Return API version number for Vulkan SC 1.0',type='defines',xrefs='vkCreateInstance vkGetPhysicalDeviceProperties']
--
dname:VKSC_API_VERSION_1_0 returns the API version number for Vulkan SC
1.0.0.

include::{generated}/api/defines/VKSC_API_VERSION_1_0.adoc[]
--
endif::VKSC_VERSION_1_0[]


[[extendingvulkan-coreversions-queryingversionsupport]]
=== Querying Version Support

ifndef::VK_VERSION_1_1[]
[NOTE]
.Note
====
In Vulkan 1.0, there is no mechanism to detect the separate versions of
<<extendingvulkan-instanceanddevicefunctionality,instance-level and
device-level functionality>> supported.
However, the fname:vkEnumerateInstanceVersion command was added in Vulkan
1.1 to determine the supported version of instance-level functionality -
querying for this function via flink:vkGetInstanceProcAddr will return
`NULL` on implementations that only support Vulkan 1.0 functionality.
For more information on this, please refer to the Vulkan 1.1 specification.
====
endif::VK_VERSION_1_1[]

ifdef::VK_VERSION_1_1[]
The version of instance-level functionality can be queried by calling
flink:vkEnumerateInstanceVersion.
endif::VK_VERSION_1_1[]

The version of device-level functionality can be queried by calling
flink:vkGetPhysicalDeviceProperties
ifdef::VK_VERSION_1_1,VK_KHR_get_physical_device_properties2[]
or flink:vkGetPhysicalDeviceProperties2,
endif::VK_VERSION_1_1,VK_KHR_get_physical_device_properties2[]
and is returned in slink:VkPhysicalDeviceProperties::pname:apiVersion,
encoded as described in <<extendingvulkan-coreversions-versionnumbers>>.


[[extendingvulkan-layers]]
== Layers

When a layer is enabled, it inserts itself into the call chain for Vulkan
commands the layer is interested in.
Layers can: be used for a variety of tasks that extend the base behavior of
Vulkan beyond what is required by the specification - such as call logging,
tracing, validation, or providing additional extensions.

[NOTE]
.Note
====
For example, an implementation is not expected to check that the value of
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.
====

[NOTE]
.Note
====
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 <<LoaderInterfaceArchitecture, "`Architecture of the Vulkan Loader
Interfaces`">> document for additional information.
====

[open,refpage='vkEnumerateInstanceLayerProperties',desc='Returns up to requested number of global layer properties',type='protos']
--
To query the available layers, call:

include::{generated}/api/protos/vkEnumerateInstanceLayerProperties.adoc[]

  * pname:pPropertyCount is a pointer to an integer related to the number of
    layer properties available or queried, as described below.
  * pname:pProperties is either `NULL` or a pointer to an array of
    slink:VkLayerProperties structures.

If pname:pProperties is `NULL`, then the number of layer properties
available is returned in pname:pPropertyCount.
Otherwise, pname:pPropertyCount must: point to a variable set by the user to
the number of elements in the pname:pProperties array, and on return the
variable is overwritten with the number of structures actually written to
pname:pProperties.
If pname:pPropertyCount is less than the number of layer properties
available, at most pname:pPropertyCount structures will be written, and
ename:VK_INCOMPLETE will be returned instead of ename:VK_SUCCESS, to
indicate that not all the available 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
fname:vkEnumerateInstanceLayerProperties with the same parameters may:
return different results, or retrieve different pname:pPropertyCount values
or pname: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.

include::{generated}/validity/protos/vkEnumerateInstanceLayerProperties.adoc[]
--

[open,refpage='VkLayerProperties',desc='Structure specifying layer properties',type='structs']
--
The sname:VkLayerProperties structure is defined as:

include::{generated}/api/structs/VkLayerProperties.adoc[]

  * pname:layerName is an array of ename:VK_MAX_EXTENSION_NAME_SIZE
    code:char containing a null-terminated UTF-8 string which is the name of
    the layer.
    Use this name in the pname:ppEnabledLayerNames array passed in the
    slink:VkInstanceCreateInfo structure to enable this layer for an
    instance.
  * pname:specVersion is the Vulkan version the layer was written to,
    encoded as described in <<extendingvulkan-coreversions-versionnumbers>>.
  * pname:implementationVersion is the version of this layer.
    It is an integer, increasing with backward compatible changes.
  * pname:description is an array of ename:VK_MAX_DESCRIPTION_SIZE code:char
    containing a null-terminated UTF-8 string which provides additional
    details that can: be used by the application to identify the layer.

include::{generated}/validity/structs/VkLayerProperties.adoc[]
--

[open,refpage='VK_MAX_EXTENSION_NAME_SIZE',desc='Maximum length of a layer of extension name string',type='consts']
--
ename:VK_MAX_EXTENSION_NAME_SIZE is the length in code:char values of an
array containing a layer or extension name string, as returned in
slink:VkLayerProperties::pname:layerName,
slink:VkExtensionProperties::pname:extensionName, and other queries.

include::{generated}/api/enums/VK_MAX_EXTENSION_NAME_SIZE.adoc[]
--

[open,refpage='VK_MAX_DESCRIPTION_SIZE',desc='Length of a driver name string',type='consts']
--
ename:VK_MAX_DESCRIPTION_SIZE is the length in code:char values of an array
containing a string with additional descriptive information about a query,
as returned in slink:VkLayerProperties::pname:description and other queries.

include::{generated}/api/enums/VK_MAX_DESCRIPTION_SIZE.adoc[]
--

To enable a layer, the name of the layer should: be added to the
pname:ppEnabledLayerNames member of slink:VkInstanceCreateInfo when creating
a sname: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 pname:ppEnabledLayerNames
member of slink:VkInstanceCreateInfo are _explicitly enabled_.
Implicitly enabled layers are loaded before explicitly enabled layers, such
that implicitly enabled layers are closer to the application, and explicitly
enabled layers are closer to the driver.
Except where otherwise specified, implicitly enabled and explicitly enabled
layers differ only in the way they are enabled, and the order in which they
are loaded.
Explicitly enabling a layer that is implicitly enabled results in this layer
being loaded as an implicitly enabled layer; it has no additional effect.


[[extendingvulkan-layers-devicelayerdeprecation]]
=== 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
sname:VkInstance and sname:VkPhysicalDevice, except they were not able to
intercept flink: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.

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

[open,refpage='vkEnumerateDeviceLayerProperties',desc='Returns properties of available physical device layers',type='protos']
--
:refpage: vkEnumerateDeviceLayerProperties

To enumerate device layers, call:

include::{generated}/api/protos/vkEnumerateDeviceLayerProperties.adoc[]

  * pname:physicalDevice is the physical device that will be queried.
  * pname:pPropertyCount is a pointer to an integer related to the number of
    layer properties available or queried.
  * pname:pProperties is either `NULL` or a pointer to an array of
    slink:VkLayerProperties structures.

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

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

[NOTE]
.Note
====
Due to platform details on Android, fname:vkEnumerateDeviceLayerProperties
may be called with pname:physicalDevice equal to `NULL` during layer
discovery.
This behaviour will only be observed by layer implementations, and not the
underlying Vulkan driver.
====
endif::VKSC_VERSION_1_0[]
ifdef::VKSC_VERSION_1_0[]
Physical device layers are not supported.
pname:pPropertyCount is set to `0` and ename:VK_SUCCESS is returned.
endif::VKSC_VERSION_1_0[]

include::{generated}/validity/protos/vkEnumerateDeviceLayerProperties.adoc[]
--

The pname:ppEnabledLayerNames and pname:enabledLayerCount members of
slink:VkDeviceCreateInfo are deprecated and their values must: be ignored by
implementations.
ifndef::VKSC_VERSION_1_0[]
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 slink:VkDeviceCreateInfo,
the
endif::VKSC_VERSION_1_0[]
ifdef::VKSC_VERSION_1_0[The]
sequence of layers active for a device will be exactly the sequence of
layers enabled when the parent instance was created.


[[extendingvulkan-extensions]]
== 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 `{core_header}`
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 <<initialization-functionpointers>>.
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 <<LoaderInterfaceArchitecture, "`Architecture of the Vulkan Loader
Interfaces`">> document for additional information.

[NOTE]
.Note
====
To enable an instance extension, the name of the extension can: be added to
the pname:ppEnabledExtensionNames member of slink:VkInstanceCreateInfo when
creating a sname:VkInstance.

To enable a device extension, the name of the extension can: be added to the
pname:ppEnabledExtensionNames member of slink:VkDeviceCreateInfo when
creating a sname:VkDevice.

ifdef::VK_VERSION_1_1,VK_KHR_get_physical_device_properties2[]
Physical-Device-Level functionality does not have any enabling mechanism and
can: be used as long as the slink:VkPhysicalDevice supports the device
extension as determined by flink:vkEnumerateDeviceExtensionProperties.
endif::VK_VERSION_1_1,VK_KHR_get_physical_device_properties2[]

Enabling an extension (with no further use of that extension) does not
change the 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.

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 they might do so in the future.
It is defined only in the <<fundamentals-validusage-extensions>> section.
====


[[extendingvulkan-instance-extensions]]
=== Instance Extensions

Instance extensions add new
<<extendingvulkan-instanceanddevicefunctionality,instance-level
functionality>> to the API, outside of the core specification.

[open,refpage='vkEnumerateInstanceExtensionProperties',desc='Returns up to requested number of global extension properties',type='protos']
--
To query the available instance extensions, call:

include::{generated}/api/protos/vkEnumerateInstanceExtensionProperties.adoc[]

  * pname:pLayerName is either `NULL` or a pointer to a null-terminated
    UTF-8 string naming the layer to retrieve extensions from.
  * pname:pPropertyCount is a pointer to an integer related to the number of
    extension properties available or queried, as described below.
  * pname:pProperties is either `NULL` or a pointer to an array of
    slink:VkExtensionProperties structures.

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

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

Because the list of available layers may change externally between calls to
flink:vkEnumerateInstanceExtensionProperties, two calls may retrieve
different results if a pname: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.

Implementations must: not advertise any pair of extensions that cannot be
enabled together due to behavioral differences, or any extension that cannot
be enabled against the advertised version.

include::{generated}/validity/protos/vkEnumerateInstanceExtensionProperties.adoc[]
--


[[extendingvulkan-device-extensions]]
=== Device Extensions

Device extensions add new
<<extendingvulkan-instanceanddevicefunctionality,device-level
functionality>> to the API, outside of the core specification.

[open,refpage='vkEnumerateDeviceExtensionProperties',desc='Returns properties of available physical device extensions',type='protos']
--
:refpage: vkEnumerateDeviceExtensionProperties

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

include::{generated}/api/protos/vkEnumerateDeviceExtensionProperties.adoc[]

  * pname:physicalDevice is the physical device that will be queried.
  * pname:pLayerName is either `NULL` or a pointer to a null-terminated
    UTF-8 string naming the layer to retrieve extensions from.
  * pname: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
    flink:vkEnumerateInstanceExtensionProperties::pname:pPropertyCount
    parameter.
  * pname:pProperties is either `NULL` or a pointer to an array of
    slink:VkExtensionProperties structures.

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

Implementations must: not advertise any pair of extensions that cannot be
enabled together due to behavioral differences, or any extension that cannot
be enabled against the advertised version.

ifdef::VK_VERSION_1_3[]
Implementations claiming support for the <<roadmap-2022, Roadmap 2022>>
profile must: advertise the `apiext:VK_KHR_global_priority` extension in
pname:pProperties.
endif::VK_VERSION_1_3[]

[NOTE]
.Note
====
Due to platform details on Android,
fname:vkEnumerateDeviceExtensionProperties may be called with
pname:physicalDevice equal to `NULL` during layer discovery.
This behaviour will only be observed by layer implementations, and not the
underlying Vulkan driver.
====

include::{chapters}/commonvalidity/no_dynamic_allocations_common.adoc[]

include::{generated}/validity/protos/vkEnumerateDeviceExtensionProperties.adoc[]
--

[open,refpage='VkExtensionProperties',desc='Structure specifying an extension properties',type='structs']
--
The sname:VkExtensionProperties structure is defined as:

include::{generated}/api/structs/VkExtensionProperties.adoc[]

  * pname:extensionName is an array of ename:VK_MAX_EXTENSION_NAME_SIZE
    code:char containing a null-terminated UTF-8 string which is the name of
    the extension.
  * pname:specVersion is the version of this extension.
    It is an integer, incremented with backward compatible changes.

include::{generated}/validity/structs/VkExtensionProperties.adoc[]
--

[[extendingvulkan-accessing-device-physical-device]]
==== Accessing Device-Level Functionality From a slink:VkPhysicalDevice

Some device extensions also add support for physical-device-level
functionality.
Physical-device-level functionality can: be used, if the required extension
is supported as advertised by flink:vkEnumerateDeviceExtensionProperties for
a given slink:VkPhysicalDevice.

[[extendingvulkan-accessing-device-logical-device]]
==== Accessing Device-Level Functionality From a slink:VkDevice

For commands that are dispatched from a slink:VkDevice, or from a child
object of a slink:VkDevice, device extensions must: be enabled in
flink:vkCreateDevice.

[[extendingvulkan-extensions-extensiondependencies]]
== Extension Dependencies

Some extensions are dependent on other extensions, or on specific core API
versions, to function.
To enable extensions with dependencies, any _required extensions_ must: also
be enabled through the same API mechanisms when creating an instance with
flink:vkCreateInstance or a device with flink:vkCreateDevice.
Each extension which has such dependencies documents them in the
<<extensions, appendix summarizing that extension>>.

If an extension is supported (as queried by
flink:vkEnumerateInstanceExtensionProperties or
flink: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 flink:vkCreateInstance is considered to be unsupported, hence it
must: not be returned by flink:vkEnumerateDeviceExtensionProperties for any
slink:VkPhysicalDevice child of the instance.
Instance extensions do not have dependencies on device extensions.

If a required extension has been <<extendingvulkan-compatibility-promotion,
promoted>> to another extension or to a core API version, then as a
_general_ rule, the dependency is also satisfied by the promoted extension
or core version.
This will be true so long as any features required by the original extension
are also required or enabled by the promoted extension or core version.
However, in some cases an extension is promoted while making some of its
features optional in the promoted extension or core version.
In this case, the dependency may: not be satisfied.
The only way to be certain is to look at the descriptions of the original
dependency and the promoted version in the <<extensions, Layers &
Extensions>> and <<versions, Core Revisions>> appendices.

[NOTE]
.Note
====
There is metadata in `vk.xml` describing some aspects of promotion,
especially `requires`, `promotedto` and `deprecatedby` attributes of
`<extension>` tags.
However, the metadata does not yet fully describe this scenario.
In the future, we may extend the XML schema to describe the full set of
extensions and versions satisfying a dependency.
As discussed in more detail for <<extendingvulkan-compatibility-promotion,
Promotion>> below, when an extension is promoted it does not mean that a
mechanical substitution of an extension API by the corresponding promoted
API will work in exactly the same fashion; be supported at runtime; or even
exist.
====


== Compatibility Guarantees (Informative)

This section is marked as informal as there is no binding responsibility on
implementations of the Vulkan API - these guarantees are however a contract
between the Vulkan Working Group and developers using this Specification.


[[extendingvulkan-compatibility-coreversions]]
=== Core Versions

Each of the <<extendingvulkan-coreversions,major, minor, and patch
versions>> of the Vulkan specification provide different compatibility
guarantees.


==== Patch Versions

A difference in the patch version indicates that a set of bug fixes or
clarifications have been made to the Specification.
Informative enums returned by Vulkan commands that will not affect the
runtime behavior of a valid application may be added in a patch version
(e.g. elink:VkVendorId).

The specification's patch version is strictly increasing for a given major
version of the specification; any change to a specification as described
above will result in the patch version being increased by 1.
Patch versions are applied to all minor versions, even if a given minor
version is not affected by the provoking change.

Specifications with different patch versions but the same major and minor
version are _fully compatible_ with each other - such that a valid
application written against one will work with an implementation of another.

[NOTE]
.Note
====
If a patch version includes a bug fix or clarification that could have a
significant impact on developer expectations, these will be highlighted in
the change log.
Generally the Vulkan Working Group tries to avoid these kinds of changes,
instead fixing them in either an extension or core version.
====


==== Minor Versions

Changes in the minor version of the specification indicate that new
functionality has been added to the core specification.
This will usually include new interfaces in the header, and may: also
include behavior changes and bug fixes.
Core functionality may: be deprecated in a minor version, but will not be
obsoleted or removed.

The specification's minor version is strictly increasing for a given major
version of the specification; any change to a specification as described
above will result in the minor version being increased by 1.
Changes that can be accommodated in a patch version will not increase the
minor version.

Specifications with a lower minor version are _backwards compatible_ with an
implementation of a specification with a higher minor version for core
functionality and extensions issued with the KHR vendor tag.
Vendor and multi-vendor extensions are not guaranteed to remain functional
across minor versions, though in general they are with few exceptions - see
<<extendingvulkan-compatibility-obsoletion>> for more information.


==== Major Versions

A difference in the major version of specifications indicates a large set of
changes which will likely include interface changes, behavioral changes,
removal of <<extendingvulkan-compatibility-deprecation,deprecated
functionality>>, and the modification, addition, or replacement of other
functionality.

The specification's major version is monotonically increasing; any change to
the specification as described above will result in the major version being
increased.
Changes that can be accommodated in a patch or minor version will not
increase the major version.

The Vulkan Working Group intends to only issue a new major version of the
Specification in order to realise significant improvements to the Vulkan API
that will necessarily require breaking compatibility.

A new major version will likely include a wholly new version of the
specification to be issued - which could include an overhaul of the
versioning semantics for the minor and patch versions.
The patch and minor versions of a specification are therefore not meaningful
across major versions.
If a major version of the specification includes similar versioning
semantics, it is expected that the patch and the minor version will be reset
to 0 for that major version.


[[extendingvulkan-compatibility-extensions]]
=== Extensions

A KHR extension must: be able to be enabled alongside any other KHR
extension, and for any minor or patch version of the core Specification
beyond the minimum version it requires.
A multi-vendor extension should: be able to be enabled alongside any KHR
extension or other multi-vendor extension, and for any minor or patch
version of the core Specification beyond the minimum version it requires.
A vendor extension should: be able to be enabled alongside any KHR
extension, multi-vendor extension, or other vendor extension from the same
vendor, and for any minor or patch version of the core Specification beyond
the minimum version it requires.
A vendor extension may: be able to be enabled alongside vendor extensions
from another vendor.

The one other exception to this is if a vendor or multi-vendor extension is
<<extendingvulkan-compatibility-obsoletion, made obsolete>> by either a core
version or another extension, which will be highlighted in the
<<extensions,extension appendix>>.


[[extendingvulkan-compatibility-promotion]]
==== Promotion

Extensions, or features of an extension, may: be promoted to a new
<<versions,core version of the API>>, or a newer extension which an equal or
greater number of implementors are in favour of.

When extension functionality is promoted, minor changes may: be introduced,
limited to the following:

  * Naming
  * Non-intrusive parameter changes
  * <<features, Feature advertisement/enablement>>
  * Combining structure parameters into larger structures
  * Author ID suffixes changed or removed

[NOTE]
.Note
====
If extension functionality is promoted, there is no guarantee of direct
compatibility, however it should require little effort to port code from the
original feature to the promoted one.

The Vulkan Working Group endeavours to ensure that larger changes are marked
as either <<extendingvulkan-compatibility-deprecation, deprecated>> or
<<extendingvulkan-compatibility-obsoletion, obsoleted>> as appropriate, and
can do so retroactively if necessary.
====

Extensions that are promoted are listed as being promoted in their extension
appendices, with reference to where they were promoted to.

When an extension is promoted, any backwards compatibility aliases which
exist in the extension will *not* be promoted.

[NOTE]
.Note
====
As a hypothetical example, if the `apiext:VK_KHR_surface` extension were
promoted to part of a future core version, the
ename:VK_COLOR_SPACE_SRGB_NONLINEAR_KHR token defined by that extension
would be promoted to etext:VK_COLOR_SPACE_SRGB_NONLINEAR.
However, the etext:VK_COLORSPACE_SRGB_NONLINEAR_KHR token aliases
ename:VK_COLOR_SPACE_SRGB_NONLINEAR_KHR.
The etext:VK_COLORSPACE_SRGB_NONLINEAR_KHR would not be promoted, because it
is a backwards compatibility alias that exists only due to a naming mistake
when the extension was initially published.
====


[[extendingvulkan-compatibility-deprecation]]
==== Deprecation

Extensions may: be marked as deprecated when the intended use cases either
become irrelevant or can be solved in other ways.
Generally, a new feature will become available to solve the use case in
another extension or core version of the API, but it is not guaranteed.

[NOTE]
.Note
====
Features that are intended to replace deprecated functionality have no
guarantees of compatibility, and applications may require drastic
modification in order to make use of the new features.
====

Extensions that are deprecated are listed as being deprecated in their
extension appendices, with an explanation of the deprecation and any
features that are relevant.


[[extendingvulkan-compatibility-obsoletion]]
==== Obsoletion

Occasionally, an extension will be marked as obsolete if a new version of
the core API or a new extension is fundamentally incompatible with it.
An obsoleted extension must: not be used with the extension or core version
that obsoleted it.

Extensions that are obsoleted are listed as being obsoleted in their
extension appendices, with reference to what they were obsoleted by.


[[extendingvulkan-compatibility-aliases]]
==== Aliases

When an extension is promoted or deprecated by a newer feature, some or all
of its functionality may: be replicated into the newer feature.
Rather than duplication of all the documentation and definitions, the
specification instead identifies the identical commands and types as
_aliases_ of one another.
Each alias is mentioned together with the definition it aliases, with the
older aliases marked as "`equivalents`".
Each alias of the same command has identical behavior, and each alias of the
same type has identical meaning - they can be used interchangeably in an
application with no compatibility issues.

[NOTE]
.Note
====
For promoted types, the aliased extension type is semantically identical to
the new core type.
The C99 headers simply `typedef` the older aliases to the promoted types.

For promoted command aliases, however, there are two separate entry point
definitions, due to the fact that the C99 ABI has no way to alias command
definitions without resorting to macros.
Calling via either entry point definition will produce identical behavior
within the bounds of the specification, and should still invoke the same
entry point in the implementation.
Debug tools may use separate entry points with different debug behavior; to
write the appropriate command name to an output log, for instance.
====


[[extendingvulkan-compatibility-specialuse]]
==== Special Use Extensions

Some extensions exist only to support a specific purpose or specific class
of application.
These are referred to as "`special use extensions`".
Use of these extensions in applications not meeting the special use criteria
is not recommended.

Special use cases are restricted, and only those defined below are used to
describe extensions:

// The attributes in the "Special Use" column are defined in
// config/attribs.adoc, and used in reference pages as well as here.
// They define human-readable names for corresponding XML attribute values,
// so specialuse="cadsupport" -> "CAD Support". They are used in the table
// here and in the ExtensionMetaDocGenerator script that produces metadata
// includes for extension appendices. When introducing a new special use,
// the attribute and the table must both be extended.

[[extendingvulkan-specialuse-table]]
.Extension Special Use Cases
[width="100%",options="header",cols="25%,15%,60%"]
|====
| Special Use    | XML Tag      | Full Description
| {cadsupport}   | cadsupport
    | Extension is intended to support specialized functionality used by
      CAD/CAM applications.
| {d3demulation} | d3demulation
    | Extension is intended to support D3D emulation layers, and
      applications ported from D3D, by adding functionality specific to D3D.
| {devtools}     | devtools
    | Extension is intended to support developer tools such as
      capture-replay libraries.
| {debugging}    | debugging
    | Extension is intended for use by applications when debugging.
| {glemulation}  | glemulation
    | Extension is intended to support OpenGL and/or OpenGL ES emulation
      layers, and applications ported from those APIs, by adding
      functionality specific to those APIs.
|====

Special use extensions are identified in the metadata for each such
extension in the <<extensions, Layers & Extensions>> appendix, using the
name in the "`Special Use`" column above.

Special use extensions are also identified in `vk.xml` with the short name
in "`XML Tag`" column above, as described in the "`API Extensions
(`extension` tag)`" section of the <<vulkan-registry, registry schema
documentation>>.

