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

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


*Last Modified Date*::
    2021-04-14
*IP Status*::
    No known IP claims.
*Contributors*::
    Mark Young, LunarG +
    Karl Schultz, LunarG +
    Rylie Pavlik, Collabora +

*Overview*

Due to the nature of the OpenXR interface, there is very little error
information available to the developer and application.
By using the apiext:XR_EXT_debug_utils extension, developers can: obtain
more information.
When combined with validation layers, even more detailed feedback on the
application's use of OpenXR will be provided.

This extension provides the following capabilities:

  - The ability to create a debug messenger which will pass along debug
    messages to an application supplied callback.
  - The ability to identify specific OpenXR handles using a name to improve
    tracking.

[[ext_debug_utils-object-debug-annotation]]
==== Object Debug Annotation

It can be useful for an application to provide its own content relative to a
specific OpenXR handle.

[[ext_debug_utils-object-naming]]
===== Object Naming

flink:xrSetDebugUtilsObjectNameEXT allows application developers to
associate user-defined information with OpenXR handles.

This is useful when paired with the callback that you register when creating
an slink:XrDebugUtilsMessengerEXT object.
When properly used, debug messages will contain not only the corresponding
object handle, but the associated object name as well.

An application can change the name associated with an object simply by
calling flink:xrSetDebugUtilsObjectNameEXT again with a new string.
If the objectName member of the slink:XrDebugUtilsObjectNameInfoEXT
structure is an empty string, then any previously set name is removed.

[[ext_debug_utils-debug-messengers]]
==== Debug Messengers

OpenXR allows an application to register arbitrary number of callbacks with
all the OpenXR components wishing to report debug information.
Some callbacks can: log the information to a file, others can: cause a debug
break point or any other behavior defined by the application.
A primary producer of callback messages are the validation layers.
If the extension is enabled, an application can: register callbacks even
when no validation layers are enabled.
The OpenXR loader, other layers, and runtimes may: also produce callback
messages.

The debug messenger will provide detailed feedback on the application's use
of OpenXR when events of interest occur.
When an event of interest does occur, the debug messenger will submit a
debug message to the debug callback that was provided during its creation.
Additionally, the debug messenger is responsible with filtering out debug
messages that the callback isn't interested in and will only provide desired
debug messages.

[[ext_debug_utils-debug-message-categorization]]
==== Debug Message Categorization

Messages that are triggered by the debug messenger are categorized by their
message type and severity.
Additionally, each message has a string value identifying its
pname:messageId.
These 3 bits of information can be used to filter out messages so you only
receive reports on the messages you desire.
In fact, during debug messenger creation, the severity and type flag values
are provided to indicate what messages should be allowed to trigger the
user's callback.

===== Message Type

The message type indicates the general category the message falls under.
Currently we have the following message types:

.XR_EXT_debug_utils Message Type Flag Descriptions
[cols=",",options="header",]
|=======================================================================
|Enum |Description
|ename:XR_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT
    | Specifies a general purpose event type.
      This is typically a non-validation, non-performance event.
|ename:XR_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT
    | Specifies an event caused during a validation against the OpenXR specification
      that may: indicate invalid OpenXR usage.
|ename:XR_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT
    | Specifies a potentially non-optimal use of OpenXR.
|ename:XR_DEBUG_UTILS_MESSAGE_TYPE_CONFORMANCE_BIT_EXT
    | Specifies a non-conformant OpenXR result.
      This is typically caused by a layer or runtime returning non-conformant data.
|=======================================================================

A message may correspond to more than one type.
For example, if a validation warning also could impact performance, then the
message might be identified with both the
ename:XR_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT and
ename:XR_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT flag bits.


===== Message Severity

The severity of a message is a flag that indicates how important the message
is using standard logging naming.
The severity flag bit values are shown in the following table.

.XR_EXT_debug_utils Message Severity Flag Descriptions
[cols=",",options="header",]
|=======================================================================
|Enum |Description
|ename:XR_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT
    | Specifies the most verbose output indicating all diagnostic messages
      from the OpenXR loader, layers, and drivers should be captured.
|ename:XR_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT
    | Specifies an informational message such as resource details that might
      be handy when debugging an application.
