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

[[api-layer-interaction]]
== API Layer Interaction

This section details how the loader interacts with API layers.


[[api-layer-call-chains-and-distributed-dispatch]]
=== API Layer Call Chains and Distributed Dispatch

Remember, an API layer does not need to intercept all commands, instead, it
can choose to intercept only a subset.
Normally, when an API layer intercepts a given OpenXR command, it will call
down the <<openxr-call-chains,call chain>> as needed.
The loader and all enabled API layers that participate in a call chain
cooperate to ensure the correct sequencing of calls from one entity to the
next.
This group effort for call chain sequencing is hereinafter referred to as
*distributed dispatch*.

If an API layer does not wish to intercept a command, it must forward the
request made to its `xrGetInstanceProcAddr` implementation (provided through
pname:getInstanceProcAddr) down to the next `xrGetInstanceProcAddr`
implementation in the call chain (provided to the API layer through
pname:nextGetInstanceProcAddr).

In distributed dispatch each API layer is responsible for properly calling
the next entity in the call chain.
This means that a dispatch mechanism is required for all OpenXR commands
that an API layer intercepts.

For example, if the enabled API layers intercepted only certain functions,
the call chain would look as follows:

image::images/optional_layer_function_impl.svg[align="center", title="Optional Function Example"]

[NOTE]
.Note
====
In the above example, notice that "API Layer A" fails to pass along the
information for "xrFunction6".
This may not be an error since some commands expect to only work with one
specific API layer (`xrEnumerateInstanceExtensionProperties` when
"layerName" is set).
However, a badly designed API layer could do something similar for other
commands.
====

The loader is responsible for dispatching all core and instance extension
OpenXR functions to the first entity in the call chain.


[[api-layer-discovery]]
=== API Layer Discovery

As mentioned in the <<implicit-vs-explicit-api-layers, Implicit vs Explicit
API Layers>> section, API layers can be categorized into two categories:

* Implicit API layers
* Explicit API layers

The main difference between the two is that implicit API layers are
automatically enabled, unless overridden, and explicit API layers must be
manually enabled.

On any system, the loader looks in specific areas for information on the API
layers that it can load.
The process of finding the available API layers on a system is known as "API
Layer Discovery".
During "API Layer Discovery", the loader determines what API layers are
available and then grabs some basic information about each API layer: the
name, the version, and any extensions it supports.
This information is then provided back to the application through the
`xrEnumerateApiLayerProperties` command.

This section specifies the minimal conventions and rules an API layer must
follow, especially with regards to interacting with the loader and other API
layers.

On Windows and Linux systems, JSON formatted manifest files are used to
store API layer information.
In order to find OpenXR API layers, the OpenXR loader will read the JSON
files to identify the names and attributes of API layers and their
extensions.

[[desktop-api-layer-discovery]]
==== Desktop API Layer Discovery

On Desktop systems (such as Windows and Linux) JSON formatted manifest files
are used to store OpenXR component information.
The OpenXR loader will search specific areas of the computer for the
corresponding JSON manifest files that are used to identify the names and
attributes of OpenXR API layers.
The use of manifest files allows the loader to avoid actively loading the
shared library files until the application request causes them to be
activated.

The following sections define the standard locations the OpenXR loader
searches when looking for JSON manifest files.

[[windows-manifest-registry-usage]]
===== Windows Manifest Registry Usage

On Windows, the OpenXR loader will scan the Windows registry for details on
JSON manifest files in the following locations:

[NOTE]
.Note
====
The following table uses 2 acronyms:

* <HKLM> is used to indicate the top key of "HKEY_LOCAL_MACHINE"
* <HKCU> is used to indicate the top key of "HKEY_CURRENT_USER"

This is done purely to simplify the reading of the table
====

.Typical Windows Manifest File Registry Keys

