// Copyright (c) 2017-2024, The Khronos Group Inc.
//
// SPDX-License-Identifier: CC-BY-4.0

include::{generated}/meta/XR_KHR_vulkan_enable.adoc[]

*Last Modified Date*::
    2019-01-25
*IP Status*::
    No known IP claims.
*Contributors*::
    Mark Young, LunarG +
    Paul Pedriana, Oculus +
    Ed Hutchins, Oculus +
    Andres Rodriguez, Valve +
    Dan Ginsburg, Valve +
    Bryce Hutchings, Microsoft +
    Minmin Gong, Microsoft +
    Robert Menzel, NVIDIA +
    Paulo Gomes, Samsung Electronics

*Overview*

This extension enables the use of the Vulkan graphics API in an OpenXR
runtime.
Without this extension, the OpenXR runtime may not be able to use any Vulkan
swapchain images.

This extension provides the mechanisms necessary for an application to
generate a valid slink:XrGraphicsBindingVulkanKHR structure in order to
create a Vulkan-based slink:XrSession.
Note that during this process the application is responsible for creating
all the required Vulkan objects.

This extension also provides mechanisms for the application to interact with
images acquired by calling flink:xrEnumerateSwapchainImages.

In order to expose the structures, types, and functions of this extension,
you must: define dlink:XR_USE_GRAPHICS_API_VULKAN before including the
OpenXR platform header `openxr_platform.h`, in all portions of your library
or application that include it.

*Initialization*

Some of the requirements for creating a valid
slink:XrGraphicsBindingVulkanKHR include correct initialization of a
sname:VkInstance, sname:VkPhysicalDevice, and sname:VkDevice.

A runtime may: require that the sname:VkInstance be initialized to a
specific Vulkan API version.
Additionally, the runtime may: require a set of instance extensions to be
enabled in the sname:VkInstance.
These requirements can be queried by the application using
flink:xrGetVulkanGraphicsRequirementsKHR and
flink:xrGetVulkanInstanceExtensionsKHR, respectively.

Similarly, the runtime may: require the sname:VkDevice to have a set of
device extensions enabled, which can be queried using
flink:xrGetVulkanDeviceExtensionsKHR.

In order to satisfy the sname:VkPhysicalDevice requirements, the application
can query flink:xrGetVulkanGraphicsDeviceKHR to identify the correct
sname:VkPhysicalDevice.

Populating an slink:XrGraphicsBindingVulkanKHR with a sname:VkInstance,
sname:VkDevice, or sname:VkPhysicalDevice that does not meet the
requirements outlined by this extension may: result in undefined behavior by
the OpenXR runtime.

The API version, instance extension, device extension and physical device
requirements only apply to the sname:VkInstance, sname:VkDevice, and
sname:VkPhysicalDevice objects which the application wishes to associate
with an slink:XrGraphicsBindingVulkanKHR.

*Concurrency*

Vulkan requires that concurrent access to a sname:VkQueue from multiple
threads be externally synchronized.
Therefore, OpenXR functions that may access the sname:VkQueue specified in
the slink:XrGraphicsBindingVulkanKHR must also be externally synchronized.

The list of OpenXR functions where the OpenXR runtime may: access the
sname:VkQueue are:

* flink:xrBeginFrame
* flink:xrEndFrame
* flink:xrAcquireSwapchainImage
* flink:xrReleaseSwapchainImage

The runtime must: not access the sname:VkQueue in any OpenXR function that
is not listed above or in an extension definition.

*Swapchain Image Layout*

When an application acquires a swapchain image by calling
flink:xrAcquireSwapchainImage in a session created using
slink:XrGraphicsBindingVulkanKHR, the OpenXR runtime must: guarantee that:

* The image has a memory layout compatible with
  ename:VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL for color images, or
  ename:VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL for depth images.
* The sname:VkQueue specified in slink:XrGraphicsBindingVulkanKHR has
  ownership of the image.

When an application releases a swapchain image by calling
flink:xrReleaseSwapchainImage, in a session created using
slink:XrGraphicsBindingVulkanKHR, the OpenXR runtime must: interpret the
image as:

* Having a memory layout compatible with
  ename:VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL for color images, or
  ename:VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL for depth images.
* Being owned by the sname:VkQueue specified in
  slink:XrGraphicsBindingVulkanKHR.