|ename:XR_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT
    | Specifies use of OpenXR that could be an application bug.
      Such cases may: not be immediately harmful, such as providing too many
      swapchain images.
      Other cases may: point to behavior that is almost certainly bad when
      unintended, such as using a swapchain image whose memory has not been filled.
      In general, if you see a warning but you know that the behavior is
      intended/desired, then simply ignore the warning.
|ename:XR_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT
    | Specifies an error that may: cause undefined behavior, including an
      application crash.
|=======================================================================

[NOTE]
.Note
====
The values of elink:XrDebugUtilsMessageSeverityFlagBitsEXT are sorted based
on severity.
The higher the flag value, the more severe the message.
This allows for simple boolean operation comparisons when looking at
elink:XrDebugUtilsMessageSeverityFlagBitsEXT values.
====

===== Message IDs

The slink:XrDebugUtilsMessengerCallbackDataEXT structure contains a
pname:messageId that may be a string identifying the message ID for the
triggering debug message.
This may be blank, or it may simply contain the name of an OpenXR component
(like "OpenXR Loader").
However, when certain API layers or runtimes are used, especially the OpenXR
core_validation API layer, then this value is intended to uniquely identify
the message generated.
If a certain warning/error message constantly fires, a user can simply look
at the unique ID in their callback handler and manually filter it out.

For validation layers, this pname:messageId value actually can be used to
find the section of the OpenXR specification that the layer believes to have
been violated.
See the core_validation API Layer documentation for more information on how
this can be done.


[[ext_debug_utils-session-labels]]
==== Session Labels

All OpenXR work is performed inside of an slink:XrSession.
There are times that it helps to label areas in your OpenXR session to allow
easier debugging.
This can be especially true if your application creates more than one
session.
There are two kinds of labels provided in this extension:

* Region labels
* Individual labels

To begin identifying a region using a debug label inside a session, you may
use the flink:xrSessionBeginDebugUtilsLabelRegionEXT function.
Calls to flink:xrSessionBeginDebugUtilsLabelRegionEXT may be nested allowing
you to identify smaller and smaller labeled regions within your code.
Using this, you can build a "call-stack" of sorts with labels since any
logging callback will contain the list of all active session label regions.

To end the last session label region that was begun, you must: call
flink:xrSessionEndDebugUtilsLabelRegionEXT.
Each flink:xrSessionBeginDebugUtilsLabelRegionEXT must: have a matching
flink:xrSessionEndDebugUtilsLabelRegionEXT.
All of a session's label regions must: be closed before the
flink:xrDestroySession function is called for the given slink:XrSession.

An individual debug label may be inserted at any time using
flink:xrSessionInsertDebugUtilsLabelEXT.
The flink:xrSessionInsertDebugUtilsLabelEXT is used to indicate a particular
location within the execution of the application's session functions.
The next call to flink:xrSessionInsertDebugUtilsLabelEXT,
flink:xrSessionBeginDebugUtilsLabelRegionEXT, or
flink:xrSessionEndDebugUtilsLabelRegionEXT overrides this value.

*New Object Types*

[open,refpage='XrDebugUtilsMessengerEXT',type='handles',desc='Callback for debug data']
--
include::{generated}/api/handles/XrDebugUtilsMessengerEXT.adoc[]

slink:XrDebugUtilsMessengerEXT represents a callback function and associated
filters registered with the runtime.
--

*New Flag Types*

[open,refpage='XrDebugUtilsMessageSeverityFlagsEXT',type='flags',desc='XrDebugUtilsMessageSeverityFlagsEXT']
--
include::{generated}/api/flags/XrDebugUtilsMessageSeverityFlagsEXT.adoc[]
--

[open,refpage='XrDebugUtilsMessageSeverityFlagBitsEXT',type='enums',desc='XrDebugUtilsMessageSeverityFlagBitsEXT']
--
include::{generated}/api/enums/XrDebugUtilsMessageSeverityFlagBitsEXT.adoc[]
--

[open,refpage='XrDebugUtilsMessageTypeFlagsEXT',type='flags',desc='XrDebugUtilsMessageTypeFlagsEXT']
--
include::{generated}/api/flags/XrDebugUtilsMessageTypeFlagsEXT.adoc[]
--