[options="header",cols="10,10,30,50%"]
|====
| Windows OS Target | Binary Target | Base Registry Key (see note above) | Common Uses
.2+| 32-bit
    .2+| 32-bit
        l| <HKLM>\SOFTWARE\Khronos\OpenXR
            | Manifest files typically installed by some application for the
            entire system and all users on that system are found under this
            base key.
        l| <HKCU>\SOFTWARE\Khronos\OpenXR
            | Manifest files typically installed by some application for just
            the current user are found under this base key.
.2+| 64-bit
    .2+| 64-bit
        l| <HKLM>\SOFTWARE\Khronos\OpenXR
            | Manifest files for 64-bit OpenXR components are typically
            installed by some application for the entire system and all users
            on that system and recorded under this base key.
        l| <HKCU>\SOFTWARE\Khronos\OpenXR
            | Manifest files for 64-bit OpenXR components are typically
            installed by some application for just the current user
            and recorded under this base key.
.2+| 64-bit
    .2+| 32-bit
        l| <HKLM>\WOW6432Node\SOFTWARE\Khronos\OpenXR
            | Manifest files for 32-bit OpenXR components are typically
            installed by some application for the entire system and all users
            on that system and recorded under this base key.
        l| <HKCU>\WOW6432Node\SOFTWARE\Khronos\OpenXR
            | Manifest files for 32-bit OpenXR components are typically
            installed by some application for just the current user
            and recorded under this base key.
|====

When the OpenXR loader scans each of the appropriate registry keys based on
the Binary Target size, the loader will search under specific sub-keys for
the correct JSON manifest files based on the type of content stored in the
manifest file.

Additionally, the major version of the OpenXR API is used to separate up
each group of elements so that they do not conflict with one another in the
future.

Finally, each API layer type has their own sub-key under which their list of
available layers resides:

.Sub-Key Suffix for Manifest Search

[width="70%",options="header",cols="^.^40%e,^.^60%v"]
|====
| JSON Manifest File Type | Sub-key Suffix Added to Each Valid Key
| Implicit API Layer | ApiLayers\Implicit
| Explicit API Layer | ApiLayers\Explicit
|====

The following example shows possible keys searched for OpenXR 1.x explicit
API layers for a 64-bit loader on a 64-bit system.

[example]
.OpenXR 1.x Explicit Layer Windows' Registry Locations
====
----
HKEY_LOCAL_MACHINE\SOFTWARE\Khronos\OpenXR\1\ApiLayers\Explicit
HKEY_CURRENT_USER\SOFTWARE\Khronos\OpenXR\1\ApiLayers\Explicit
----
====

When searching for implicit API layers, the loader appends
`ApiLayers\Implicit` to each of the keys found.

Similar to the above example, this example shows the possible keys searched
for OpenXR 1.x implicit API layers for the same system as above.

[example]
.OpenXR 1.x Implicit Layer Windows' Registry Locations
====
----
HKEY_LOCAL_MACHINE\SOFTWARE\Khronos\OpenXR\1\ApiLayers\Implicit
HKEY_CURRENT_USER\SOFTWARE\Khronos\OpenXR\1\ApiLayers\Implicit
----
====

Each registry value under the above keys must: be defined in the following
way:

* The name of the value must: be the full path name to a valid manifest JSON
  file (including the ".json" suffix)
* The data for value must: be a DWORD
** In order for the loader to attempt to load the binary associated with
   this, the value must: be 0.
** To disable this manifest file so that the loader does not attempt to use
   it, set the value to a non-zero value.

For each value in these keys which has DWORD data set to 0, the loader opens
the manifest file specified by the name of the value.
The OpenXR loader will then obtain information about the library, including
the name and pathname of the shared library (".dll") file which defines the
actual API layer binary.

For example, let us assume the registry contains the following data:

----
[HKEY_LOCAL_MACHINE\SOFTWARE\Khronos\OpenXR\1\ApiLayers\Explicit\]

"C:\vendor a\layer_a.json"=dword:00000000
"C:\windows\system32\layer_b.json"=dword:00000001
"C:\windows\system32\layer_c.json"=dword:00000000
----