The application is responsible for transitioning the swapchain image back to
the image layout and queue ownership that the OpenXR runtime requires.
If the image is not in a layout compatible with the above specifications the
runtime may: exhibit undefined behavior.

*Swapchain Flag Bits*

All elink:XrSwapchainUsageFlags values passed in a session created using
slink:XrGraphicsBindingVulkanKHR must: be interpreted as follows by the
runtime, so that the returned swapchain images used by the application may
be used as if they were created with at least the specified
`VkImageUsageFlagBits` or `VkImageCreateFlagBits` set.

[cols=2*,options=header]
|===
| elink:XrSwapchainUsageFlagBits
| Corresponding Vulkan flag bit

| ename:XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT
| `VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT`

| ename:XR_SWAPCHAIN_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
| `VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT`

| ename:XR_SWAPCHAIN_USAGE_UNORDERED_ACCESS_BIT
| `VK_IMAGE_USAGE_STORAGE_BIT`

| ename:XR_SWAPCHAIN_USAGE_TRANSFER_SRC_BIT
| `VK_IMAGE_USAGE_TRANSFER_SRC_BIT`

| ename:XR_SWAPCHAIN_USAGE_TRANSFER_DST_BIT
| `VK_IMAGE_USAGE_TRANSFER_DST_BIT`

| ename:XR_SWAPCHAIN_USAGE_SAMPLED_BIT
| `VK_IMAGE_USAGE_SAMPLED_BIT`

| ename:XR_SWAPCHAIN_USAGE_MUTABLE_FORMAT_BIT
| `VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT`

ifdef::XR_KHR_swapchain_usage_input_attachment_bit[]
| ename:XR_SWAPCHAIN_USAGE_INPUT_ATTACHMENT_BIT_KHR
  (Added by apiext:XR_KHR_swapchain_usage_input_attachment_bit and only available when that extension is enabled)
| `VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT`
endif::XR_KHR_swapchain_usage_input_attachment_bit[]

ifdef::XR_MND_swapchain_usage_input_attachment_bit[]
| ename:XR_SWAPCHAIN_USAGE_INPUT_ATTACHMENT_BIT_MND
  (Added by the now deprecated apiext:XR_MND_swapchain_usage_input_attachment_bit extension and only available when that extension is enabled)
| `VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT`
endif::XR_MND_swapchain_usage_input_attachment_bit[]

|===

*New Object Types*

*New Flag Types*

*New Enum Constants*

elink:XrStructureType enumeration is extended with:

* ename:XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR
* ename:XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR
* ename:XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR

*New Enums*

*New Structures*

The following structures are provided to supply supporting runtimes the
necessary information required to work with the Vulkan API executing on
certain operating systems.

[open,refpage='XrGraphicsBindingVulkanKHR',type='structs',desc='The graphics binding structure to be passed at session creation to use Vulkan',xrefs='xrCreateSession']
--
The slink:XrGraphicsBindingVulkanKHR structure is defined as:

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

.Member Descriptions
****
* pname:type is the elink:XrStructureType of this structure.
* pname:next is code:NULL or a pointer to the next structure in a structure
  chain.
  No such structures are defined in core OpenXR or this extension.
* pname:instance is a valid Vulkan sname:VkInstance.
* pname:physicalDevice is a valid Vulkan sname:VkPhysicalDevice.
* pname:device is a valid Vulkan sname:VkDevice.
* pname:queueFamilyIndex is a valid queue family index on pname:device.
* pname:queueIndex is a valid queue index on pname:device to be used for
  synchronization.
****

When creating a Vulkan-backed slink:XrSession, the application will provide
a pointer to an slink:XrGraphicsBindingVulkanKHR in the `next` chain of the
slink:XrSessionCreateInfo.

.Valid Usage
****
* pname:instance must: have enabled a Vulkan API version in the range
  specified by slink:XrGraphicsBindingVulkanKHR
* pname:instance must: have enabled all the instance extensions specified by
  flink:xrGetVulkanInstanceExtensionsKHR
* pname:physicalDevice sname:VkPhysicalDevice must: match the device
  specified by flink:xrGetVulkanGraphicsDeviceKHR
* pname:device must: have enabled all the device extensions specified by
  flink:xrGetVulkanDeviceExtensionsKHR
****

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