[open,refpage='XrDebugUtilsMessageTypeFlagBitsEXT',type='enums',desc='XrDebugUtilsMessageTypeFlagBitsEXT']
--
include::{generated}/api/enums/XrDebugUtilsMessageTypeFlagBitsEXT.adoc[]
--

*New Enum Constants*

elink:XrStructureType enumeration is extended with:

* ename:XR_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT
* ename:XR_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT
* ename:XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT
* ename:XR_TYPE_DEBUG_UTILS_LABEL_EXT


*New Enums*


*New Structures*

[open,refpage='XrDebugUtilsObjectNameInfoEXT',type='structs',desc='Debug utils object name info']
--
include::{generated}/api/structs/XrDebugUtilsObjectNameInfoEXT.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:objectType is an elink:XrObjectType specifying the type of the
  object to be named.
* pname:objectHandle is the object to be named.
* pname:objectName is a code:NULL terminated UTF-8 string specifying the
  name to apply to objectHandle.
****

.Valid Usage
****
* If pname:objectType is ename:XR_OBJECT_TYPE_UNKNOWN, pname:objectHandle
  must: not be dlink:XR_NULL_HANDLE
* If pname:objectType is not ename:XR_OBJECT_TYPE_UNKNOWN,
  pname:objectHandle must: be dlink:XR_NULL_HANDLE or an OpenXR handle of
  the type associated with pname:objectType
****
include::{generated}/validity/structs/XrDebugUtilsObjectNameInfoEXT.adoc[]
--


[open,refpage='XrDebugUtilsLabelEXT',type='structs',desc='Debug Utils Label']
--
include::{generated}/api/structs/XrDebugUtilsLabelEXT.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:labelName is a code:NULL terminated UTF-8 string specifying the
  label name.
****

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

[open,refpage='XrDebugUtilsMessengerCallbackDataEXT',type='structs',desc='Debug utils messenger callback data']
--
include::{generated}/api/structs/XrDebugUtilsMessengerCallbackDataEXT.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:messageId is a code:NULL terminated string that identifies the
  message in a unique way.
  If the callback is triggered by a validation layer, this string
  corresponds the Valid Usage ID (VUID) that can be used to jump to the
  appropriate location in the OpenXR specification.
  This value may: be code:NULL if no unique message identifier is associated
  with the message.
* pname:functionName is a code:NULL terminated string that identifies the
  OpenXR function that was executing at the time the message callback was
  triggered.
  This value may: be code:NULL in cases where it is difficult to determine
  the originating OpenXR function.
* pname:message is a code:NULL terminated string detailing the trigger
  conditions.
* pname:objectCount is a count of items contained in the pname:objects
  array.
  This may be `0`.
* pname:objects is code:NULL or a pointer to an array of
  slink:XrDebugUtilsObjectNameInfoEXT objects related to the detected issue.
  The array is roughly in order of importance, but the 0th element is always
  guaranteed to be the most important object for this message.
* pname:sessionLabelCount is a count of items contained in the
  pname:sessionLabels array.
  This may be `0`.
* pname:sessionLabels is code:NULL or a pointer to an array of
  slink:XrDebugUtilsLabelEXT active in the current slink:XrSession at the
  time the callback was triggered.
  Refer to <<ext_debug_utils-session-labels>> for more information.
****

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

An slink:XrDebugUtilsMessengerCallbackDataEXT is a messenger object that
handles passing along debug messages to a provided debug callback.

[NOTE]
.Note
====
This structure should only be considered valid during the lifetime of the
triggered callback.
====

The labels listed inside pname:sessionLabels are organized in time order,
with the most recently generated label appearing first, and the oldest label
appearing last.
--

[open,refpage='XrDebugUtilsMessengerCreateInfoEXT',type='structs',desc='Debug utils messenger create info']
--
include::{generated}/api/structs/XrDebugUtilsMessengerCreateInfoEXT.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:messageSeverities is a bitmask of
  elink:XrDebugUtilsMessageSeverityFlagBitsEXT specifying which severity of
  event(s) that will cause this callback to be called.
* pname:messageTypes is a combination of
  elink:XrDebugUtilsMessageTypeFlagBitsEXT specifying which type of event(s)
  will cause this callback to be called.
* pname:userCallback is the application defined callback function to call.
* pname:userData is arbitrary user data to be passed to the callback.
****