In this case, the loader will step through each entry, and check the value.
If the value is 0, then the loader will attempt to load the API layer
manifest file.
In this case, the loader will open the first and last listings, but not the
middle one.
This is because the value of 1 for layer_b.json disables the layer from
being loaded.


[[linux-manifest-search-paths]]
===== Linux Manifest Search Paths

On Linux, the OpenXR loader will scan for JSON manifest files using the
following base folders:

.Typical Linux Manifest File Search Directories

[options="header",cols="20%e,20%v,60%"]
|====
| Environment Variable | Common Locations | Common Uses
| XDG_CONFIG_DIRS
    | /etc/xdg
        | Defines common paths for config files
| SYSCONFDIR
    | /usr/local/etc
        | The directory for installing read-only data files that pertain to
        a single machine.  In this case, it is commonly used to store locally
        built API layers.
| EXTRASYSCONFDIR
    | /etc
        | Location of API layers installed from non-Linux-distribution-provided
        packages.
| XDG_DATA_DIRS
    | /usr/local/share, /usr/share/
        | Location of API layers installed from Linux-distribution-provided
        packages.
| XDG_DATA_HOME
    | $HOME/.local/share
        | Used to define manually enabled API layers per user.  $HOME is the
        current home directory of the application's user id; this
        path will be ignored for suid programs
|====

[NOTE]
.Note
====
The "/usr/local/*" directories can: be configured to be other directories at
build time.
====

When the OpenXR loader scans the directories defined by each of the above
environmental variables, it pulls out each individual path (tokenizing the
value based on the colon (:) separator), and then appends additional
sub-path information on the end of each based on the type of manifest file
being searched for.
The following table shows the sub-path information added onto the end of
each path based on the JSON manifest file type:

.Sub-Folder Suffix for Manifest Search

[width="70%",options="header",cols="^.^40%e,^.^60%v"]
|====
| JSON Manifest File Type | Sub-Folder Suffix Added to Each Path
| Implicit Layer | openxr/<major_version>/api_layers/implicit.d
| Explicit Layer | openxr/<major_version>/api_layers/explicit.d
|====

Where <major_version> is the integer number for the OpenXR API's major
version the API layers are associated with.

The following example shows possible search paths for OpenXR 1.x explicit
API layers (depending on the environmental variables defined on a user's
system).

[example]
.OpenXR 1.x Linux Explicit Layer Search Paths
====
----
/usr/local/etc/openxr/1/api_layers/explicit.d
/usr/local/share/openxr/1/api_layers/explicit.d
/etc/openxr/1/api_layers/explicit.d
/usr/share/openxr/1/api_layers/explicit.d
$HOME/.local/share/openxr/1/api_layers/explicit.d
----
====

When searching for OpenXR 1.x implicit API layers, the loader appends
`openxr/1/api_layers/implicit.d` to each of the paths found.

Similar to the above example, the following shows the search paths for
OpenXR 1.x implicit API layers for the same system as above.

[example]
.OpenXR 1.x Linux Implicit Layer Search Paths
====
----
/usr/local/etc/openxr/1/api_layers/implicit.d
/usr/local/share/openxr/1/api_layers/implicit.d
/etc/openxr/1/api_layers/implicit.d
/usr/share/openxr/1/api_layers/implicit.d
$HOME/.local/share/openxr/1/api_layers/implicit.d
----
====


[[overriding-the-default-api-layer-paths]]
===== Overriding the Default API Layer Paths

There may be times that a developer wishes to force the loader to use their
own explicit API layers (or specific explicit API layers).
In order to support this, the desktop loader can be forced to look in
specific paths for explicit API layers with the `XR_API_LAYER_PATH`
environment variable.
Simply set it to a properly delimited list of paths that you want the loader
to search for explicit API layer JSON Manifest files.
While relative paths may work, it is preferable to use absolute paths when
defining this environment variable to reduce issues.

[NOTE]
.Important
====
If the "XR_API_LAYER_PATH" environmental variable is defined, then the
desktop loader will not look in the standard locations to find explicit API
layers, instead looking only at the paths defined in that environment
variable.
Implicit API layers will always be discovered using the standard paths.
====