[open,refpage='XrSwapchainImageVulkanKHR',type='structs',desc='Vulkan-specific swapchain image structure',xrefs='XrSwapchainImageBaseHeader']
--
The slink:XrSwapchainImageVulkanKHR structure is defined as:

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

.Member Descriptions
****
* pname:type is the elink:XrStructureType of this structure.
* pname:next is code:NULL or a pointer to the next structure in a structure
  chain.
  No such structures are defined in core OpenXR or this extension.
* pname:image is a valid Vulkan sname:VkImage to use.
****

If a given session was created with slink:XrGraphicsBindingVulkanKHR, the
following conditions must: apply.

* Calls to flink:xrEnumerateSwapchainImages on an slink:XrSwapchain in that
  session must: return an array of slink:XrSwapchainImageVulkanKHR
  structures.
* Whenever an OpenXR function accepts an slink:XrSwapchainImageBaseHeader
  pointer as a parameter in that session, the runtime must: also accept a
  pointer to an slink:XrSwapchainImageVulkanKHR.

The OpenXR runtime must: interpret the top-left corner of the swapchain
image as the coordinate origin unless specified otherwise by extension
functionality.

The OpenXR runtime must: interpret the swapchain images in a clip space of
positive Y pointing down, near Z plane at 0, and far Z plane at 1.

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

[open,refpage='XrGraphicsRequirementsVulkanKHR',type='structs',desc='Vulkan API version requirements',xrefs='xrGetVulkanGraphicsRequirementsKHR']
--
The slink:XrGraphicsRequirementsVulkanKHR structure is defined as:

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

.Member Descriptions
****
* pname:type is the elink:XrStructureType of this structure.
* pname:next is code:NULL or a pointer to the next structure in a structure
  chain.
  No such structures are defined in core OpenXR or this extension.
* pname:minApiVersionSupported is the minimum Vulkan Instance API version
  that the runtime supports.
  Uses dlink:XR_MAKE_VERSION on major and minor API version, ignoring any
  patch version component.
* pname:maxApiVersionSupported is the maximum Vulkan Instance API version
  that the runtime has been tested on and is known to support.
  Newer Vulkan Instance API versions might work if they are compatible.
  Uses dlink:XR_MAKE_VERSION on major and minor API version, ignoring any
  patch version component.
****

slink:XrGraphicsRequirementsVulkanKHR is populated by
flink:xrGetVulkanGraphicsRequirementsKHR with the runtime's Vulkan API
version requirements.

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

*New Functions*

[open,refpage='xrGetVulkanGraphicsRequirementsKHR',type='protos',desc='Retrieve the Vulkan version requirements for an instance and system',xrefs='XrGraphicsRequirementsVulkanKHR']
--
To query Vulkan API version requirements, call:

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

.Parameter Descriptions
****
* pname:instance is an slink:XrInstance handle previously created with
  flink:xrCreateInstance.
* pname:systemId is an basetype:XrSystemId handle for the system which will
  be used to create a session.
* pname:graphicsRequirements is the slink:XrGraphicsRequirementsVulkanKHR
  output structure.
****

The flink:xrGetVulkanGraphicsRequirementsKHR function identifies to the
application the minimum Vulkan version requirement and the highest known
tested Vulkan version.
The runtime must: return ename:XR_ERROR_GRAPHICS_REQUIREMENTS_CALL_MISSING
(ename:XR_ERROR_VALIDATION_FAILURE may: be returned due to legacy behavior)
on calls to flink:xrCreateSession if
flink:xrGetVulkanGraphicsRequirementsKHR has not been called for the same
pname:instance and pname:systemId.

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

Some computer systems may have multiple graphics devices, each of which may
have independent external display outputs.
XR systems that connect to such graphics devices are typically connected to
a single device.
Applications need to know what graphics device the XR system is connected to
so that they can use that graphics device to generate XR images.

[open,refpage='xrGetVulkanGraphicsDeviceKHR',type='protos',desc='Retrieve the Vulkan physical device associated with an OpenXR instance and system']
--
To identify what graphics device needs to be used for an instance and
system, call:

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

.Parameter Descriptions
****
* pname:instance is an slink:XrInstance handle previously created with
  flink:xrCreateInstance.
* pname:systemId is an basetype:XrSystemId handle for the system which will
  be used to create a session.