.Valid Usage
****
* pname:userCallback must: be a valid PFN_xrDebugUtilsMessengerCallbackEXT
****

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

For each slink:XrDebugUtilsMessengerEXT that is created the
slink:XrDebugUtilsMessengerCreateInfoEXT::pname:messageSeverities and
slink:XrDebugUtilsMessengerCreateInfoEXT::pname:messageTypes determine when
that slink:XrDebugUtilsMessengerCreateInfoEXT::pname:userCallback is called.
The process to determine if the user's userCallback is triggered when an
event occurs is as follows:

* The runtime will perform a bitwise AND of the event's
  elink:XrDebugUtilsMessageSeverityFlagBitsEXT with the
  slink:XrDebugUtilsMessengerCreateInfoEXT::pname:messageSeverities provided
  during creation of the slink:XrDebugUtilsMessengerEXT object.

* If this results in `0`, the message is skipped.

* The runtime will perform bitwise AND of the event's
  elink:XrDebugUtilsMessageTypeFlagBitsEXT with the
  slink:XrDebugUtilsMessengerCreateInfoEXT::pname:messageTypes provided
  during the creation of the slink:XrDebugUtilsMessengerEXT object.

* If this results in `0`, the message is skipped.

* If the message of the current event is not skipped, the callback will be
  called with the message.

The callback will come directly from the component that detected the event,
unless some other layer intercepts the calls for its own purposes (filter
them in a different way, log to a system error log, etc.).
--

An application can: receive multiple callbacks if multiple
slink:XrDebugUtilsMessengerEXT objects are created.
A callback will always be executed in the same thread as the originating
OpenXR call.

[NOTE]
.Note
====
A callback can: be called from multiple threads simultaneously if the
application is making OpenXR calls from multiple threads.
====


*New Functions*

[open,refpage='xrSetDebugUtilsObjectNameEXT',type='protos',desc='Sets debug utils object name']
--
include::{generated}/api/protos/xrSetDebugUtilsObjectNameEXT.adoc[]

.Parameter Descriptions
****
* pname:instance is the slink:XrInstance that the object was created under.
* pname:nameInfo is a pointer to an instance of the
  slink:XrDebugUtilsObjectNameInfoEXT structure specifying the parameters of
  the name to set on the object.
****

.Valid Usage
****
* In the structure pointed to by pname:nameInfo,
  slink:XrDebugUtilsObjectNameInfoEXT::pname:objectType must: not be
  ename:XR_OBJECT_TYPE_UNKNOWN
* In the structure pointed to by pname:nameInfo,
  slink:XrDebugUtilsObjectNameInfoEXT::pname:objectHandle must: not be
  dlink:XR_NULL_HANDLE
****

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

Applications may: change the name associated with an object simply by
calling flink:xrSetDebugUtilsObjectNameEXT again with a new string.
If slink:XrDebugUtilsObjectNameInfoEXT::pname:objectName is an empty string,
then any previously set name is removed.
--

[open,refpage='xrCreateDebugUtilsMessengerEXT',type='protos',desc='Creates a debug messenger',xrefs='XrDebugUtilsMessengerCreateInfoEXT xrDestroyDebugUtilsMessengerEXT']
--
include::{generated}/api/protos/xrCreateDebugUtilsMessengerEXT.adoc[]

.Parameter Descriptions
****
* pname:instance is the instance the messenger will be used with.
* pname:createInfo points to an slink:XrDebugUtilsMessengerCreateInfoEXT
  structure, which contains the callback pointer as well as defines the
  conditions under which this messenger will trigger the callback.
* pname:messenger is a pointer to which the created
  slink:XrDebugUtilsMessengerEXT object is returned.
****

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

The application must: ensure that flink:xrCreateDebugUtilsMessengerEXT is
not executed in parallel with any OpenXR function that is also called with
pname:instance or child of pname:instance.

When an event of interest occurs a debug messenger calls its
slink:XrDebugUtilsMessengerCreateInfoEXT::pname:userCallback with a debug
message from the producer of the event.
Additionally, the debug messenger must: filter out any debug messages that
the application's callback is not interested in based on
slink:XrDebugUtilsMessengerCreateInfoEXT flags, as described below.
--

