Merge pull request #80881 from BastiaanOlij/openxr_foveation_ext

Implement OpenXR Foveated rendering support
This commit is contained in:
Rémi Verschelde 2023-09-25 17:18:00 +02:00
commit 9fdf24fa67
No known key found for this signature in database
GPG Key ID: C3336907360768E1
15 changed files with 675 additions and 74 deletions

View File

@ -2717,6 +2717,12 @@
<member name="xr/openxr/form_factor" type="int" setter="" getter="" default="&quot;0&quot;"> <member name="xr/openxr/form_factor" type="int" setter="" getter="" default="&quot;0&quot;">
Specify whether OpenXR should be configured for an HMD or a hand held device. Specify whether OpenXR should be configured for an HMD or a hand held device.
</member> </member>
<member name="xr/openxr/foveation_dynamic" type="bool" setter="" getter="" default="false">
If true and foveation is supported, will automatically adjust foveation level based on framerate up to the level set on [code]xr/openxr/foveation_level[/code].
</member>
<member name="xr/openxr/foveation_level" type="int" setter="" getter="" default="&quot;0&quot;">
Applied foveation level if supported: 0 = off, 1 = low, 2 = medium, 3 = high.
</member>
<member name="xr/openxr/reference_space" type="int" setter="" getter="" default="&quot;1&quot;"> <member name="xr/openxr/reference_space" type="int" setter="" getter="" default="&quot;1&quot;">
Specify the default reference space. Specify the default reference space.
</member> </member>

View File

@ -2087,6 +2087,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "xr/openxr/view_configuration", PROPERTY_HINT_ENUM, "Mono,Stereo"), "1"); // "Mono,Stereo,Quad,Observer" GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "xr/openxr/view_configuration", PROPERTY_HINT_ENUM, "Mono,Stereo"), "1"); // "Mono,Stereo,Quad,Observer"
GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "xr/openxr/reference_space", PROPERTY_HINT_ENUM, "Local,Stage"), "1"); GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "xr/openxr/reference_space", PROPERTY_HINT_ENUM, "Local,Stage"), "1");
GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "xr/openxr/environment_blend_mode", PROPERTY_HINT_ENUM, "Opaque,Additive,Alpha"), "0"); GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "xr/openxr/environment_blend_mode", PROPERTY_HINT_ENUM, "Opaque,Additive,Alpha"), "0");
GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "xr/openxr/foveation_level", PROPERTY_HINT_ENUM, "Off,Low,Medium,High"), "0");
GLOBAL_DEF_BASIC("xr/openxr/foveation_dynamic", false);
GLOBAL_DEF_BASIC("xr/openxr/submit_depth_buffer", false); GLOBAL_DEF_BASIC("xr/openxr/submit_depth_buffer", false);
GLOBAL_DEF_BASIC("xr/openxr/startup_alert", true); GLOBAL_DEF_BASIC("xr/openxr/startup_alert", true);

View File