[example]
.Setting XR_API_LAYER_PATH Override
====
*Windows*

----
set XR_API_LAYER_PATH=<my_api_layer_path_1>;<my_api_layer_path_2>;<my_api_layer_path_3>
----

*Linux*

----
export XR_API_LAYER_PATH=<my_api_layer_path_1>:<my_api_layer_path_2>:<my_api_layer_path_3>
----
====

[[android-api-layer-discovery]]
==== Android API Layer Discovery

On Android the loader finds API layers by reading all
<<api-layer-manifest-file-format, Manifest files>> with the extension
.json. The following directories inside APK assets are used for explicit
and implicit layers:

----
openxr/__major_ver__/api_layers/implicit.d
openxr/__major_ver__/api_layers/explicit.d
----

[Note]
====
The loader accesses these using the Android AssetManager classes.
====

The loader also looks for system installed API layers in a similar process
as is used for active runtime discovery.
The following system directories are searched for
<<api-layer-manifest-file-format, Manifest files>> in the following priority
order for implicit and explicit API layers:

===== Implicit API Layers

1. `/product/etc/openxr/__major_ver__/api_layers/implicit.d`
2. `/odm/etc/openxr/__major_ver__/api_layers/implicit.d`
3. `/oem/etc/openxr/__major_ver__/api_layers/implicit.d`
4. `/system/etc/openxr/__major_ver__/api_layers/implicit.d`
5. `/vendor/etc/openxr/__major_ver__/api_layers/implicit.d`

===== Explicit API Layers

1. `/product/etc/openxr/__major_ver__/api_layers/explicit.d`
2. `/oem/etc/openxr/__major_ver__/api_layers/explicit.d`
3. `/vendor/etc/openxr/__major_ver__/api_layers/explicit.d`
4. `/system/etc/openxr/__major_ver__/api_layers/explicit.d`
5. `/odm/etc/openxr/__major_ver__/api_layers/explicit.d`

[[api-layer-manifest-file-format]]
==== API Layer Manifest File Format

On Windows, Linux and Android, the loader uses manifest files to discover
API layers.
The loader doesn't load the API layer libraries (e.g. DLL or .so files) for
each of the enabled API layers except during `xrCreateInstance` when it sets
up the call chain.
This is to reduce the likelihood of loading a malicious API layer into
memory.
Instead, details are read from the manifest file, which are then provided
for applications to determine what API layers should actually be loaded.

The following section discusses the details of the API layer manifest JSON
file format.
The JSON file itself does not have any requirements for naming.
The only requirement is that the filename extension is ".json".

[example]
.API Layer Manifest Examples
====
*Simple Explicit API Layer Manifest File*

[source,json]
----
{
   "file_format_version" : "1.0.0",
   "api_layer": {
       "name": "XR_APILAYER_LUNARG_test",
       "library_path": "xrTestLayer.dll",
       "api_version" : "1.0",
       "implementation_version" : "2",
       "description" : "LunarG test API layer"
   }
}
----

*More Complex Implicit API Layer Manifest File*

[source,json]
----
{
   "file_format_version" : "1.0.0",
   "api_layer": {
       "name": "XR_APILAYER_LUNARG_test",
       "library_path": "xrTestLayer.dll",
       "api_version" : "1.0",
       "implementation_version" : "2",
       "description" : "LunarG test API layer",
       "functions": {
           "xrNegotiateLoaderApiLayerInterface":
               "TestLayer_xrNegotiateLoaderApiLayerInterface"
       },
       "instance_extensions": [
           {
               "name": "XR_EXT_instance_extension_example",
               "extension_version": "1"
           }
       ],
       "enable_environment": "ENABLE_XR_API_LAYER_TEST_1",
       "disable_environment": "DISABLE_XR_API_LAYER_TEST_1"
   }
}
----
====

.API Layer Manifest JSON Fields