[open,refpage='xrDestroyDebugUtilsMessengerEXT',type='protos',desc='Destroys a debug messenger',xrefs='xrCreateDebugUtilsMessengerEXT XrDebugUtilsMessengerEXT']
--
include::{generated}/api/protos/xrDestroyDebugUtilsMessengerEXT.adoc[]

.Parameter Descriptions
****
* pname:messenger the slink:XrDebugUtilsMessengerEXT object to destroy.
  pname:messenger is an externally synchronized object and must: not be used
  on more than one thread at a time.
  This means that flink:xrDestroyDebugUtilsMessengerEXT must: not be called
  when a callback is active.
****

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

The application must: ensure that flink:xrDestroyDebugUtilsMessengerEXT is
not executed in parallel with any OpenXR function that is also called with
the `instance` or child of `instance` that it was created with.
--

[open,refpage='xrSubmitDebugUtilsMessageEXT',type='protos',desc='Submits debug utils message',xrefs='']
--
include::{generated}/api/protos/xrSubmitDebugUtilsMessageEXT.adoc[]

.Parameter Descriptions
****
* pname:instance is the debug stream's slink:XrInstance.
* pname:messageSeverity is a single bit value of
  elink:XrDebugUtilsMessageSeverityFlagsEXT severity of this event/message.
* pname:messageTypes is an elink:XrDebugUtilsMessageTypeFlagsEXT bitmask of
  elink:XrDebugUtilsMessageTypeFlagBitsEXT specifying which types of event
  to identify this message with.
* pname:callbackData contains all the callback related data in the
  slink:XrDebugUtilsMessengerCallbackDataEXT structure.
****

.Valid Usage
****
* For each structure in
  slink:XrDebugUtilsMessengerCallbackDataEXT::pname:objects, the value of
  slink:XrDebugUtilsObjectNameInfoEXT::pname:objectType must: not be
  ename:XR_OBJECT_TYPE_UNKNOWN
****

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

The application can: also produce a debug message, and submit it into the
OpenXR messaging system.

The call will propagate through the layers and generate callback(s) as
indicated by the message's flags.
The parameters are passed on to the callback in addition to the userData
value that was defined at the time the messenger was created.
--

[open,refpage='xrSessionBeginDebugUtilsLabelRegionEXT',type='protos',desc='Session begin debug utils label region',xrefs='XrDebugUtilsLabelEXT']
--
include::{generated}/api/protos/xrSessionBeginDebugUtilsLabelRegionEXT.adoc[]

.Parameter Descriptions
****
* pname:session is the slink:XrSession that a label region should be
  associated with.
* pname:labelInfo is the slink:XrDebugUtilsLabelEXT containing the label
  information for the region that should be begun.
****

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

The flink:xrSessionBeginDebugUtilsLabelRegionEXT function begins a label
region within pname:session.
--

[open,refpage='xrSessionEndDebugUtilsLabelRegionEXT',type='protos',desc='Session end debug utils label region',xrefs='']
--
include::{generated}/api/protos/xrSessionEndDebugUtilsLabelRegionEXT.adoc[]

.Parameter Descriptions
****
* pname:session is the slink:XrSession that a label region should be
  associated with.
****

.Valid Usage
****
* flink:xrSessionEndDebugUtilsLabelRegionEXT must: be called only after a
  matching flink:xrSessionBeginDebugUtilsLabelRegionEXT.
****

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

This function ends the last label region begun with the
flink:xrSessionBeginDebugUtilsLabelRegionEXT function within the same
pname:session.
--

[open,refpage='xrSessionInsertDebugUtilsLabelEXT',type='protos',desc='Session insert debug utils label',xrefs='xrSessionBeginDebugUtilsLabelRegionEXT xrSessionEndDebugUtilsLabelRegionEXT']
--
include::{generated}/api/protos/xrSessionInsertDebugUtilsLabelEXT.adoc[]

.Parameter Descriptions
****
* pname:session is the slink:XrSession that a label region should be
  associated with.
* pname:labelInfo is the slink:XrDebugUtilsLabelEXT containing the label
  information for the region that should be begun.
****

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

The flink:xrSessionInsertDebugUtilsLabelEXT function inserts an individual
label within pname:session.
The individual labels are useful for different reasons based on the type of
debugging scenario.
When used with something active like a profiler or debugger, it identifies a
single point of time.
When used with logging, the individual label identifies that a particular
location has been passed at the point the log message is triggered.
Because of this usage, individual labels only exist in a log until the next
call to any of the label functions:

* flink:xrSessionBeginDebugUtilsLabelRegionEXT
* flink:xrSessionEndDebugUtilsLabelRegionEXT
* flink:xrSessionInsertDebugUtilsLabelEXT
--

*New Function Pointers*

[open,refpage='PFN_xrDebugUtilsMessengerCallbackEXT',type='funcpointers',desc='Type of callback function invoked by the debug utils',xrefs='xrCreateDebugUtilsMessengerEXT XrDebugUtilsMessengerCreateInfoEXT']
--
include::{generated}/api/funcpointers/PFN_xrDebugUtilsMessengerCallbackEXT.adoc[]

.Parameter Descriptions
****
* pname:messageSeverity indicates the single bit value of
  elink:XrDebugUtilsMessageSeverityFlagsEXT that triggered this callback.
* pname:messageTypes indicates the elink:XrDebugUtilsMessageTypeFlagsEXT
  specifying which types of event triggered this callback.
* pname:callbackData contains all the callback related data in the
  slink:XrDebugUtilsMessengerCallbackDataEXT structure.
* pname:userData is the user data provided when the
  slink:XrDebugUtilsMessengerEXT was created.
****

The callback must: not call flink:xrDestroyDebugUtilsMessengerEXT.

The callback returns an basetype:XrBool32 that indicates to the calling
layer the application's desire to abort the call.
A value of ename:XR_TRUE indicates that the application wants to abort this
call.
If the application returns ename:XR_FALSE, the function must: not be
aborted.
Applications should: always return ename:XR_FALSE so that they see the same
behavior with and without validation layers enabled.

If the application returns ename:XR_TRUE from its callback and the OpenXR
call being aborted returns an elink:XrResult, the layer will return
ename:XR_ERROR_VALIDATION_FAILURE.

The object pointed to by pname:callbackData (and any pointers in it
recursively) must: be valid during the lifetime of the triggered callback.
It may: become invalid afterwards.
--

*Examples*

**Example 1**

+XR_EXT_debug_utils+ allows an application to register multiple callbacks
with any OpenXR component wishing to report debug information.
Some callbacks may log the information to a file, others may cause a debug
break point or other application defined behavior.
An application can: register callbacks even when no validation layers are
enabled, but they will only be called for loader and, if implemented, driver
events.

To capture events that occur while creating or destroying an instance an
application can: link an slink:XrDebugUtilsMessengerCreateInfoEXT structure
to the next element of the slink:XrInstanceCreateInfo structure given to
flink:xrCreateInstance.
This callback is only valid for the duration of the flink:xrCreateInstance
and the flink:xrDestroyInstance call.
Use flink:xrCreateDebugUtilsMessengerEXT to create persistent callback
objects.

Example uses: Create three callback objects.
One will log errors and warnings to the debug console using Windows
code:OutputDebugString.
The second will cause the debugger to break at that callback when an error
happens and the third will log warnings to stdout.

