Merge pull request #116207 from eritschlSC/projection_layer_extension

OpenXR: Add support for projection layer extensions
This commit is contained in:
Thaddeus Crews 2026-02-18 17:28:22 -06:00
commit 2ae60b4108
No known key found for this signature in database
GPG key ID: 8C6E5FEB5FC03CCC
8 changed files with 78 additions and 0 deletions

View file

@ -257,6 +257,14 @@
[b]Note:[/b] This cannot be called after the OpenXR session has started. However, it can be called in [method OpenXRExtensionWrapper._on_session_created].
</description>
</method>
<method name="register_projection_layer_extension">
<return type="void" />
<param index="0" name="extension" type="OpenXRExtensionWrapper" />
<description>
Registers the given extension as modifying [code]XrCompositionLayerProjection[/code] via the [method OpenXRExtensionWrapper._set_projection_layer_and_get_next_pointer] virtual method.
[b]Note:[/b] This cannot be called after the OpenXR session has started. However, it can be called in [method OpenXRExtensionWrapper._on_session_created].
</description>
</method>
<method name="register_projection_views_extension">
<return type="void" />
<param index="0" name="extension" type="OpenXRExtensionWrapper" />
@ -339,6 +347,14 @@
[b]Note:[/b] This cannot be called while the OpenXR session is still running.
</description>
</method>
<method name="unregister_projection_layer_extension">
<return type="void" />
<param index="0" name="extension" type="OpenXRExtensionWrapper" />
<description>
Unregisters the given extension as modifying [code]XrCompositionLayerProjection[/code].
[b]Note:[/b] This cannot be called while the OpenXR session is still running.
</description>
</method>
<method name="unregister_projection_views_extension">
<return type="void" />
<param index="0" name="extension" type="OpenXRExtensionWrapper" />

View file

@ -276,6 +276,14 @@
Add additional data structures when the OpenXR instance is created. [param xr_version] specifies the OpenXR version we're instantiating.
</description>
</method>
<method name="_set_projection_layer_and_get_next_pointer" qualifiers="virtual">
<return type="int" />
<param index="0" name="next_pointer" type="void*" />
<description>
Adds additional data structures to [code]XrCompositionLayerProjection[/code].
This will only be called if the extension previously registered itself with [method OpenXRAPIExtension.register_projection_layer_extension].
</description>
</method>
<method name="_set_projection_views_and_get_next_pointer" qualifiers="virtual">
<return type="int" />
<param index="0" name="view_index" type="int" />

View file