[width="70%",options="header",cols="<.^20%,^.^10%,<.^60%,^.^10%"]
|====
| JSON Node | API Layer Type | Description and Notes | Introspection Query
| "file_format_version"
    | *Required* for Implicit / Explicit
        | Manifest format major.minor.patch version number.  Currently only a
        value of 1.0.0 is supported.
            | N/A
| "api_layer"
    | *Required* for Implicit / Explicit
        | The identifier used to group a single API layer's information together.
            | `xrEnumerateApiLayerProperties`
| "name"
    | *Required* for Implicit / Explicit
        | The string used to uniquely identify this API layer to applications.
            | `xrEnumerateApiLayerProperties`
| "library_path"
    | *Required* for Implicit / Explicit
        | The "library_path" specifies either a filename, a relative pathname,
        or a full pathname to the API layer's shared library file.  If
        "library_path" specifies a relative pathname, it is relative to the
        path of the JSON manifest file (e.g. for cases when an application
        provides an API layer that is in the same folder hierarchy as the rest of
        the application files).  If "library_path" specifies a filename, the
        library must live in the system's shared object search path. There
        are no rules about the name of the API layer shared library files other
        than it should end with the appropriate suffix (".DLL" on Windows,
        and ".so" on Linux).
            | N/A
| "api_version"
    | *Required* for Implicit / Explicit
        | The major.minor (but not patch) version number of the OpenXR API that the
        shared library file for the library was built against. For example:
        1.0.
            | `xrEnumerateApiLayerProperties`
| "implementation_version"
    | *Required* for Implicit / Explicit
        | The version of the API layer implemented.  If the API layer itself has any
        major changes, this number should change so the loader and/or
        application can identify it properly.
            | `xrEnumerateApiLayerProperties`
| "description"
    | *Required* for Implicit / Explicit
        | A high-level description of the API layer and its intended use.
            | `xrEnumerateApiLayerProperties`
| "functions"
    | Optional for Implicit / Explicit
        | This section can be used to identify a different function name for
        the loader to use in place of standard API layer interface functions. The
        "functions" node is required if the API layer is using an alternative name
        for `xrNegotiateLoaderApiLayerInterface`.
            | `xrGetInstanceProcAddr` (except for `xrNegotiateLoaderApiLayerInterface`
            which must be queried using the OS/platform-specific
            `GetProcAddress`).
| "instance_extensions"
    | Optional for Implicit / Explicit
        | Contains the list of instance extension names supported by this
        API layer. One "instance_extensions" node with an array of one or more
        elements is required if any instance extensions are supported by a
        API layer, otherwise the node is optional. Each element of the array
        must have the nodes "name" and "extension_version" which correspond to
        `XrExtensionProperties` "extensionName" and "extensionVersion" respectively.
            | `xrEnumerateInstanceExtensionProperties`
| "enable_environment"
    | Optional for Implicit
        | Indicates an environment variable used to enable the implicit API layer.
        If provided in the JSON file, this environment variable (which should vary
        with each "version" of the API layer) must be set in the environment or else
        the implicit API layer is not loaded. This is for application environments
        (e.g. Steam) which want to enable an API layer(s) only for applications that
        they launch, and allows for applications run outside of that
        environment to not get that implicit API layer(s).
            | N/A
| "disable_environment"
    | *Required* for Implicit
        | Indicates an environment variable used to disable the implicit API layer.
        Required to allow users or applications to disable implicit layers that are
        not desired or that cause problems for the application. The user/application
        can set this environment variable (before calling OpenXR functions) to skip
        loading this API layer.
        This environment variable should vary with each "version" of the
        API layer.  If both the
        "enable_environment" and "disable_environment" variables are set, the
        implicit API layer is disabled.
            | N/A
|====

[NOTE]
.Note
====
If the same API layer shared library supports multiple, incompatible
versions of text manifest file format versions, it must have separate JSON
files for each (all of which may point to the same shared library).
====


[[api-layer-manifest-file-version-history]]
===== API Layer Manifest File Version History