* pname:vkInstance is a valid Vulkan sname:VkInstance.
* pname:vkPhysicalDevice is a pointer to a sname:VkPhysicalDevice value to
  populate.
****

flink:xrGetVulkanGraphicsDeviceKHR function identifies to the application
what graphics device (Vulkan sname:VkPhysicalDevice) needs to be used.
flink:xrGetVulkanGraphicsDeviceKHR must: be called prior to calling
flink:xrCreateSession, and the sname:VkPhysicalDevice that
flink:xrGetVulkanGraphicsDeviceKHR returns should be passed to
flink:xrCreateSession in the slink:XrGraphicsBindingVulkanKHR.

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

[open,refpage='xrGetVulkanInstanceExtensionsKHR',type='protos',desc='Get list of required Vulkan instance extensions for an OpenXR instance and system',xrefs='xrGetVulkanDeviceExtensionsKHR']
--
include::{generated}/api/protos/xrGetVulkanInstanceExtensionsKHR.adoc[]

.Parameter Descriptions
****
* pname:instance is an slink:XrInstance handle previously created with
  flink:xrCreateInstance.
* pname:systemId is an basetype:XrSystemId handle for the system which will
  be used to create a session.
* pname:bufferCapacityInput is the capacity of the pname:buffer, or 0 to
  indicate a request to retrieve the required capacity.
* pname:bufferCountOutput is a pointer to the count of characters written
  (including terminating `\0`), or a pointer to the required capacity in the
  case that pname:bufferCapacityInput is insufficient.
* pname:buffer is a pointer to an array of characters, but can: be code:NULL
  if pname:bufferCapacityInput is 0.
  The format of the output is a single space (ASCII `0x20`) delimited string
  of extension names.
* See the <<fundamentals-buffer-size-parameters>> section for a detailed
  description of retrieving the required pname:buffer size.
****

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

[open,refpage='xrGetVulkanDeviceExtensionsKHR',type='protos',desc='Get list of required Vulkan device extensions for an OpenXR instance and system',xrefs='xrGetVulkanInstanceExtensionsKHR']
--
include::{generated}/api/protos/xrGetVulkanDeviceExtensionsKHR.adoc[]

.Parameter Descriptions
****
* pname:instance is an slink:XrInstance handle previously created with
  flink:xrCreateInstance.
* pname:systemId is an basetype:XrSystemId handle for the system which will
  be used to create a session.
* pname:bufferCapacityInput is the capacity of the pname:buffer, or 0 to
  indicate a request to retrieve the required capacity.
* pname:bufferCountOutput is a pointer to the count of characters written
  (including terminating `\0`), or a pointer to the required capacity in the
  case that pname:bufferCapacityInput is insufficient.
* pname:buffer is a pointer to an array of characters, but can: be code:NULL
  if pname:bufferCapacityInput is 0.
  The format of the output is a single space (ASCII `0x20`) delimited string
  of extension names.
* See the <<fundamentals-buffer-size-parameters>> section for a detailed
  description of retrieving the required pname:buffer size.
****

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

*Issues*

*Version History*

* Revision 1, 2018-05-07 (Mark Young)
** Initial draft
* Revision 2, 2018-06-21 (Bryce Hutchings)
** Replace `session` parameter with `instance` and `systemId` parameters.
** Move `xrGetVulkanDeviceExtensionsKHR`, `xrGetVulkanInstanceExtensionsKHR`
   and `xrGetVulkanGraphicsDeviceKHR` functions into this extension
** Add new `XrGraphicsRequirementsVulkanKHR` function.
* Revision 3, 2018-11-15 (Paul Pedriana)
** Specified the swapchain texture coordinate origin.
* Revision 4, 2018-11-16 (Minmin Gong)
** Specified Y direction and Z range in clip space
* Revision 5, 2019-01-24 (Robert Menzel)
** Description updated
* Revision 6, 2019-01-25 (Andres Rodriguez)
** Reword sections of the spec to shift requirements on to the runtime
   instead of the app
* Revision 7, 2020-08-06 (Bryce Hutchings)
** Added new `XR_ERROR_GRAPHICS_REQUIREMENTS_CALL_MISSING` error code
* Revision 8, 2021-01-21 (Rylie Pavlik, Collabora, Ltd.)
** Document mapping for `XrSwapchainUsageFlags`