[source,c++]
------------------------------------------------------------------------------
    extern XrInstance instance;  // previously initialized

    // Must call extension functions through a function pointer:
    PFN_xrCreateDebugUtilsMessengerEXT pfnCreateDebugUtilsMessengerEXT;
    CHK_XR(xrGetInstanceProcAddr(instance, "xrCreateDebugUtilsMessengerEXT",
                                 reinterpret_cast<PFN_xrVoidFunction*>(
                                     &pfnCreateDebugUtilsMessengerEXT)));

    PFN_xrDestroyDebugUtilsMessengerEXT pfnDestroyDebugUtilsMessengerEXT;
    CHK_XR(xrGetInstanceProcAddr(instance, "xrDestroyDebugUtilsMessengerEXT",
                                 reinterpret_cast<PFN_xrVoidFunction*>(
                                     &pfnDestroyDebugUtilsMessengerEXT)));

    XrDebugUtilsMessengerCreateInfoEXT callback1 = {
        XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,   // type
        NULL,                                            // next
        XR_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT |  // messageSeverities
            XR_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT,
        XR_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |  // messageTypes
            XR_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT,
        myOutputDebugString,  // userCallback
        NULL                  // userData
    };
    XrDebugUtilsMessengerEXT messenger1 = XR_NULL_HANDLE;
    CHK_XR(pfnCreateDebugUtilsMessengerEXT(instance, &callback1, &messenger1));

    callback1.messageSeverities = XR_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
    callback1.userCallback = myDebugBreak;
    callback1.userData = NULL;
    XrDebugUtilsMessengerEXT messenger2 = XR_NULL_HANDLE;
    CHK_XR(pfnCreateDebugUtilsMessengerEXT(instance, &callback1, &messenger2));

    XrDebugUtilsMessengerCreateInfoEXT callback3 = {
        XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,    // type
        NULL,                                             // next
        XR_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT,  // messageSeverities
        XR_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |     // messageTypes
            XR_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT,
        myStdOutLogger,  // userCallback
        NULL             // userData
    };
    XrDebugUtilsMessengerEXT messenger3 = XR_NULL_HANDLE;
    CHK_XR(pfnCreateDebugUtilsMessengerEXT(instance, &callback3, &messenger3));

    // ...

    // Remove callbacks when cleaning up
    pfnDestroyDebugUtilsMessengerEXT(messenger1);
    pfnDestroyDebugUtilsMessengerEXT(messenger2);
    pfnDestroyDebugUtilsMessengerEXT(messenger3);
------------------------------------------------------------------------------

**Example 2**

Associate a name with an slink:XrSpace, for easier debugging in external
tools or with validation layers that can print a friendly name when
referring to objects in error messages.

[source,c++]
----------------------------------------
    extern XrInstance instance;  // previously initialized
    extern XrSpace space;        // previously initialized

    // Must call extension functions through a function pointer:
    PFN_xrSetDebugUtilsObjectNameEXT pfnSetDebugUtilsObjectNameEXT;
    CHK_XR(xrGetInstanceProcAddr(instance, "xrSetDebugUtilsObjectNameEXT",
                                 reinterpret_cast<PFN_xrVoidFunction*>(
                                     &pfnSetDebugUtilsObjectNameEXT)));

    // Set a name on the space
    const XrDebugUtilsObjectNameInfoEXT spaceNameInfo = {
        XR_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT,  // type
        NULL,                                      // next
        XR_OBJECT_TYPE_SPACE,                      // objectType
        (uint64_t)space,                           // objectHandle
        "My Object-Specific Space",                // objectName
    };

    pfnSetDebugUtilsObjectNameEXT(instance, &spaceNameInfo);

    // A subsequent error might print:
    //   Space "My Object-Specific Space" (0xc0dec0dedeadbeef) is used
    //   with an XrSession that is not it's parent.
----------------------------------------

**Example 3**

Labeling the workload with naming information so that any form of analysis
can display a more usable visualization of where actions occur in the
lifetime of a session.

