mirror of
https://github.com/godotengine/godot.git
synced 2024-11-23 20:53:15 +00:00
Add support for the debug utils extension in OpenXR
This commit is contained in:
parent
db76de5de8
commit
08ffa5d89e
@ -2948,6 +2948,12 @@
|
||||
<member name="xr/openxr/environment_blend_mode" type="int" setter="" getter="" default=""0"">
|
||||
Specify how OpenXR should blend in the environment. This is specific to certain AR and passthrough devices where camera images are blended in by the XR compositor.
|
||||
</member>
|
||||
<member name="xr/openxr/extensions/debug_message_types" type="int" setter="" getter="" default=""15"">
|
||||
Specifies the message types for which we request debug messages. Requires [member xr/openxr/extensions/debug_utils] to be set and the extension to be supported by the XR runtime.
|
||||
</member>
|
||||
<member name="xr/openxr/extensions/debug_utils" type="int" setter="" getter="" default=""0"">
|
||||
Enables debug utilities on XR runtimes that supports the debug utils extension. Sets the maximum severity being reported (0 = disabled, 1 = error, 2 = warning, 3 = info, 4 = verbose).
|
||||
</member>
|
||||
<member name="xr/openxr/extensions/eye_gaze_interaction" type="bool" setter="" getter="" default="false">
|
||||
Specify whether to enable eye tracking for this project. Depending on the platform, additional export configuration may be needed.
|
||||
</member>
|
||||
|
@ -2555,6 +2555,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
|
||||
GLOBAL_DEF_BASIC("xr/openxr/startup_alert", true);
|
||||
|
||||
// OpenXR project extensions settings.
|
||||
GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "xr/openxr/extensions/debug_utils", PROPERTY_HINT_ENUM, "Disabled,Error,Warning,Info,Verbose"), "0");
|
||||
GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "xr/openxr/extensions/debug_message_types", PROPERTY_HINT_FLAGS, "General,Validation,Performance,Conformance"), "15");
|
||||
GLOBAL_DEF_BASIC("xr/openxr/extensions/hand_tracking", false);
|
||||
GLOBAL_DEF_BASIC("xr/openxr/extensions/hand_tracking_unobstructed_data_source", false); // XR_HAND_TRACKING_DATA_SOURCE_UNOBSTRUCTED_EXT
|
||||
GLOBAL_DEF_BASIC("xr/openxr/extensions/hand_tracking_controller_data_source", false); // XR_HAND_TRACKING_DATA_SOURCE_CONTROLLER_EXT
|
||||
|
@ -17,12 +17,25 @@
|
||||
<link title="XrPosef documentation">https://registry.khronos.org/OpenXR/specs/1.0/man/html/XrPosef.html</link>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="begin_debug_label_region">
|
||||
<return type="void" />
|
||||
<param index="0" name="label_name" type="String" />
|
||||
<description>
|
||||
Begins a new debug label region, this label will be reported in debug messages for any calls following this until [method end_debug_label_region] is called. Debug labels can be stacked.
|
||||
</description>
|
||||
</method>
|
||||
<method name="can_render">
|
||||
<return type="bool" />
|
||||
<description>
|
||||
Returns [code]true[/code] if OpenXR is initialized for rendering with an XR viewport.
|
||||
</description>
|
||||
</method>
|
||||
<method name="end_debug_label_region">
|
||||
<return type="void" />
|
||||
<description>
|
||||
Marks the end of a debug label region. Removes the latest debug label region added by calling [method begin_debug_label_region].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_error_string">
|
||||
<return type="String" />
|
||||
<param index="0" name="result" type="int" />
|
||||
@ -88,6 +101,13 @@
|
||||
Returns the id of the system, which is a [url=https://registry.khronos.org/OpenXR/specs/1.0/man/html/XrSystemId.html]XrSystemId[/url] cast to an integer.
|
||||
</description>
|
||||
</method>
|
||||
<method name="insert_debug_label">
|
||||
<return type="void" />
|
||||
<param index="0" name="label_name" type="String" />
|
||||
<description>
|
||||
Inserts a debug label, this label is reported in any debug message resulting from the OpenXR calls that follows, until any of [method begin_debug_label_region], [method end_debug_label_region], or [method insert_debug_label] is called.
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_environment_blend_mode_alpha_supported">
|
||||
<return type="int" enum="OpenXRAPIExtension.OpenXRAlphaBlendModeSupport" />
|
||||
<description>
|
||||
@ -127,6 +147,15 @@
|
||||
If set to [code]true[/code], an OpenXR extension is loaded which is capable of emulating the [constant XRInterface.XR_ENV_BLEND_MODE_ALPHA_BLEND] blend mode.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_object_name">
|
||||
<return type="void" />
|
||||
<param index="0" name="object_type" type="int" />
|
||||
<param index="1" name="object_handle" type="int" />
|
||||
<param index="2" name="object_name" type="String" />
|
||||
<description>
|
||||
Set the object name of an OpenXR object, used for debug output. [param object_type] must be a valid OpenXR [code]XrObjectType[/code] enum and [param object_handle] must be a valid OpenXR object handle.
|
||||
</description>
|
||||
</method>
|
||||
<method name="transform_from_pose">
|
||||
<return type="Transform3D" />
|
||||
<param index="0" name="pose" type="const void*" />
|
||||
|
@ -58,7 +58,7 @@ HashMap<String, bool *> OpenXRCompositionLayerExtension::get_requested_extension
|
||||
return request_extensions;
|
||||
}
|
||||
|
||||
void OpenXRCompositionLayerExtension::on_session_created(const XrSession p_instance) {
|
||||
void OpenXRCompositionLayerExtension::on_session_created(const XrSession p_session) {
|
||||
OpenXRAPI::get_singleton()->register_composition_layer_provider(this);
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,7 @@ public:
|
||||
virtual ~OpenXRCompositionLayerExtension() override;
|
||||
|
||||
virtual HashMap<String, bool *> get_requested_extensions() override;
|
||||
virtual void on_session_created(const XrSession p_instance) override;
|
||||
virtual void on_session_created(const XrSession p_session) override;
|
||||
virtual void on_session_destroyed() override;
|
||||
virtual void on_pre_render() override;
|
||||
|
||||
|
287
modules/openxr/extensions/openxr_debug_utils_extension.cpp
Normal file
287
modules/openxr/extensions/openxr_debug_utils_extension.cpp
Normal file
@ -0,0 +1,287 @@
|
||||
/**************************************************************************/
|
||||
/* openxr_debug_utils_extension.cpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#include "openxr_debug_utils_extension.h"
|
||||
|
||||
#include "../openxr_api.h"
|
||||
#include "core/config/project_settings.h"
|
||||
#include "core/string/print_string.h"
|
||||
|
||||
#include <openxr/openxr.h>
|
||||
|
||||
OpenXRDebugUtilsExtension *OpenXRDebugUtilsExtension::singleton = nullptr;
|
||||
|
||||
OpenXRDebugUtilsExtension *OpenXRDebugUtilsExtension::get_singleton() {
|
||||
return singleton;
|
||||
}
|
||||
|
||||
OpenXRDebugUtilsExtension::OpenXRDebugUtilsExtension() {
|
||||
singleton = this;
|
||||
}
|
||||
|
||||
OpenXRDebugUtilsExtension::~OpenXRDebugUtilsExtension() {
|
||||
singleton = nullptr;
|
||||
}
|
||||
|
||||
HashMap<String, bool *> OpenXRDebugUtilsExtension::get_requested_extensions() {
|
||||
HashMap<String, bool *> request_extensions;
|
||||
|
||||
request_extensions[XR_EXT_DEBUG_UTILS_EXTENSION_NAME] = &debug_utils_ext;
|
||||
|
||||
return request_extensions;
|
||||
}
|
||||
|
||||
void OpenXRDebugUtilsExtension::on_instance_created(const XrInstance p_instance) {
|
||||
if (debug_utils_ext) {
|
||||
EXT_INIT_XR_FUNC(xrCreateDebugUtilsMessengerEXT);
|
||||
EXT_INIT_XR_FUNC(xrDestroyDebugUtilsMessengerEXT);
|
||||
EXT_INIT_XR_FUNC(xrSetDebugUtilsObjectNameEXT);
|
||||
EXT_INIT_XR_FUNC(xrSessionBeginDebugUtilsLabelRegionEXT);
|
||||
EXT_INIT_XR_FUNC(xrSessionEndDebugUtilsLabelRegionEXT);
|
||||
EXT_INIT_XR_FUNC(xrSessionInsertDebugUtilsLabelEXT);
|
||||
|
||||
debug_utils_ext = xrCreateDebugUtilsMessengerEXT_ptr && xrDestroyDebugUtilsMessengerEXT_ptr && xrSetDebugUtilsObjectNameEXT_ptr && xrSessionBeginDebugUtilsLabelRegionEXT_ptr && xrSessionEndDebugUtilsLabelRegionEXT_ptr && xrSessionInsertDebugUtilsLabelEXT_ptr;
|
||||
} else {
|
||||
WARN_PRINT("OpenXR: The debug utils extension is not available on this runtime. Debug logging is not enabled!");
|
||||
}
|
||||
|
||||
// On successful init, setup our default messenger.
|
||||
if (debug_utils_ext) {
|
||||
int max_severity = GLOBAL_GET("xr/openxr/extensions/debug_utils");
|
||||
int types = GLOBAL_GET("xr/openxr/extensions/debug_message_types");
|
||||
|
||||
XrDebugUtilsMessageSeverityFlagsEXT message_severities = 0;
|
||||
|
||||
if (max_severity >= 1) {
|
||||
message_severities |= XR_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
|
||||
}
|
||||
if (max_severity >= 2) {
|
||||
message_severities |= XR_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
|
||||
}
|
||||
if (max_severity >= 3) {
|
||||
message_severities |= XR_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
|
||||
}
|
||||
if (max_severity >= 4) {
|
||||
message_severities |= XR_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT;
|
||||
}
|
||||
|
||||
XrDebugUtilsMessageTypeFlagsEXT message_types = 0;
|
||||
|
||||
// These should match up but just to be safe and future proof...
|
||||
if (types & 1) {
|
||||
message_types |= XR_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
|
||||
}
|
||||
if (types & 2) {
|
||||
message_types |= XR_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
|
||||
}
|
||||
if (types & 4) {
|
||||
message_types |= XR_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
|
||||
}
|
||||
if (types & 8) {
|
||||
message_types |= XR_DEBUG_UTILS_MESSAGE_TYPE_CONFORMANCE_BIT_EXT;
|
||||
}
|
||||
|
||||
XrDebugUtilsMessengerCreateInfoEXT callback_info = {
|
||||
XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, // type
|
||||
nullptr, // next
|
||||
message_severities, // messageSeverities
|
||||
message_types, // messageTypes
|
||||
&OpenXRDebugUtilsExtension::_debug_callback, // userCallback
|
||||
nullptr, // userData
|
||||
};
|
||||
|
||||
XrResult result = xrCreateDebugUtilsMessengerEXT(p_instance, &callback_info, &default_messenger);
|
||||
if (XR_FAILED(result)) {
|
||||
ERR_PRINT("OpenXR: Failed to create debug callback [" + OpenXRAPI::get_singleton()->get_error_string(result) + "]");
|
||||
}
|
||||
|
||||
set_object_name(XR_OBJECT_TYPE_INSTANCE, uint64_t(p_instance), "Main Godot OpenXR Instance");
|
||||
}
|
||||
}
|
||||
|
||||
void OpenXRDebugUtilsExtension::on_instance_destroyed() {
|
||||
if (default_messenger != XR_NULL_HANDLE) {
|
||||
XrResult result = xrDestroyDebugUtilsMessengerEXT(default_messenger);
|
||||
if (XR_FAILED(result)) {
|
||||
ERR_PRINT("OpenXR: Failed to destroy debug callback [" + OpenXRAPI::get_singleton()->get_error_string(result) + "]");
|
||||
}
|
||||
|
||||
default_messenger = XR_NULL_HANDLE;
|
||||
}
|
||||
|
||||
xrCreateDebugUtilsMessengerEXT_ptr = nullptr;
|
||||
xrDestroyDebugUtilsMessengerEXT_ptr = nullptr;
|
||||
xrSetDebugUtilsObjectNameEXT_ptr = nullptr;
|
||||
xrSessionBeginDebugUtilsLabelRegionEXT_ptr = nullptr;
|
||||
xrSessionEndDebugUtilsLabelRegionEXT_ptr = nullptr;
|
||||
xrSessionInsertDebugUtilsLabelEXT_ptr = nullptr;
|
||||
debug_utils_ext = false;
|
||||
}
|
||||
|
||||
bool OpenXRDebugUtilsExtension::get_active() {
|
||||
return debug_utils_ext;
|
||||
}
|
||||
|
||||
void OpenXRDebugUtilsExtension::set_object_name(XrObjectType p_object_type, uint64_t p_object_handle, const char *p_object_name) {
|
||||
ERR_FAIL_COND(!debug_utils_ext);
|
||||
ERR_FAIL_NULL(xrSetDebugUtilsObjectNameEXT_ptr);
|
||||
|
||||
const XrDebugUtilsObjectNameInfoEXT space_name_info = {
|
||||
XR_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, // type
|
||||
nullptr, // next
|
||||
p_object_type, // objectType
|
||||
p_object_handle, // objectHandle
|
||||
p_object_name, // objectName
|
||||
};
|
||||
|
||||
XrResult result = xrSetDebugUtilsObjectNameEXT_ptr(OpenXRAPI::get_singleton()->get_instance(), &space_name_info);
|
||||
if (XR_FAILED(result)) {
|
||||
ERR_PRINT("OpenXR: Failed to set object name [" + OpenXRAPI::get_singleton()->get_error_string(result) + "]");
|
||||
}
|
||||
}
|
||||
|
||||
void OpenXRDebugUtilsExtension::begin_debug_label_region(const char *p_label_name) {
|
||||
ERR_FAIL_COND(!debug_utils_ext);
|
||||
ERR_FAIL_NULL(xrSessionBeginDebugUtilsLabelRegionEXT_ptr);
|
||||
|
||||
const XrDebugUtilsLabelEXT session_active_region_label = {
|
||||
XR_TYPE_DEBUG_UTILS_LABEL_EXT, // type
|
||||
NULL, // next
|
||||
p_label_name, // labelName
|
||||
};
|
||||
|
||||
XrResult result = xrSessionBeginDebugUtilsLabelRegionEXT_ptr(OpenXRAPI::get_singleton()->get_session(), &session_active_region_label);
|
||||
if (XR_FAILED(result)) {
|
||||
ERR_PRINT("OpenXR: Failed to begin label region [" + OpenXRAPI::get_singleton()->get_error_string(result) + "]");
|
||||
}
|
||||
}
|
||||
|
||||
void OpenXRDebugUtilsExtension::end_debug_label_region() {
|
||||
ERR_FAIL_COND(!debug_utils_ext);
|
||||
ERR_FAIL_NULL(xrSessionEndDebugUtilsLabelRegionEXT_ptr);
|
||||
|
||||
XrResult result = xrSessionEndDebugUtilsLabelRegionEXT_ptr(OpenXRAPI::get_singleton()->get_session());
|
||||
if (XR_FAILED(result)) {
|
||||
ERR_PRINT("OpenXR: Failed to end label region [" + OpenXRAPI::get_singleton()->get_error_string(result) + "]");
|
||||
}
|
||||
}
|
||||
|
||||
void OpenXRDebugUtilsExtension::insert_debug_label(const char *p_label_name) {
|
||||
ERR_FAIL_COND(!debug_utils_ext);
|
||||
ERR_FAIL_NULL(xrSessionInsertDebugUtilsLabelEXT_ptr);
|
||||
|
||||
const XrDebugUtilsLabelEXT session_active_region_label = {
|
||||
XR_TYPE_DEBUG_UTILS_LABEL_EXT, // type
|
||||
NULL, // next
|
||||
p_label_name, // labelName
|
||||
};
|
||||
|
||||
XrResult result = xrSessionInsertDebugUtilsLabelEXT_ptr(OpenXRAPI::get_singleton()->get_session(), &session_active_region_label);
|
||||
if (XR_FAILED(result)) {
|
||||
ERR_PRINT("OpenXR: Failed to insert label [" + OpenXRAPI::get_singleton()->get_error_string(result) + "]");
|
||||
}
|
||||
}
|
||||
|
||||
XrBool32 XRAPI_PTR OpenXRDebugUtilsExtension::_debug_callback(XrDebugUtilsMessageSeverityFlagsEXT p_message_severity, XrDebugUtilsMessageTypeFlagsEXT p_message_types, const XrDebugUtilsMessengerCallbackDataEXT *p_callback_data, void *p_user_data) {
|
||||
OpenXRDebugUtilsExtension *debug_utils = OpenXRDebugUtilsExtension::get_singleton();
|
||||
|
||||
if (debug_utils) {
|
||||
return debug_utils->debug_callback(p_message_severity, p_message_types, p_callback_data, p_user_data);
|
||||
}
|
||||
|
||||
return XR_FALSE;
|
||||
}
|
||||
|
||||
XrBool32 OpenXRDebugUtilsExtension::debug_callback(XrDebugUtilsMessageSeverityFlagsEXT p_message_severity, XrDebugUtilsMessageTypeFlagsEXT p_message_types, const XrDebugUtilsMessengerCallbackDataEXT *p_callback_data, void *p_user_data) {
|
||||
String msg;
|
||||
|
||||
ERR_FAIL_NULL_V(p_callback_data, XR_FALSE);
|
||||
|
||||
if (p_message_types == XR_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT) {
|
||||
msg = ", type: General";
|
||||
} else if (p_message_types == XR_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT) {
|
||||
msg = ", type: Validation";
|
||||
} else if (p_message_types == XR_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) {
|
||||
msg = ", type: Performance";
|
||||
} else if (p_message_types == XR_DEBUG_UTILS_MESSAGE_TYPE_CONFORMANCE_BIT_EXT) {
|
||||
msg = ", type: Conformance";
|
||||
} else {
|
||||
msg = ", type: Unknown (" + String::num_uint64(p_message_types) + ")";
|
||||
}
|
||||
|
||||
if (p_callback_data->functionName) {
|
||||
msg += ", function Name: " + String(p_callback_data->functionName);
|
||||
}
|
||||
if (p_callback_data->messageId) {
|
||||
msg += "\nMessage ID: " + String(p_callback_data->messageId);
|
||||
}
|
||||
if (p_callback_data->message) {
|
||||
msg += "\nMessage: " + String(p_callback_data->message);
|
||||
}
|
||||
|
||||
if (p_callback_data->objectCount > 0) {
|
||||
String objects;
|
||||
|
||||
for (uint32_t i = 0; i < p_callback_data->objectCount; i++) {
|
||||
if (!objects.is_empty()) {
|
||||
objects += ", ";
|
||||
}
|
||||
objects += p_callback_data->objects[i].objectName;
|
||||
}
|
||||
|
||||
msg += "\nObjects: " + objects;
|
||||
}
|
||||
|
||||
if (p_callback_data->sessionLabelCount > 0) {
|
||||
String labels;
|
||||
|
||||
for (uint32_t i = 0; i < p_callback_data->sessionLabelCount; i++) {
|
||||
if (!labels.is_empty()) {
|
||||
labels += ", ";
|
||||
}
|
||||
labels += p_callback_data->sessionLabels[i].labelName;
|
||||
}
|
||||
|
||||
msg += "\nLabels: " + labels;
|
||||
}
|
||||
|
||||
if (p_message_severity == XR_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) {
|
||||
ERR_PRINT("OpenXR: Severity: Error" + msg);
|
||||
} else if (p_message_severity == XR_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) {
|
||||
WARN_PRINT("OpenXR: Severity: Warning" + msg);
|
||||
} else if (p_message_severity == XR_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) {
|
||||
print_line("OpenXR: Severity: Info" + msg);
|
||||
} else if (p_message_severity == XR_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) {
|
||||
// This is a bit double because we won't output this unless verbose messaging in Godot is on.
|
||||
print_verbose("OpenXR: Severity: Verbose" + msg);
|
||||
}
|
||||
|
||||
return XR_FALSE;
|
||||
}
|
76
modules/openxr/extensions/openxr_debug_utils_extension.h
Normal file
76
modules/openxr/extensions/openxr_debug_utils_extension.h
Normal file
@ -0,0 +1,76 @@
|
||||
/**************************************************************************/
|
||||
/* openxr_debug_utils_extension.h */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef OPENXR_DEBUG_UTILS_EXTENSION_H
|
||||
#define OPENXR_DEBUG_UTILS_EXTENSION_H
|
||||
|
||||
#include "../util.h"
|
||||
#include "openxr_extension_wrapper.h"
|
||||
|
||||
class OpenXRDebugUtilsExtension : public OpenXRExtensionWrapper {
|
||||
public:
|
||||
static OpenXRDebugUtilsExtension *get_singleton();
|
||||
|
||||
OpenXRDebugUtilsExtension();
|
||||
virtual ~OpenXRDebugUtilsExtension() override;
|
||||
|
||||
virtual HashMap<String, bool *> get_requested_extensions() override;
|
||||
virtual void on_instance_created(const XrInstance p_instance) override;
|
||||
virtual void on_instance_destroyed() override;
|
||||
|
||||
bool get_active();
|
||||
|
||||
void set_object_name(XrObjectType p_object_type, uint64_t p_object_handle, const char *p_object_name);
|
||||
void begin_debug_label_region(const char *p_label_name);
|
||||
void end_debug_label_region();
|
||||
void insert_debug_label(const char *p_label_name);
|
||||
|
||||
private:
|
||||
static OpenXRDebugUtilsExtension *singleton;
|
||||
|
||||
// related extensions
|
||||
bool debug_utils_ext = false;
|
||||
|
||||
// debug handlers
|
||||
XrDebugUtilsMessengerEXT default_messenger = XR_NULL_HANDLE;
|
||||
|
||||
static XrBool32 XRAPI_PTR _debug_callback(XrDebugUtilsMessageSeverityFlagsEXT p_message_severity, XrDebugUtilsMessageTypeFlagsEXT p_message_types, const XrDebugUtilsMessengerCallbackDataEXT *p_callback_data, void *p_user_data);
|
||||
XrBool32 debug_callback(XrDebugUtilsMessageSeverityFlagsEXT p_message_severity, XrDebugUtilsMessageTypeFlagsEXT p_message_types, const XrDebugUtilsMessengerCallbackDataEXT *p_callback_data, void *p_user_data);
|
||||
|
||||
// OpenXR API call wrappers
|
||||
EXT_PROTO_XRRESULT_FUNC3(xrCreateDebugUtilsMessengerEXT, (XrInstance), p_instance, (const XrDebugUtilsMessengerCreateInfoEXT *), p_create_info, (XrDebugUtilsMessengerEXT *), p_messenger)
|
||||
EXT_PROTO_XRRESULT_FUNC1(xrDestroyDebugUtilsMessengerEXT, (XrDebugUtilsMessengerEXT), p_messenger)
|
||||
EXT_PROTO_XRRESULT_FUNC2(xrSetDebugUtilsObjectNameEXT, (XrInstance), p_instance, (const XrDebugUtilsObjectNameInfoEXT *), p_name_info)
|
||||
EXT_PROTO_XRRESULT_FUNC2(xrSessionBeginDebugUtilsLabelRegionEXT, (XrSession), p_session, (const XrDebugUtilsLabelEXT *), p_label_info)
|
||||
EXT_PROTO_XRRESULT_FUNC1(xrSessionEndDebugUtilsLabelRegionEXT, (XrSession), p_session)
|
||||
EXT_PROTO_XRRESULT_FUNC2(xrSessionInsertDebugUtilsLabelEXT, (XrSession), p_session, (const XrDebugUtilsLabelEXT *), p_label_info)
|
||||
};
|
||||
|
||||
#endif // OPENXR_DEBUG_UTILS_EXTENSION_H
|
@ -76,7 +76,7 @@ public:
|
||||
virtual void on_before_instance_created() {} // `on_before_instance_created` is called before we create our OpenXR instance.
|
||||
virtual void on_instance_created(const XrInstance p_instance) {} // `on_instance_created` is called right after we've successfully created our OpenXR instance.
|
||||
virtual void on_instance_destroyed() {} // `on_instance_destroyed` is called right before we destroy our OpenXR instance.
|
||||
virtual void on_session_created(const XrSession p_instance) {} // `on_session_created` is called right after we've successfully created our OpenXR session.
|
||||
virtual void on_session_created(const XrSession p_session) {} // `on_session_created` is called right after we've successfully created our OpenXR session.
|
||||
virtual void on_session_destroyed() {} // `on_session_destroyed` is called right before we destroy our OpenXR session.
|
||||
|
||||
// `on_process` is called as part of our OpenXR process handling,
|
||||
|
@ -54,6 +54,7 @@
|
||||
#endif
|
||||
|
||||
#include "extensions/openxr_composition_layer_depth_extension.h"
|
||||
#include "extensions/openxr_debug_utils_extension.h"
|
||||
#include "extensions/openxr_eye_gaze_interaction.h"
|
||||
#include "extensions/openxr_fb_display_refresh_rate_extension.h"
|
||||
#include "extensions/openxr_fb_foveation_extension.h"
|
||||
@ -316,6 +317,46 @@ String OpenXRAPI::get_swapchain_format_name(int64_t p_swapchain_format) const {
|
||||
return String("Swapchain format ") + String::num_int64(int64_t(p_swapchain_format));
|
||||
}
|
||||
|
||||
void OpenXRAPI::set_object_name(XrObjectType p_object_type, uint64_t p_object_handle, const String &p_object_name) {
|
||||
OpenXRDebugUtilsExtension *debug_utils = OpenXRDebugUtilsExtension::get_singleton();
|
||||
if (!debug_utils || !debug_utils->get_active()) {
|
||||
// Not enabled/active? Ignore.
|
||||
return;
|
||||
}
|
||||
|
||||
debug_utils->set_object_name(p_object_type, p_object_handle, p_object_name.utf8().get_data());
|
||||
}
|
||||
|
||||
void OpenXRAPI::begin_debug_label_region(const String &p_label_name) {
|
||||
OpenXRDebugUtilsExtension *debug_utils = OpenXRDebugUtilsExtension::get_singleton();
|
||||
if (!debug_utils || !debug_utils->get_active()) {
|
||||
// Not enabled/active? Ignore.
|
||||
return;
|
||||
}
|
||||
|
||||
debug_utils->begin_debug_label_region(p_label_name.utf8().get_data());
|
||||
}
|
||||
|
||||
void OpenXRAPI::end_debug_label_region() {
|
||||
OpenXRDebugUtilsExtension *debug_utils = OpenXRDebugUtilsExtension::get_singleton();
|
||||
if (!debug_utils || !debug_utils->get_active()) {
|
||||
// Not enabled/active? Ignore.
|
||||
return;
|
||||
}
|
||||
|
||||
debug_utils->end_debug_label_region();
|
||||
}
|
||||
|
||||
void OpenXRAPI::insert_debug_label(const String &p_label_name) {
|
||||
OpenXRDebugUtilsExtension *debug_utils = OpenXRDebugUtilsExtension::get_singleton();
|
||||
if (!debug_utils || !debug_utils->get_active()) {
|
||||
// Not enabled/active? Ignore.
|
||||
return;
|
||||
}
|
||||
|
||||
debug_utils->insert_debug_label(p_label_name.utf8().get_data());
|
||||
}
|
||||
|
||||
bool OpenXRAPI::load_layer_properties() {
|
||||
// This queries additional layers that are available and can be initialized when we create our OpenXR instance
|
||||
if (layer_properties != nullptr) {
|
||||
@ -826,6 +867,10 @@ bool OpenXRAPI::create_session() {
|
||||
return false;
|
||||
}
|
||||
|
||||
set_object_name(XR_OBJECT_TYPE_SESSION, uint64_t(session), "Main Godot OpenXR Session");
|
||||
|
||||
begin_debug_label_region("Godot session active");
|
||||
|
||||
for (OpenXRExtensionWrapper *wrapper : registered_extension_wrappers) {
|
||||
wrapper->on_session_created(session);
|
||||
}
|
||||
@ -916,6 +961,8 @@ bool OpenXRAPI::setup_play_space() {
|
||||
print_line("OpenXR: Failed to create LOCAL space in order to emulate LOCAL_FLOOR [", get_error_string(result), "]");
|
||||
will_emulate_local_floor = false;
|
||||
}
|
||||
|
||||
set_object_name(XR_OBJECT_TYPE_SPACE, uint64_t(local_floor_emulation.local_space), "Emulation local space");
|
||||
}
|
||||
|
||||
if (local_floor_emulation.stage_space == XR_NULL_HANDLE) {
|
||||
@ -931,6 +978,8 @@ bool OpenXRAPI::setup_play_space() {
|
||||
print_line("OpenXR: Failed to create STAGE space in order to emulate LOCAL_FLOOR [", get_error_string(result), "]");
|
||||
will_emulate_local_floor = false;
|
||||
}
|
||||
|
||||
set_object_name(XR_OBJECT_TYPE_SPACE, uint64_t(local_floor_emulation.stage_space), "Emulation stage space");
|
||||
}
|
||||
|
||||
if (!will_emulate_local_floor) {
|
||||
@ -972,6 +1021,8 @@ bool OpenXRAPI::setup_play_space() {
|
||||
play_space = new_play_space;
|
||||
reference_space = new_reference_space;
|
||||
|
||||
set_object_name(XR_OBJECT_TYPE_SPACE, uint64_t(play_space), "Play space");
|
||||
|
||||
local_floor_emulation.enabled = will_emulate_local_floor;
|
||||
local_floor_emulation.should_reset_floor_height = will_emulate_local_floor;
|
||||
|
||||
@ -1007,6 +1058,8 @@ bool OpenXRAPI::setup_view_space() {
|
||||
return false;
|
||||
}
|
||||
|
||||
set_object_name(XR_OBJECT_TYPE_SPACE, uint64_t(view_space), "View space");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1181,6 +1234,8 @@ bool OpenXRAPI::create_main_swapchains(Size2i p_size) {
|
||||
if (!render_state.main_swapchains[OPENXR_SWAPCHAIN_COLOR].create(0, XR_SWAPCHAIN_USAGE_SAMPLED_BIT | XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT | XR_SWAPCHAIN_USAGE_MUTABLE_FORMAT_BIT, color_swapchain_format, render_state.main_swapchain_size.width, render_state.main_swapchain_size.height, sample_count, view_count)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
set_object_name(XR_OBJECT_TYPE_SWAPCHAIN, uint64_t(render_state.main_swapchains[OPENXR_SWAPCHAIN_COLOR].get_swapchain()), "Main color swapchain");
|
||||
}
|
||||
|
||||
// We create our depth swapchain if:
|
||||
@ -1191,6 +1246,8 @@ bool OpenXRAPI::create_main_swapchains(Size2i p_size) {
|
||||
if (!render_state.main_swapchains[OPENXR_SWAPCHAIN_DEPTH].create(0, XR_SWAPCHAIN_USAGE_SAMPLED_BIT | XR_SWAPCHAIN_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, depth_swapchain_format, render_state.main_swapchain_size.width, render_state.main_swapchain_size.height, sample_count, view_count)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
set_object_name(XR_OBJECT_TYPE_SWAPCHAIN, uint64_t(render_state.main_swapchains[OPENXR_SWAPCHAIN_COLOR].get_swapchain()), "Main depth swapchain");
|
||||
}
|
||||
|
||||
// We create our velocity swapchain if:
|
||||
@ -1309,6 +1366,8 @@ void OpenXRAPI::destroy_session() {
|
||||
wrapper->on_session_destroyed();
|
||||
}
|
||||
|
||||
end_debug_label_region();
|
||||
|
||||
xrDestroySession(session);
|
||||
session = XR_NULL_HANDLE;
|
||||
}
|
||||
@ -2215,6 +2274,9 @@ void OpenXRAPI::pre_render() {
|
||||
}
|
||||
}
|
||||
|
||||
// We should get our frame no from the rendering server, but this will do.
|
||||
begin_debug_label_region(String("Session Frame ") + String::num_uint64(++render_state.frame));
|
||||
|
||||
// let's start our frame..
|
||||
XrFrameBeginInfo frame_begin_info = {
|
||||
XR_TYPE_FRAME_BEGIN_INFO, // type
|
||||
@ -2333,6 +2395,8 @@ void OpenXRAPI::end_frame() {
|
||||
return;
|
||||
}
|
||||
|
||||
end_debug_label_region(); // Session frame #
|
||||
|
||||
// neither eye is rendered
|
||||
return;
|
||||
}
|
||||
@ -2407,6 +2471,8 @@ void OpenXRAPI::end_frame() {
|
||||
print_line("OpenXR: failed to end frame! [", get_error_string(result), "]");
|
||||
return;
|
||||
}
|
||||
|
||||
end_debug_label_region(); // Session frame #
|
||||
}
|
||||
|
||||
float OpenXRAPI::get_display_refresh_rate() const {
|
||||
@ -2822,6 +2888,8 @@ RID OpenXRAPI::action_set_create(const String p_name, const String p_localized_n
|
||||
return RID();
|
||||
}
|
||||
|
||||
set_object_name(XR_OBJECT_TYPE_ACTION_SET, uint64_t(action_set.handle), p_name);
|
||||
|
||||
return action_set_owner.make_rid(action_set);
|
||||
}
|
||||
|
||||
@ -2997,6 +3065,8 @@ RID OpenXRAPI::action_create(RID p_action_set, const String p_name, const String
|
||||
return RID();
|
||||
}
|
||||
|
||||
set_object_name(XR_OBJECT_TYPE_ACTION, uint64_t(action.handle), p_name);
|
||||
|
||||
return action_owner.make_rid(action);
|
||||
}
|
||||
|
||||
|
@ -336,6 +336,7 @@ private:
|
||||
XrTime predicted_display_time = 0;
|
||||
XrSpace play_space = XR_NULL_HANDLE;
|
||||
double render_target_size_multiplier = 1.0;
|
||||
uint64_t frame = 0;
|
||||
|
||||
uint32_t view_count = 0;
|
||||
XrView *views = nullptr;
|
||||
@ -422,6 +423,10 @@ public:
|
||||
XrResult get_instance_proc_addr(const char *p_name, PFN_xrVoidFunction *p_addr);
|
||||
String get_error_string(XrResult result) const;
|
||||
String get_swapchain_format_name(int64_t p_swapchain_format) const;
|
||||
void set_object_name(XrObjectType p_object_type, uint64_t p_object_handle, const String &p_object_name);
|
||||
void begin_debug_label_region(const String &p_label_name);
|
||||
void end_debug_label_region();
|
||||
void insert_debug_label(const String &p_label_name);
|
||||
|
||||
OpenXRInterface *get_xr_interface() const { return xr_interface; }
|
||||
void set_xr_interface(OpenXRInterface *p_xr_interface);
|
||||
|
@ -43,6 +43,10 @@ void OpenXRAPIExtension::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("get_instance_proc_addr", "name"), &OpenXRAPIExtension::get_instance_proc_addr);
|
||||
ClassDB::bind_method(D_METHOD("get_error_string", "result"), &OpenXRAPIExtension::get_error_string);
|
||||
ClassDB::bind_method(D_METHOD("get_swapchain_format_name", "swapchain_format"), &OpenXRAPIExtension::get_swapchain_format_name);
|
||||
ClassDB::bind_method(D_METHOD("set_object_name", "object_type", "object_handle", "object_name"), &OpenXRAPIExtension::set_object_name);
|
||||
ClassDB::bind_method(D_METHOD("begin_debug_label_region", "label_name"), &OpenXRAPIExtension::begin_debug_label_region);
|
||||
ClassDB::bind_method(D_METHOD("end_debug_label_region"), &OpenXRAPIExtension::end_debug_label_region);
|
||||
ClassDB::bind_method(D_METHOD("insert_debug_label", "label_name"), &OpenXRAPIExtension::insert_debug_label);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("is_initialized"), &OpenXRAPIExtension::is_initialized);
|
||||
ClassDB::bind_method(D_METHOD("is_running"), &OpenXRAPIExtension::is_running);
|
||||
@ -116,6 +120,30 @@ String OpenXRAPIExtension::get_swapchain_format_name(int64_t p_swapchain_format)
|
||||
return OpenXRAPI::get_singleton()->get_swapchain_format_name(p_swapchain_format);
|
||||
}
|
||||
|
||||
void OpenXRAPIExtension::set_object_name(int64_t p_object_type, uint64_t p_object_handle, const String &p_object_name) {
|
||||
ERR_FAIL_NULL(OpenXRAPI::get_singleton());
|
||||
|
||||
OpenXRAPI::get_singleton()->set_object_name(XrObjectType(p_object_type), p_object_handle, p_object_name);
|
||||
}
|
||||
|
||||
void OpenXRAPIExtension::begin_debug_label_region(const String &p_label_name) {
|
||||
ERR_FAIL_NULL(OpenXRAPI::get_singleton());
|
||||
|
||||
OpenXRAPI::get_singleton()->begin_debug_label_region(p_label_name);
|
||||
}
|
||||
|
||||
void OpenXRAPIExtension::end_debug_label_region() {
|
||||
ERR_FAIL_NULL(OpenXRAPI::get_singleton());
|
||||
|
||||
OpenXRAPI::get_singleton()->end_debug_label_region();
|
||||
}
|
||||
|
||||
void OpenXRAPIExtension::insert_debug_label(const String &p_label_name) {
|
||||
ERR_FAIL_NULL(OpenXRAPI::get_singleton());
|
||||
|
||||
OpenXRAPI::get_singleton()->insert_debug_label(p_label_name);
|
||||
}
|
||||
|
||||
bool OpenXRAPIExtension::is_initialized() {
|
||||
ERR_FAIL_NULL_V(OpenXRAPI::get_singleton(), false);
|
||||
return OpenXRAPI::get_singleton()->is_initialized();
|
||||
|
@ -64,6 +64,10 @@ public:
|
||||
uint64_t get_instance_proc_addr(String p_name);
|
||||
String get_error_string(uint64_t result);
|
||||
String get_swapchain_format_name(int64_t p_swapchain_format);
|
||||
void set_object_name(int64_t p_object_type, uint64_t p_object_handle, const String &p_object_name);
|
||||
void begin_debug_label_region(const String &p_label_name);
|
||||
void end_debug_label_region();
|
||||
void insert_debug_label(const String &p_label_name);
|
||||
|
||||
bool is_initialized();
|
||||
bool is_running();
|
||||
|
@ -48,6 +48,7 @@
|
||||
|
||||
#include "extensions/openxr_composition_layer_depth_extension.h"
|
||||
#include "extensions/openxr_composition_layer_extension.h"
|
||||
#include "extensions/openxr_debug_utils_extension.h"
|
||||
#include "extensions/openxr_eye_gaze_interaction.h"
|
||||
#include "extensions/openxr_fb_display_refresh_rate_extension.h"
|
||||
#include "extensions/openxr_hand_interaction_extension.h"
|
||||
@ -133,6 +134,9 @@ void initialize_openxr_module(ModuleInitializationLevel p_level) {
|
||||
OpenXRAPI::register_extension_wrapper(memnew(OpenXRVisibilityMaskExtension));
|
||||
|
||||
// register gated extensions
|
||||
if (int(GLOBAL_GET("xr/openxr/extensions/debug_utils")) > 0) {
|
||||
OpenXRAPI::register_extension_wrapper(memnew(OpenXRDebugUtilsExtension));
|
||||
}
|
||||
if (GLOBAL_GET("xr/openxr/extensions/hand_tracking")) {
|
||||
OpenXRAPI::register_extension_wrapper(memnew(OpenXRHandTrackingExtension));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user