@ -43,6 +43,7 @@ void OpenXRExtensionWrapper::_bind_methods() {
GDVIRTUAL_BIND(_set_projection_views_and_get_next_pointer, "view_index", "next_pointer");
GDVIRTUAL_BIND(_set_frame_wait_info_and_get_next_pointer, "next_pointer");
GDVIRTUAL_BIND(_set_frame_end_info_and_get_next_pointer, "next_pointer");
GDVIRTUAL_BIND(_set_projection_layer_and_get_next_pointer, "next_pointer");
GDVIRTUAL_BIND(_set_view_locate_info_and_get_next_pointer, "next_pointer");
GDVIRTUAL_BIND(_set_reference_space_create_info_and_get_next_pointer, "reference_space_type", "next_pointer");
GDVIRTUAL_BIND(_prepare_view_configuration, "view_count");
@ -210,6 +211,16 @@ void *OpenXRExtensionWrapper::set_frame_end_info_and_get_next_pointer(void *p_ne
return nullptr;
}
void *OpenXRExtensionWrapper::set_projection_layer_and_get_next_pointer(void *p_next_pointer) {
uint64_t pointer = 0;
if (GDVIRTUAL_CALL(_set_projection_layer_and_get_next_pointer, GDExtensionPtr<void>(p_next_pointer), pointer)) {
return reinterpret_cast<void *>(pointer);
}
return nullptr;
}
void OpenXRExtensionWrapper::prepare_view_configuration(uint32_t p_view_count) {
GDVIRTUAL_CALL(_prepare_view_configuration, p_view_count);
}

View file

@ -88,6 +88,8 @@ public:
virtual void *set_frame_wait_info_and_get_next_pointer(void *p_next_pointer); // Add additional data structures when calling xrWaitFrame
virtual void *set_view_locate_info_and_get_next_pointer(void *p_next_pointer); // Add additional data structures when calling xrLocateViews
virtual void *set_frame_end_info_and_get_next_pointer(void *p_next_pointer); // Add additional data structures when calling xrEndFrame
// This will only be called for extensions registered via OpenXRAPI::register_projection_layer_extension().
virtual void *set_projection_layer_and_get_next_pointer(void *p_next_pointer); // Add additional data structures to XrCompositionLayerProjection
virtual void prepare_view_configuration(uint32_t p_view_count);
virtual void *set_view_configuration_and_get_next_pointer(uint32_t p_view, void *p_next_pointer); // Add additional data structures when calling xrEnumerateViewConfiguration
@ -102,6 +104,7 @@ public:
GDVIRTUAL2R(uint64_t, _set_projection_views_and_get_next_pointer, int, GDExtensionPtr<void>);
GDVIRTUAL1R(uint64_t, _set_frame_wait_info_and_get_next_pointer, GDExtensionPtr<void>);
GDVIRTUAL1R(uint64_t, _set_frame_end_info_and_get_next_pointer, GDExtensionPtr<void>);
GDVIRTUAL1R(uint64_t, _set_projection_layer_and_get_next_pointer, GDExtensionPtr<void>);
GDVIRTUAL1R(uint64_t, _set_view_locate_info_and_get_next_pointer, GDExtensionPtr<void>);
GDVIRTUAL2R(uint64_t, _set_reference_space_create_info_and_get_next_pointer, int, GDExtensionPtr<void>);
GDVIRTUAL0R(int, _get_composition_layer_count);

View file

@ -2655,6 +2655,15 @@ void OpenXRAPI::end_frame() {
layer_flags |= XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT;
}
void *projection_layer_next_pointer = nullptr;
for (OpenXRExtensionWrapper *extension : projection_layer_extensions) {
void *np = extension->set_projection_layer_and_get_next_pointer(projection_layer_next_pointer);
if (np != nullptr) {
projection_layer_next_pointer = np;
}
}
render_state.projection_layer.next = projection_layer_next_pointer;
render_state.projection_layer.layerFlags = layer_flags;
render_state.projection_layer.space = render_state.play_space;
render_state.projection_layer.viewCount = (uint32_t)render_state.projection_views.size();
@ -2905,6 +2914,7 @@ OpenXRAPI::OpenXRAPI() {
OpenXRAPI::~OpenXRAPI() {
composition_layer_providers.clear();
frame_info_extensions.clear();
projection_layer_extensions.clear();
supported_extensions.clear();
layer_properties.clear();
@ -3959,6 +3969,14 @@ void OpenXRAPI::unregister_frame_info_extension(OpenXRExtensionWrapper *p_extens
frame_info_extensions.erase(p_extension);
}
void OpenXRAPI::register_projection_layer_extension(OpenXRExtensionWrapper *p_extension) {
projection_layer_extensions.append(p_extension);
}
void OpenXRAPI::unregister_projection_layer_extension(OpenXRExtensionWrapper *p_extension) {
projection_layer_extensions.erase(p_extension);
}
const Vector<XrEnvironmentBlendMode> OpenXRAPI::get_supported_environment_blend_modes() {
return supported_environment_blend_modes;
}

View file

@ -107,6 +107,9 @@ private:
// frame info extensions
Vector<OpenXRExtensionWrapper *> frame_info_extensions;
// projection layer extensions
Vector<OpenXRExtensionWrapper *> projection_layer_extensions;
// view configuration
LocalVector<XrViewConfigurationType> supported_view_configuration_types;
@ -632,6 +635,9 @@ public:
void register_frame_info_extension(OpenXRExtensionWrapper *p_extension);
void unregister_frame_info_extension(OpenXRExtensionWrapper *p_extension);
void register_projection_layer_extension(OpenXRExtensionWrapper *p_extension);
void unregister_projection_layer_extension(OpenXRExtensionWrapper *p_extension);
const Vector<XrEnvironmentBlendMode> get_supported_environment_blend_modes();
bool is_environment_blend_mode_supported(XrEnvironmentBlendMode p_blend_mode) const;

View file

@ -76,6 +76,9 @@ void OpenXRAPIExtension::_bind_methods() {
ClassDB::bind_method(D_METHOD("register_frame_info_extension", "extension"), &OpenXRAPIExtension::register_frame_info_extension);
ClassDB::bind_method(D_METHOD("unregister_frame_info_extension", "extension"), &OpenXRAPIExtension::unregister_frame_info_extension);
ClassDB::bind_method(D_METHOD("register_projection_layer_extension", "extension"), &OpenXRAPIExtension::register_projection_layer_extension);
ClassDB::bind_method(D_METHOD("unregister_projection_layer_extension", "extension"), &OpenXRAPIExtension::unregister_projection_layer_extension);
ClassDB::bind_method(D_METHOD("get_render_state_z_near"), &OpenXRAPIExtension::get_render_state_z_near);
ClassDB::bind_method(D_METHOD("get_render_state_z_far"), &OpenXRAPIExtension::get_render_state_z_far);
@ -281,6 +284,16 @@ void OpenXRAPIExtension::unregister_frame_info_extension(OpenXRExtensionWrapper
OpenXRAPI::get_singleton()->unregister_frame_info_extension(p_extension);
}
void OpenXRAPIExtension::register_projection_layer_extension(OpenXRExtensionWrapper *p_extension) {
ERR_FAIL_NULL(OpenXRAPI::get_singleton());
OpenXRAPI::get_singleton()->register_projection_layer_extension(p_extension);
}
void OpenXRAPIExtension::unregister_projection_layer_extension(OpenXRExtensionWrapper *p_extension) {
ERR_FAIL_NULL(OpenXRAPI::get_singleton());
OpenXRAPI::get_singleton()->unregister_projection_layer_extension(p_extension);
}
double OpenXRAPIExtension::get_render_state_z_near() {
ERR_NOT_ON_RENDER_THREAD_V(0.0);
ERR_FAIL_NULL_V(OpenXRAPI::get_singleton(), 0.0);

View file

@ -103,6 +103,9 @@ public:
void register_frame_info_extension(OpenXRExtensionWrapper *p_extension);
void unregister_frame_info_extension(OpenXRExtensionWrapper *p_extension);
void register_projection_layer_extension(OpenXRExtensionWrapper *p_extension);
void unregister_projection_layer_extension(OpenXRExtensionWrapper *p_extension);
double get_render_state_z_near();
double get_render_state_z_far();