[source,c++]
----------------------------------------
    extern XrInstance instance;  // previously initialized
    extern XrSession session;    // previously initialized

    // Must call extension functions through a function pointer:

    PFN_xrSessionBeginDebugUtilsLabelRegionEXT pfnSessionBeginDebugUtilsLabelRegionEXT;
    CHK_XR(xrGetInstanceProcAddr(instance, "xrSessionBeginDebugUtilsLabelRegionEXT",
                                 reinterpret_cast<PFN_xrVoidFunction*>(
                                     &pfnSessionBeginDebugUtilsLabelRegionEXT)));

    PFN_xrSessionEndDebugUtilsLabelRegionEXT pfnSessionEndDebugUtilsLabelRegionEXT;
    CHK_XR(xrGetInstanceProcAddr(instance, "xrSessionEndDebugUtilsLabelRegionEXT",
                                 reinterpret_cast<PFN_xrVoidFunction*>(
                                     &pfnSessionEndDebugUtilsLabelRegionEXT)));

    PFN_xrSessionInsertDebugUtilsLabelEXT pfnSessionInsertDebugUtilsLabelEXT;
    CHK_XR(xrGetInstanceProcAddr(instance, "xrSessionInsertDebugUtilsLabelEXT",
                                 reinterpret_cast<PFN_xrVoidFunction*>(
                                     &pfnSessionInsertDebugUtilsLabelEXT)));

    XrSessionBeginInfo session_begin_info = {
        XR_TYPE_SESSION_BEGIN_INFO,
        nullptr,
        XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO
    };
    xrBeginSession(session, &session_begin_info);

    const XrDebugUtilsLabelEXT session_active_region_label = {
        XR_TYPE_DEBUG_UTILS_LABEL_EXT,  // type
        NULL,                           // next
        "Session active",               // labelName
    };

    // Start an annotated region of calls under the 'Session Active' name
    pfnSessionBeginDebugUtilsLabelRegionEXT(session, &session_active_region_label);

    // Brackets added for clarity
    {
        XrDebugUtilsLabelEXT individual_label = {
            XR_TYPE_DEBUG_UTILS_LABEL_EXT,  // type
            NULL,                           // next
            "WaitFrame",                    // labelName
        };

        const char wait_frame_label[] = "WaitFrame";
        individual_label.labelName = wait_frame_label;
        pfnSessionInsertDebugUtilsLabelEXT(session, &individual_label);
        XrFrameWaitInfo wait_frame_info;  // initialization omitted for readability
        XrFrameState frame_state = {XR_TYPE_FRAME_STATE, nullptr};
        xrWaitFrame(session, &wait_frame_info, &frame_state);

        // Do stuff 1

        const XrDebugUtilsLabelEXT session_frame_region_label = {
            XR_TYPE_DEBUG_UTILS_LABEL_EXT,  // type
            NULL,                           // next
            "Session Frame 123",            // labelName
        };

        // Start an annotated region of calls under the 'Session Frame 123' name
        pfnSessionBeginDebugUtilsLabelRegionEXT(session, &session_frame_region_label);

        // Brackets added for clarity
        {

            const char begin_frame_label[] = "BeginFrame";
            individual_label.labelName = begin_frame_label;
            pfnSessionInsertDebugUtilsLabelEXT(session, &individual_label);

            XrFrameBeginInfo begin_frame_info;  // initialization omitted for readability
            xrBeginFrame(session, &begin_frame_info);

            // Do stuff 2

            const char end_frame_label[] = "EndFrame";
            individual_label.labelName = end_frame_label;
            pfnSessionInsertDebugUtilsLabelEXT(session, &individual_label);

            XrFrameEndInfo end_frame_info;  // initialization omitted for readability
            xrEndFrame(session, &end_frame_info);
        }

        // End the session/begun region started above
        // (in this case it's the "Session Frame 123" label)
        pfnSessionEndDebugUtilsLabelRegionEXT(session);
    }

    // End the session/begun region started above
    // (in this case it's the "Session Active" label)
    pfnSessionEndDebugUtilsLabelRegionEXT(session);
----------------------------------------

In the above example, if an error occurred in the `// Do stuff 1` section,
then your debug utils callback would contain the following data in its
pname:sessionLabels array:

* `[0]` = `individual_label` with `labelName` = "WaitFrame"
* `[1]` = `session_active_region_label` with `labelName` = "Session active"

However, if an error occurred in the `// Do stuff 2` section, then your
debug utils callback would contain the following data in its
pname:sessionLabels array:

* `[0]` = `individual_label` with `labelName` = "BeginFrame"
* `[1]` = `session_frame_region_label` with `labelName` = "Session Frame
  123"
* `[2]` = `session_active_region_label` with `labelName` = "Session active"

You'll notice that "WaitFrame" is no longer available as soon as the next
call to another function like flink:xrSessionBeginDebugUtilsLabelRegionEXT.

*Issues*

None

*Version History*

* Revision 1, 2018-02-19 (Mark Young / Karl Schultz)
** Initial draft, based on +VK_EXT_debug_utils+.
* Revision 2, 2018-11-16 (Mark Young)
** Clean up some language based on changes going into the Vulkan
   +VK_EXT_debug_utils+ extension by Peter Kraus (aka @krOoze).
** Added session labels
* Revision 3, 2019-07-19 (Rylie Pavlik)
** Update examples.
** Improve formatting.
* Revision 4, 2021-04-04 (Rylie Pavlik)
** Fix missing error code.
** Improve formatting.
* Revision 5, 2023-07-25 (John Kearney, Meta)
** `XrDebugUtilsMessengerCallbackDataEXT` parameters messageId and
   functionName to be optional.