The current highest supported API layer manifest file format supported is
1.0.0.
Information about each version is detailed in the following sub-sections:

_API Layer Manifest File Version 1.0.0_

The initial version of the API layer manifest file specified the basic
format and fields of an API layer JSON file.
The fields of the 1.0.0 file format include:

* "file_format_version"
* "api_layer"
* "name"
* "library_path"
* "api_version"
* "implementation_version"
* "description"
* "functions"
* "instance_extensions"
* "enable_environment"
* "disable_environment"


[[loader-api-layer-interface-negotiation]]
=== Loader/API Layer Interface Negotiation

Now that an API layer has been discovered, an application can choose to load
it (or it is loaded by default if it is an implicit API layer).
When the loader attempts to load the API layer, the first thing it does is
attempt to negotiate the version of the loader to API layer interface.
In order to negotiate the loader/API layer interface version, the API layer
must implement the fname:xrNegotiateLoaderApiLayerInterface function (or a
renamed version of this function identified in the manifest file).
See the declaration of fname:xrNegotiateLoaderApiLayerInterface in
`openxr_loader_negotiation.h`.


[[api-layer-interface-versions]]
==== API Layer Interface Versions

The current API layer interface is at version 1.
The following sections detail the differences between the various versions.


[[api-layer-interface-version-1]]
===== API Layer Interface Version 1

* Defined manifest file version 1.0.0.
* Introduced the concept of negotiation.
** Requires API layers to export `xrNegotiateLoaderApiLayerInterface`
   function.


[[api-layer-intercept-requirements]]
=== API Layer Intercept Requirements

* API Layers intercept an OpenXR command by defining a C/C++ function with
  signature *identical* to the OpenXR API for that command.
* The following commands are required: to be implemented by any API layer:
** `xrGetInstanceProcAddr`
** `xrCreateApiLayerInstance`
* The following commands must: not be implemented by any API layer:
** `xrCreateInstance`
* For any OpenXR command an API layer intercepts which has a non-void return
  value, an appropriate value must: be returned by the API layer intercept
  command.
* Most commands an API layer intercepts must: call down the chain to the
  corresponding OpenXR command in the next entity.
** The common behavior for an API layer is to intercept a call, perform some
   behavior, then pass it down to the next entity.
*** If a layer does not call down to the next entity for a given command,
    undefined behavior may occur.
    This is because the command will not be received by API layers and
    runtimes further down the call chain.
*** One command that cannot: call down the chain is:
**** `xrNegotiateLoaderApiLayerInterfaceVersion`
*** Some commands that may: choose to not call down the chain are:
**** `xrGetInstanceProcAddr`
* API layer intercept commands may: insert extra calls to OpenXR commands in
  addition to those that are intercepted
** If an API layer inserts new calls, that API layer must: pass along all
   new commands to the next entity.


[[api-layer-conventions-and-rules]]
=== API Layer Conventions and Rules

An API layer, when inserted into an otherwise compliant OpenXR
implementation, must still result in a compliant OpenXR implementation.
The intention is for API layers to have a well-defined baseline behavior.
Therefore, it must follow some conventions and rules defined below:

* An API layer may: be in a call chain with any number of API layers before
  or after it.
* It must: not make invalid calls to, or rely on undefined behaviors of, its
  lower API layers.
* If it changes the behavior of a function, it must: ensure the API layers
  called prior to itself do not make invalid calls because of the changed
  behavior.
** For example, if an API layer chooses to intercept an object creation
   function, and then wraps the objects created by lower API layers, it
   must: make sure the lower API layers never see the wrapped objects.
*** This means it must protect the lower API layers directly from itself or
    indirectly from its upper API layers.
* `xrEnumerateApiLayerProperties` must: return only its own API layer
  properties.
* `xrEnumerateInstanceExtensionProperties` must: obey the "layerName"
  parameter:
** If "layerName" is the name of this API layer, it must: return the
   contents of the instance extensions it supports.