@ -110,6 +110,8 @@ env_openxr.add_source_files(module_obj, "extensions/openxr_htc_controller_extens
env_openxr.add_source_files(module_obj, "extensions/openxr_htc_vive_tracker_extension.cpp") env_openxr.add_source_files(module_obj, "extensions/openxr_htc_vive_tracker_extension.cpp")
env_openxr.add_source_files(module_obj, "extensions/openxr_huawei_controller_extension.cpp") env_openxr.add_source_files(module_obj, "extensions/openxr_huawei_controller_extension.cpp")
env_openxr.add_source_files(module_obj, "extensions/openxr_hand_tracking_extension.cpp") env_openxr.add_source_files(module_obj, "extensions/openxr_hand_tracking_extension.cpp")
env_openxr.add_source_files(module_obj, "extensions/openxr_fb_foveation_extension.cpp")
env_openxr.add_source_files(module_obj, "extensions/openxr_fb_update_swapchain_extension.cpp")
env_openxr.add_source_files(module_obj, "extensions/openxr_fb_passthrough_extension_wrapper.cpp") env_openxr.add_source_files(module_obj, "extensions/openxr_fb_passthrough_extension_wrapper.cpp")
env_openxr.add_source_files(module_obj, "extensions/openxr_fb_display_refresh_rate_extension.cpp") env_openxr.add_source_files(module_obj, "extensions/openxr_fb_display_refresh_rate_extension.cpp")
env_openxr.add_source_files(module_obj, "extensions/openxr_pico_controller_extension.cpp") env_openxr.add_source_files(module_obj, "extensions/openxr_pico_controller_extension.cpp")

View File

@ -77,6 +77,13 @@
Returns [code]true[/code] if the given action set is active. Returns [code]true[/code] if the given action set is active.
</description> </description>
</method> </method>
<method name="is_foveation_supported" qualifiers="const">
<return type="bool" />
<description>
Returns [code]true[/code] if OpenXRs foveation extension is supported, the interface must be initialised before this returns a valid value.
[b]Note:[/b] This feature is only available on the compatibility renderer and currently only available on some stand alone headsets. For Vulkan set [member Viewport.vrs_mode] to [code]VRS_XR[/code] on desktop.
</description>
</method>
<method name="set_action_set_active"> <method name="set_action_set_active">
<return type="void" /> <return type="void" />
<param index="0" name="name" type="String" /> <param index="0" name="name" type="String" />
@ -98,6 +105,12 @@
<member name="display_refresh_rate" type="float" setter="set_display_refresh_rate" getter="get_display_refresh_rate" default="0.0"> <member name="display_refresh_rate" type="float" setter="set_display_refresh_rate" getter="get_display_refresh_rate" default="0.0">
The display refresh rate for the current HMD. Only functional if this feature is supported by the OpenXR runtime and after the interface has been initialized. The display refresh rate for the current HMD. Only functional if this feature is supported by the OpenXR runtime and after the interface has been initialized.
</member> </member>
<member name="foveation_dynamic" type="bool" setter="set_foveation_dynamic" getter="get_foveation_dynamic" default="false">
Enable dynamic foveation adjustment, the interface must be initialised before this is accessible. If enabled foveation will automatically adjusted between low and [member foveation_level].
</member>
<member name="foveation_level" type="int" setter="set_foveation_level" getter="get_foveation_level" default="0">
Set foveation level from 0 (off) to 3 (high), the interface must be initialised before this is accessible.
</member>
<member name="render_target_size_multiplier" type="float" setter="set_render_target_size_multiplier" getter="get_render_target_size_multiplier" default="1.0"> <member name="render_target_size_multiplier" type="float" setter="set_render_target_size_multiplier" getter="get_render_target_size_multiplier" default="1.0">
The render size multiplier for the current HMD. Must be set before the interface has been initialized. The render size multiplier for the current HMD. Must be set before the interface has been initialized.
</member> </member>

View File

@ -0,0 +1,168 @@
/**************************************************************************/
/* openxr_fb_foveation_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_fb_foveation_extension.h"
#include "core/config/project_settings.h"
OpenXRFBFoveationExtension *OpenXRFBFoveationExtension::singleton = nullptr;
OpenXRFBFoveationExtension *OpenXRFBFoveationExtension::get_singleton() {
return singleton;
}
OpenXRFBFoveationExtension::OpenXRFBFoveationExtension(const String &p_rendering_driver) {
singleton = this;
rendering_driver = p_rendering_driver;
swapchain_update_state_ext = OpenXRFBUpdateSwapchainExtension::get_singleton();
int fov_level = GLOBAL_GET("xr/openxr/foveation_level");
if (fov_level >= 0 && fov_level < 4) {
foveation_level = XrFoveationLevelFB(fov_level);
}
bool fov_dyn = GLOBAL_GET("xr/openxr/foveation_dynamic");
foveation_dynamic = fov_dyn ? XR_FOVEATION_DYNAMIC_LEVEL_ENABLED_FB : XR_FOVEATION_DYNAMIC_DISABLED_FB;
swapchain_create_info_foveation_fb.type = XR_TYPE_SWAPCHAIN_CREATE_INFO_FOVEATION_FB;
swapchain_create_info_foveation_fb.next = nullptr;
swapchain_create_info_foveation_fb.flags = 0;
}
OpenXRFBFoveationExtension::~OpenXRFBFoveationExtension() {
singleton = nullptr;
swapchain_update_state_ext = nullptr;
}
HashMap<String, bool *> OpenXRFBFoveationExtension::get_requested_extensions() {
HashMap<String, bool *> request_extensions;
if (rendering_driver == "vulkan") {
// This is currently only supported on OpenGL, but we may add Vulkan support in the future...
} else if (rendering_driver == "opengl3") {
request_extensions[XR_FB_FOVEATION_EXTENSION_NAME] = &fb_foveation_ext;
request_extensions[XR_FB_FOVEATION_CONFIGURATION_EXTENSION_NAME] = &fb_foveation_configuration_ext;
}
return request_extensions;
}
void OpenXRFBFoveationExtension::on_instance_created(const XrInstance p_instance) {
if (fb_foveation_ext) {
EXT_INIT_XR_FUNC(xrCreateFoveationProfileFB);
EXT_INIT_XR_FUNC(xrDestroyFoveationProfileFB);
}
if (fb_foveation_configuration_ext) {
// nothing to register here...
}
}
void OpenXRFBFoveationExtension::on_instance_destroyed() {
fb_foveation_ext = false;
fb_foveation_configuration_ext = false;
}
bool OpenXRFBFoveationExtension::is_enabled() const {
return swapchain_update_state_ext != nullptr && swapchain_update_state_ext->is_enabled() && fb_foveation_ext && fb_foveation_configuration_ext;
}
void *OpenXRFBFoveationExtension::set_swapchain_create_info_and_get_next_pointer(void *p_next_pointer) {
if (is_enabled()) {
swapchain_create_info_foveation_fb.next = p_next_pointer;
return &swapchain_create_info_foveation_fb;
} else {
return p_next_pointer;
}
}
void OpenXRFBFoveationExtension::on_state_ready() {
update_profile();
}
XrFoveationLevelFB OpenXRFBFoveationExtension::get_foveation_level() const {
return foveation_level;
}
void OpenXRFBFoveationExtension::set_foveation_level(XrFoveationLevelFB p_foveation_level) {
foveation_level = p_foveation_level;
// Update profile will do nothing if we're not yet initialised
update_profile();
}
XrFoveationDynamicFB OpenXRFBFoveationExtension::get_foveation_dynamic() const {
return foveation_dynamic;
}
void OpenXRFBFoveationExtension::set_foveation_dynamic(XrFoveationDynamicFB p_foveation_dynamic) {
foveation_dynamic = p_foveation_dynamic;
// Update profile will do nothing if we're not yet initialised
update_profile();
}
void OpenXRFBFoveationExtension::update_profile() {
if (!is_enabled()) {
return;
}
XrFoveationLevelProfileCreateInfoFB level_profile_create_info;
level_profile_create_info.type = XR_TYPE_FOVEATION_LEVEL_PROFILE_CREATE_INFO_FB;
level_profile_create_info.next = nullptr;
level_profile_create_info.level = foveation_level;
level_profile_create_info.verticalOffset = 0.0f;
level_profile_create_info.dynamic = foveation_dynamic;
XrFoveationProfileCreateInfoFB profile_create_info;
profile_create_info.type = XR_TYPE_FOVEATION_PROFILE_CREATE_INFO_FB;
profile_create_info.next = &level_profile_create_info;
XrFoveationProfileFB foveation_profile;
XrResult result = xrCreateFoveationProfileFB(OpenXRAPI::get_singleton()->get_session(), &profile_create_info, &foveation_profile);
if (XR_FAILED(result)) {
print_line("OpenXR: Unable to create the foveation profile [", OpenXRAPI::get_singleton()->get_error_string(result), "]");
return;
}
XrSwapchainStateFoveationFB foveation_update_state;
foveation_update_state.type = XR_TYPE_SWAPCHAIN_STATE_FOVEATION_FB;
foveation_update_state.profile = foveation_profile;
result = swapchain_update_state_ext->xrUpdateSwapchainFB(OpenXRAPI::get_singleton()->get_color_swapchain(), (XrSwapchainStateBaseHeaderFB *)&foveation_update_state);
if (XR_FAILED(result)) {
print_line("OpenXR: Unable to update the swapchain [", OpenXRAPI::get_singleton()->get_error_string(result), "]");
// We still want to destroy our profile so keep going...
}
result = xrDestroyFoveationProfileFB(foveation_profile);
if (XR_FAILED(result)) {
print_line("OpenXR: Unable to destroy the foveation profile [", OpenXRAPI::get_singleton()->get_error_string(result), "]");
}
}

View File

@ -0,0 +1,96 @@
/**************************************************************************/
/* openxr_fb_foveation_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_FB_FOVEATION_EXTENSION_H
#define OPENXR_FB_FOVEATION_EXTENSION_H
// This extension implements the FB Foveation extension.
// This is an extension Meta added due to VRS being unavailable on Android.
// Other Android based devices are implementing this as well, see:
// https://github.khronos.org/OpenXR-Inventory/extension_support.html#XR_FB_foveation
// Note: Currently we only support this for OpenGL.
// This extension works on enabling foveated rendering on the swapchain.
// Vulkan does not render 3D content directly to the swapchain image
// hence this extension can't be used.
#include "../openxr_api.h"
#include "../util.h"
#include "openxr_extension_wrapper.h"
#include "openxr_fb_update_swapchain_extension.h"
class OpenXRFBFoveationExtension : public OpenXRExtensionWrapper {
public:
static OpenXRFBFoveationExtension *get_singleton();
OpenXRFBFoveationExtension(const String &p_rendering_driver);
virtual ~OpenXRFBFoveationExtension() 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;
virtual void *set_swapchain_create_info_and_get_next_pointer(void *p_next_pointer) override;
virtual void on_state_ready() override;
bool is_enabled() const;
XrFoveationLevelFB get_foveation_level() const;
void set_foveation_level(XrFoveationLevelFB p_foveation_level);
XrFoveationDynamicFB get_foveation_dynamic() const;
void set_foveation_dynamic(XrFoveationDynamicFB p_foveation_dynamic);
private:
static OpenXRFBFoveationExtension *singleton;
// Setup
String rendering_driver;
bool fb_foveation_ext = false;
bool fb_foveation_configuration_ext = false;
// Configuration
XrFoveationLevelFB foveation_level = XR_FOVEATION_LEVEL_NONE_FB;
XrFoveationDynamicFB foveation_dynamic = XR_FOVEATION_DYNAMIC_DISABLED_FB;
void update_profile();
// Enable foveation on this swapchain
XrSwapchainCreateInfoFoveationFB swapchain_create_info_foveation_fb;
OpenXRFBUpdateSwapchainExtension *swapchain_update_state_ext = nullptr;
// OpenXR API call wrappers
EXT_PROTO_XRRESULT_FUNC3(xrCreateFoveationProfileFB, (XrSession), session, (const XrFoveationProfileCreateInfoFB *), create_info, (XrFoveationProfileFB *), profile);
EXT_PROTO_XRRESULT_FUNC1(xrDestroyFoveationProfileFB, (XrFoveationProfileFB), profile);
};
#endif // OPENXR_FB_FOVEATION_EXTENSION_H

View File

@ -0,0 +1,102 @@
/**************************************************************************/
/* openxr_fb_update_swapchain_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_fb_update_swapchain_extension.h"
// always include this as late as possible
#include "../openxr_platform_inc.h"
OpenXRFBUpdateSwapchainExtension *OpenXRFBUpdateSwapchainExtension::singleton = nullptr;
OpenXRFBUpdateSwapchainExtension *OpenXRFBUpdateSwapchainExtension::get_singleton() {
return singleton;
}
OpenXRFBUpdateSwapchainExtension::OpenXRFBUpdateSwapchainExtension(const String &p_rendering_driver) {
singleton = this;
rendering_driver = p_rendering_driver;
}
OpenXRFBUpdateSwapchainExtension::~OpenXRFBUpdateSwapchainExtension() {
singleton = nullptr;
}
HashMap<String, bool *> OpenXRFBUpdateSwapchainExtension::get_requested_extensions() {
HashMap<String, bool *> request_extensions;
request_extensions[XR_FB_SWAPCHAIN_UPDATE_STATE_EXTENSION_NAME] = &fb_swapchain_update_state_ext;
if (rendering_driver == "vulkan") {
#ifdef XR_USE_GRAPHICS_API_VULKAN
request_extensions[XR_FB_SWAPCHAIN_UPDATE_STATE_VULKAN_EXTENSION_NAME] = &fb_swapchain_update_state_vulkan_ext;
#endif
} else if (rendering_driver == "opengl3") {
#ifdef XR_USE_GRAPHICS_API_OPENGL_ES
request_extensions[XR_FB_SWAPCHAIN_UPDATE_STATE_OPENGL_ES_EXTENSION_NAME] = &fb_swapchain_update_state_opengles_ext;
#endif
}
return request_extensions;
}
void OpenXRFBUpdateSwapchainExtension::on_instance_created(const XrInstance p_instance) {
if (fb_swapchain_update_state_ext) {
EXT_INIT_XR_FUNC(xrUpdateSwapchainFB);
EXT_INIT_XR_FUNC(xrGetSwapchainStateFB);
}
if (fb_swapchain_update_state_vulkan_ext) {
// nothing to register here...
}
if (fb_swapchain_update_state_opengles_ext) {
// nothing to register here...
}
}
void OpenXRFBUpdateSwapchainExtension::on_instance_destroyed() {
fb_swapchain_update_state_ext = false;
fb_swapchain_update_state_vulkan_ext = false;
fb_swapchain_update_state_opengles_ext = false;
}
bool OpenXRFBUpdateSwapchainExtension::is_enabled() const {
if (rendering_driver == "vulkan") {
return fb_swapchain_update_state_ext && fb_swapchain_update_state_vulkan_ext;
} else if (rendering_driver == "opengl3") {
#ifdef XR_USE_GRAPHICS_API_OPENGL_ES
return fb_swapchain_update_state_ext && fb_swapchain_update_state_opengles_ext;
#else
return fb_swapchain_update_state_ext;
#endif
}
return false;
}

View File

@ -0,0 +1,73 @@
/**************************************************************************/
/* openxr_fb_update_swapchain_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_FB_UPDATE_SWAPCHAIN_EXTENSION_H
#define OPENXR_FB_UPDATE_SWAPCHAIN_EXTENSION_H
// This extension implements the FB update swapchain extension.
// This is an extension Meta added to further configure the swapchain.
// Other Android based devices are implementing this as well, see:
// https://github.khronos.org/OpenXR-Inventory/extension_support.html#XR_FB_swapchain_update_state
#include "../openxr_api.h"
#include "../util.h"
#include "openxr_extension_wrapper.h"
class OpenXRFBUpdateSwapchainExtension : public OpenXRExtensionWrapper {
friend class OpenXRFBFoveationExtension;
public:
static OpenXRFBUpdateSwapchainExtension *get_singleton();
OpenXRFBUpdateSwapchainExtension(const String &p_rendering_driver);
virtual ~OpenXRFBUpdateSwapchainExtension() 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 is_enabled() const;
private:
static OpenXRFBUpdateSwapchainExtension *singleton;
// Setup
String rendering_driver;
bool fb_swapchain_update_state_ext = false;
bool fb_swapchain_update_state_vulkan_ext = false;
bool fb_swapchain_update_state_opengles_ext = false;
// OpenXR API call wrappers
EXT_PROTO_XRRESULT_FUNC2(xrUpdateSwapchainFB, (XrSwapchain), swapchain, (const XrSwapchainStateBaseHeaderFB *), state);
EXT_PROTO_XRRESULT_FUNC2(xrGetSwapchainStateFB, (XrSwapchain), swapchain, (XrSwapchainStateBaseHeaderFB *), state);
};
#endif // OPENXR_FB_UPDATE_SWAPCHAIN_EXTENSION_H

View File

@ -39,38 +39,8 @@
#include "core/templates/vector.h" #include "core/templates/vector.h"
#ifdef ANDROID_ENABLED // always include this as late as possible
#define XR_USE_GRAPHICS_API_OPENGL_ES #include "../openxr_platform_inc.h"
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES3/gl3.h>
#include <GLES3/gl3ext.h>
#else
#define XR_USE_GRAPHICS_API_OPENGL
#endif
#ifdef WINDOWS_ENABLED
// Including windows.h here is absolutely evil, we shouldn't be doing this outside of platform
// however due to the way the openxr headers are put together, we have no choice.
#include <windows.h>
#endif
#ifdef X11_ENABLED
#define GL_GLEXT_PROTOTYPES 1
#define GL3_PROTOTYPES 1
#include "thirdparty/glad/glad/gl.h"
#include "thirdparty/glad/glad/glx.h"
#include <X11/Xlib.h>
#endif
#ifdef ANDROID_ENABLED
// The jobject type from jni.h is used by openxr_platform.h on Android.
#include <jni.h>
#endif
// Include platform dependent structs.
#include <openxr/openxr_platform.h>
class OpenXROpenGLExtension : public OpenXRGraphicsExtensionWrapper { class OpenXROpenGLExtension : public OpenXRGraphicsExtensionWrapper {
public: public:

View File

@ -36,24 +36,9 @@
#include "openxr_extension_wrapper.h" #include "openxr_extension_wrapper.h"
#include "core/templates/vector.h" #include "core/templates/vector.h"
#include "drivers/vulkan/vulkan_context.h"
// Need to include Vulkan so we know of type definitions. // always include this as late as possible
#define XR_USE_GRAPHICS_API_VULKAN #include "../openxr_platform_inc.h"
#ifdef WINDOWS_ENABLED
// Including windows.h here is absolutely evil, we shouldn't be doing this outside of platform
// however due to the way the openxr headers are put together, we have no choice.
#include <windows.h>
#endif
#ifdef ANDROID_ENABLED
// The jobject type from jni.h is used by openxr_platform.h on Android.
#include <jni.h>
#endif
// Include platform dependent structs.
#include <openxr/openxr_platform.h>
class OpenXRVulkanExtension : public OpenXRGraphicsExtensionWrapper, VulkanHooks { class OpenXRVulkanExtension : public OpenXRGraphicsExtensionWrapper, VulkanHooks {
public: public:

View File

@ -43,30 +43,7 @@
#include "editor/editor_settings.h" #include "editor/editor_settings.h"
#endif #endif
// We need to have all the graphics API defines before the Vulkan or OpenGL #include "openxr_platform_inc.h"
// extensions are included, otherwise we'll only get one graphics API.
#ifdef VULKAN_ENABLED
#define XR_USE_GRAPHICS_API_VULKAN
#endif
#if defined(GLES3_ENABLED) && !defined(MACOS_ENABLED)
#ifdef ANDROID_ENABLED
#define XR_USE_GRAPHICS_API_OPENGL_ES
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES3/gl3.h>
#include <GLES3/gl3ext.h>
#else
#define XR_USE_GRAPHICS_API_OPENGL
#endif // ANDROID_ENABLED
#ifdef X11_ENABLED
#define GL_GLEXT_PROTOTYPES 1
#define GL3_PROTOTYPES 1
#include "thirdparty/glad/glad/gl.h"
#include "thirdparty/glad/glad/glx.h"
#include <X11/Xlib.h>
#endif // X11_ENABLED
#endif // GLES_ENABLED
#ifdef VULKAN_ENABLED #ifdef VULKAN_ENABLED
#include "extensions/openxr_vulkan_extension.h" #include "extensions/openxr_vulkan_extension.h"
@ -78,7 +55,9 @@
#include "extensions/openxr_composition_layer_depth_extension.h" #include "extensions/openxr_composition_layer_depth_extension.h"
#include "extensions/openxr_fb_display_refresh_rate_extension.h" #include "extensions/openxr_fb_display_refresh_rate_extension.h"
#include "extensions/openxr_fb_foveation_extension.h"
#include "extensions/openxr_fb_passthrough_extension_wrapper.h" #include "extensions/openxr_fb_passthrough_extension_wrapper.h"
#include "extensions/openxr_fb_update_swapchain_extension.h"
#ifdef ANDROID_ENABLED #ifdef ANDROID_ENABLED
#define OPENXR_LOADER_NAME "libopenxr_loader.so" #define OPENXR_LOADER_NAME "libopenxr_loader.so"
@ -1340,6 +1319,10 @@ bool OpenXRAPI::initialize(const String &p_rendering_driver) {
ERR_FAIL_V_MSG(false, "OpenXR: Unsupported rendering device."); ERR_FAIL_V_MSG(false, "OpenXR: Unsupported rendering device.");
} }
// Also register our rendering extensions
register_extension_wrapper(memnew(OpenXRFBUpdateSwapchainExtension(p_rendering_driver)));
register_extension_wrapper(memnew(OpenXRFBFoveationExtension(p_rendering_driver)));
// initialize // initialize
for (OpenXRExtensionWrapper *wrapper : registered_extension_wrappers) { for (OpenXRExtensionWrapper *wrapper : registered_extension_wrappers) {
wrapper->on_before_instance_created(); wrapper->on_before_instance_created();
@ -1859,6 +1842,10 @@ bool OpenXRAPI::pre_draw_viewport(RID p_render_target) {
return true; return true;
} }
XrSwapchain OpenXRAPI::get_color_swapchain() {
return swapchains[OPENXR_SWAPCHAIN_COLOR].swapchain;
}
RID OpenXRAPI::get_color_texture() { RID OpenXRAPI::get_color_texture() {
if (swapchains[OPENXR_SWAPCHAIN_COLOR].image_acquired) { if (swapchains[OPENXR_SWAPCHAIN_COLOR].image_acquired) {
return graphics_extension->get_texture(swapchains[OPENXR_SWAPCHAIN_COLOR].swapchain_graphics_data, swapchains[OPENXR_SWAPCHAIN_COLOR].image_index); return graphics_extension->get_texture(swapchains[OPENXR_SWAPCHAIN_COLOR].swapchain_graphics_data, swapchains[OPENXR_SWAPCHAIN_COLOR].image_index);
@ -2010,6 +1997,55 @@ void OpenXRAPI::set_render_target_size_multiplier(double multiplier) {
render_target_size_multiplier = multiplier; render_target_size_multiplier = multiplier;
} }
bool OpenXRAPI::is_foveation_supported() const {
OpenXRFBFoveationExtension *fov_ext = OpenXRFBFoveationExtension::get_singleton();
return fov_ext != nullptr && fov_ext->is_enabled();
}
int OpenXRAPI::get_foveation_level() const {
OpenXRFBFoveationExtension *fov_ext = OpenXRFBFoveationExtension::get_singleton();
if (fov_ext != nullptr && fov_ext->is_enabled()) {
switch (fov_ext->get_foveation_level()) {
case XR_FOVEATION_LEVEL_NONE_FB:
return 0;
case XR_FOVEATION_LEVEL_LOW_FB:
return 1;
case XR_FOVEATION_LEVEL_MEDIUM_FB:
return 2;
case XR_FOVEATION_LEVEL_HIGH_FB:
return 3;
default:
return 0;
}
}
return 0;
}
void OpenXRAPI::set_foveation_level(int p_foveation_level) {
ERR_FAIL_UNSIGNED_INDEX(p_foveation_level, 4);
OpenXRFBFoveationExtension *fov_ext = OpenXRFBFoveationExtension::get_singleton();
if (fov_ext != nullptr && fov_ext->is_enabled()) {
XrFoveationLevelFB levels[] = { XR_FOVEATION_LEVEL_NONE_FB, XR_FOVEATION_LEVEL_LOW_FB, XR_FOVEATION_LEVEL_MEDIUM_FB, XR_FOVEATION_LEVEL_HIGH_FB };
fov_ext->set_foveation_level(levels[p_foveation_level]);
}
}
bool OpenXRAPI::get_foveation_dynamic() const {
OpenXRFBFoveationExtension *fov_ext = OpenXRFBFoveationExtension::get_singleton();
if (fov_ext != nullptr && fov_ext->is_enabled()) {
return fov_ext->get_foveation_dynamic() == XR_FOVEATION_DYNAMIC_LEVEL_ENABLED_FB;
}
return false;
}
void OpenXRAPI::set_foveation_dynamic(bool p_foveation_dynamic) {
OpenXRFBFoveationExtension *fov_ext = OpenXRFBFoveationExtension::get_singleton();
if (fov_ext != nullptr && fov_ext->is_enabled()) {
fov_ext->set_foveation_dynamic(p_foveation_dynamic ? XR_FOVEATION_DYNAMIC_LEVEL_ENABLED_FB : XR_FOVEATION_DYNAMIC_DISABLED_FB);
}
}
OpenXRAPI::OpenXRAPI() { OpenXRAPI::OpenXRAPI() {
// OpenXRAPI is only constructed if OpenXR is enabled. // OpenXRAPI is only constructed if OpenXR is enabled.
singleton = this; singleton = this;

View File

@ -54,7 +54,6 @@
// Godot is currently restricted to C++17 which doesn't allow this notation. Make sure critical fields are set. // Godot is currently restricted to C++17 which doesn't allow this notation. Make sure critical fields are set.
// forward declarations, we don't want to include these fully // forward declarations, we don't want to include these fully
class OpenXRVulkanExtension;
class OpenXRInterface; class OpenXRInterface;
class OpenXRAPI { class OpenXRAPI {
@ -356,6 +355,7 @@ public:
void pre_render(); void pre_render();
bool pre_draw_viewport(RID p_render_target); bool pre_draw_viewport(RID p_render_target);
XrSwapchain get_color_swapchain();
RID get_color_texture(); RID get_color_texture();
RID get_depth_texture(); RID get_depth_texture();
void post_draw_viewport(RID p_render_target); void post_draw_viewport(RID p_render_target);
@ -370,6 +370,15 @@ public:
double get_render_target_size_multiplier() const; double get_render_target_size_multiplier() const;
void set_render_target_size_multiplier(double multiplier); void set_render_target_size_multiplier(double multiplier);
// Foveation settings
bool is_foveation_supported() const;
int get_foveation_level() const;
void set_foveation_level(int p_foveation_level);
bool get_foveation_dynamic() const;
void set_foveation_dynamic(bool p_foveation_dynamic);
// action map // action map
String get_default_action_map_resource_name(); String get_default_action_map_resource_name();

View File

@ -54,10 +54,23 @@ void OpenXRInterface::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_render_target_size_multiplier", "multiplier"), &OpenXRInterface::set_render_target_size_multiplier); ClassDB::bind_method(D_METHOD("set_render_target_size_multiplier", "multiplier"), &OpenXRInterface::set_render_target_size_multiplier);
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "render_target_size_multiplier"), "set_render_target_size_multiplier", "get_render_target_size_multiplier"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "render_target_size_multiplier"), "set_render_target_size_multiplier", "get_render_target_size_multiplier");
// Foveation level
ClassDB::bind_method(D_METHOD("is_foveation_supported"), &OpenXRInterface::is_foveation_supported);
ClassDB::bind_method(D_METHOD("get_foveation_level"), &OpenXRInterface::get_foveation_level);
ClassDB::bind_method(D_METHOD("set_foveation_level", "foveation_level"), &OpenXRInterface::set_foveation_level);
ADD_PROPERTY(PropertyInfo(Variant::INT, "foveation_level"), "set_foveation_level", "get_foveation_level");
ClassDB::bind_method(D_METHOD("get_foveation_dynamic"), &OpenXRInterface::get_foveation_dynamic);
ClassDB::bind_method(D_METHOD("set_foveation_dynamic", "foveation_dynamic"), &OpenXRInterface::set_foveation_dynamic);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "foveation_dynamic"), "set_foveation_dynamic", "get_foveation_dynamic");
// Action sets
ClassDB::bind_method(D_METHOD("is_action_set_active", "name"), &OpenXRInterface::is_action_set_active); ClassDB::bind_method(D_METHOD("is_action_set_active", "name"), &OpenXRInterface::is_action_set_active);
ClassDB::bind_method(D_METHOD("set_action_set_active", "name", "active"), &OpenXRInterface::set_action_set_active); ClassDB::bind_method(D_METHOD("set_action_set_active", "name", "active"), &OpenXRInterface::set_action_set_active);
ClassDB::bind_method(D_METHOD("get_action_sets"), &OpenXRInterface::get_action_sets); ClassDB::bind_method(D_METHOD("get_action_sets"), &OpenXRInterface::get_action_sets);
// Refresh rates
ClassDB::bind_method(D_METHOD("get_available_display_refresh_rates"), &OpenXRInterface::get_available_display_refresh_rates); ClassDB::bind_method(D_METHOD("get_available_display_refresh_rates"), &OpenXRInterface::get_available_display_refresh_rates);
// Hand tracking. // Hand tracking.
@ -740,6 +753,46 @@ void OpenXRInterface::set_render_target_size_multiplier(double multiplier) {
} }
} }
bool OpenXRInterface::is_foveation_supported() const {
if (openxr_api == nullptr) {
return false;
} else {
return openxr_api->is_foveation_supported();
}
}
int OpenXRInterface::get_foveation_level() const {
if (openxr_api == nullptr) {
return 0;
} else {
return openxr_api->get_foveation_level();
}
}
void OpenXRInterface::set_foveation_level(int p_foveation_level) {
if (openxr_api == nullptr) {
return;
} else {
openxr_api->set_foveation_level(p_foveation_level);
}
}
bool OpenXRInterface::get_foveation_dynamic() const {
if (openxr_api == nullptr) {
return false;
} else {
return openxr_api->get_foveation_dynamic();
}
}
void OpenXRInterface::set_foveation_dynamic(bool p_foveation_dynamic) {
if (openxr_api == nullptr) {
return;
} else {
openxr_api->set_foveation_dynamic(p_foveation_dynamic);
}
}
Size2 OpenXRInterface::get_render_target_size() { Size2 OpenXRInterface::get_render_target_size() {
if (openxr_api == nullptr) { if (openxr_api == nullptr) {
return Size2(); return Size2();

View File

@ -130,6 +130,14 @@ public:
double get_render_target_size_multiplier() const; double get_render_target_size_multiplier() const;
void set_render_target_size_multiplier(double multiplier); void set_render_target_size_multiplier(double multiplier);
bool is_foveation_supported() const;
int get_foveation_level() const;
void set_foveation_level(int p_foveation_level);
bool get_foveation_dynamic() const;
void set_foveation_dynamic(bool p_foveation_dynamic);
virtual Size2 get_render_target_size() override; virtual Size2 get_render_target_size() override;
virtual uint32_t get_view_count() override; virtual uint32_t get_view_count() override;
virtual Transform3D get_camera_transform() override; virtual Transform3D get_camera_transform() override;

View File

@ -0,0 +1,78 @@
/**************************************************************************/
/* openxr_platform_inc.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_PLATFORM_INC_H
#define OPENXR_PLATFORM_INC_H
// In various places we need to include platform definitions but we can't
// include these in our normal header files as we'll end up with issues.
#ifdef VULKAN_ENABLED
#define XR_USE_GRAPHICS_API_VULKAN
#include "drivers/vulkan/vulkan_context.h"
#endif // VULKAN_ENABLED
#if defined(GLES3_ENABLED) && !defined(MACOS_ENABLED)
#ifdef ANDROID_ENABLED
#define XR_USE_GRAPHICS_API_OPENGL_ES
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES3/gl3.h>
#include <GLES3/gl3ext.h>
#else
#define XR_USE_GRAPHICS_API_OPENGL
#endif // ANDROID_ENABLED
#ifdef X11_ENABLED
#define GL_GLEXT_PROTOTYPES 1
#define GL3_PROTOTYPES 1
#include "thirdparty/glad/glad/gl.h"
#include "thirdparty/glad/glad/glx.h"
#endif // X11_ENABLED
#endif // defined(GLES3_ENABLED) && !defined(MACOS_ENABLED)
#ifdef X11_ENABLED
#include <X11/Xlib.h>
#endif // X11_ENABLED
#ifdef WINDOWS_ENABLED
// Including windows.h here is absolutely evil, we shouldn't be doing this outside of platform
// however due to the way the openxr headers are put together, we have no choice.
#include <windows.h>
#endif // WINDOWS_ENABLED
#ifdef ANDROID_ENABLED
// The jobject type from jni.h is used by openxr_platform.h on Android.
#include <jni.h>
#endif // ANDROID_ENABLED
// Include platform dependent structs.
#include <openxr/openxr_platform.h>
#endif // OPENXR_PLATFORM_INC_H