** If "layerName" is NULL and:
*** It is an explicit API layer, it must: not fill in any data.
*** It is an implicit API layer, it must: add it's own instance extension
    contents to the list of extensions.
* For any OpenXR command the API layer intercepts, `xrGetInstanceProcAddr`
  must: return a pointer to a local entry point.
** Otherwise it returns the value obtained by calling down the instance call
   chain.


[[api-layer-create-instance-process]]
=== API Layer Create Instance Process

After <<loader-api-layer-interface-negotiation, interface negotiation>> and
any directed `xrEnumerateInstanceExtensionProperties` calls, the next time
an API layer is invoked is during the loader's `xrCreateInstance` call.
The API layer is only involved if it is in the enabled API layer list (this
includes implicit, environment variable enabled, and application enabled API
layers).
An API layer needs additional information during `xrCreateInstance` calls,
so each API layer must implement the fname:xrCreateApiLayerInstance
function, which is a special API layer function (declared in
`openxr_loader_negotiation.h`).

During the `xrCreateInstance` call, the following happens:

. The call enters the loader's trampoline function `xrCreateInstance`
. The loader will generate an instance of the sname:XrApiLayerCreateInfo
  structure
. The loader will go through each API layer in reverse order (i.e. starting with
  the layer closest to the runtime and ending with the API layer closest to
  the application):
.. Record the API layer's name, `xrGetInstanceProcAddr` address, and the
   `xrCreateApiLayerInstance` address.
.. Build a `XrApiLayerNextInfo` structure for the API layer recording the
   name and command addresses.
... If this is the first API layer (the one closest to the runtime) we want
    it to enter the loader again when we're done.
    So, the loader sets the following:
.... `XrApiLayerNextInfo.nextGetInstanceProcAddr` =
     `loaderXrTermGetInstanceProcAddr`
.... `XrApiLayerNextInfo.nextCreateLayerInstance` =
     `loaderXrTermCreateLayerInstance`
.... `XrApiLayerNextInfo.next` = NULL
... Otherwise, the loader sets the information to the previous API layer's
    information:
.... `XrApiLayerNextInfo.nextGetInstanceProcAddr` = Previous
     `XrApiLayerNextInfo.loaderXrTermGetInstanceProcAddr`
.... `XrApiLayerNextInfo.nextCreateLayerInstance` = Previous
     `XrApiLayerNextInfo.loaderXrTermCreateLayerInstance`
.... `XrApiLayerNextInfo.next` = address to previous `XrApiLayerNextInfo`
. The loader will then update the `XrApiLayerCreateInfo.nextInfo` to point to the
  last created `XrApiLayerNextInfo` since this is the first API layer in the
  call-chain.
. The loader calls the first API layer's fname:xrCreateApiLayerInstance command
  passing in the pointer to the created sname:XrApiLayerCreateInfo
. The API layer receives the information in its fname:xrCreateApiLayerInstance command.
. The API layer copies the sname:XrApiLayerCreateInfo structure into it's own structure.
. The API layer then updates it's version of the sname:XrApiLayerCreateInfo structure
  setting pname:nextInfo to point to the sname:XrApiLayerNextInfo for the
  next API layer (i.e. `XrApiLayerCreateInfo->nextInfo =
  XrApiLayerCreateInfo->nextInfo->next;`).
. The API layer may validate that it is getting the correct next information by
  checking that the pname:layerName matches.
. The API layer then uses the information out of its sname:XrApiLayerNextInfo to call
  down the call-chain to the next fname:xrCreateApiLayerInstance, using a
  pointer to its sname:XrApiLayerCreateInfo structure instead of the one
  that was passed in during its fname:xrCreateApiLayerInstance command.
.. If the call passes, this API layer may choose to setup its own dispatch
   table to the next API layer's commands using the returned `XrInstance`,
   the next API layer's `xrGetInstanceProcAddr` and the
   fname:GeneratedXrPopulateDispatchTable utility command provided in the
   generated `xr_generated_dispatch_table.h` header.
. Finally, the API layer should return the result passed in from the next API layer.
