OpenXR: Allow GDExtensions to provide multiple, ordered composition layers
Co-authored-by: Bastiaan Olij <mux213@gmail.com>
This commit is contained in:
parent
da945ce626
commit
308a6a4734
|
@ -11,8 +11,25 @@
|
||||||
<methods>
|
<methods>
|
||||||
<method name="_get_composition_layer" qualifiers="virtual">
|
<method name="_get_composition_layer" qualifiers="virtual">
|
||||||
<return type="int" />
|
<return type="int" />
|
||||||
|
<param index="0" name="index" type="int" />
|
||||||
<description>
|
<description>
|
||||||
Returns a pointer to an [code]XrCompositionLayerBaseHeader[/code] struct to provide a composition layer. This will only be called if the extension previously registered itself with [method OpenXRAPIExtension.register_composition_layer_provider].
|
Returns a pointer to an [code]XrCompositionLayerBaseHeader[/code] struct to provide the given composition layer.
|
||||||
|
This will only be called if the extension previously registered itself with [method OpenXRAPIExtension.register_composition_layer_provider].
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
|
<method name="_get_composition_layer_count" qualifiers="virtual">
|
||||||
|
<return type="int" />
|
||||||
|
<description>
|
||||||
|
Returns the number of composition layers this extension wrapper provides via [method _get_composition_layer].
|
||||||
|
This will only be called if the extension previously registered itself with [method OpenXRAPIExtension.register_composition_layer_provider].
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
|
<method name="_get_composition_layer_order" qualifiers="virtual">
|
||||||
|
<return type="int" />
|
||||||
|
<param index="0" name="index" type="int" />
|
||||||
|
<description>
|
||||||
|
Returns an integer that will be used to sort the given composition layer provided via [method _get_composition_layer]. Lower numbers will move the layer to the front of the list, and higher numbers to the end. The default projection layer has an order of [code]0[/code], so layers provided by this method should probably be above or below (but not exactly) [code]0[/code].
|
||||||
|
This will only be called if the extension previously registered itself with [method OpenXRAPIExtension.register_composition_layer_provider].
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
<method name="_get_requested_extensions" qualifiers="virtual">
|
<method name="_get_requested_extensions" qualifiers="virtual">
|
||||||
|
|
|
@ -56,8 +56,15 @@ bool OpenXRCompositionLayerDepthExtension::is_available() {
|
||||||
return available;
|
return available;
|
||||||
}
|
}
|
||||||
|
|
||||||
XrCompositionLayerBaseHeader *OpenXRCompositionLayerDepthExtension::get_composition_layer() {
|
int OpenXRCompositionLayerDepthExtension::get_composition_layer_count() {
|
||||||
// Seems this is all done in our base layer... Just in case this changes...
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
XrCompositionLayerBaseHeader *OpenXRCompositionLayerDepthExtension::get_composition_layer(int p_index) {
|
||||||
|
// Seems this is all done in our base layer... Just in case this changes...
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int OpenXRCompositionLayerDepthExtension::get_composition_layer_order(int p_index) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -43,7 +43,9 @@ public:
|
||||||
|
|
||||||
virtual HashMap<String, bool *> get_requested_extensions() override;
|
virtual HashMap<String, bool *> get_requested_extensions() override;
|
||||||
bool is_available();
|
bool is_available();
|
||||||
virtual XrCompositionLayerBaseHeader *get_composition_layer() override;
|
virtual int get_composition_layer_count() override;
|
||||||
|
virtual XrCompositionLayerBaseHeader *get_composition_layer(int p_index) override;
|
||||||
|
virtual int get_composition_layer_order(int p_index) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static OpenXRCompositionLayerDepthExtension *singleton;
|
static OpenXRCompositionLayerDepthExtension *singleton;
|
||||||
|
|
|
@ -38,7 +38,9 @@
|
||||||
// Interface for OpenXR extensions that provide a composition layer.
|
// Interface for OpenXR extensions that provide a composition layer.
|
||||||
class OpenXRCompositionLayerProvider {
|
class OpenXRCompositionLayerProvider {
|
||||||
public:
|
public:
|
||||||
virtual XrCompositionLayerBaseHeader *get_composition_layer() = 0;
|
virtual int get_composition_layer_count() = 0;
|
||||||
|
virtual XrCompositionLayerBaseHeader *get_composition_layer(int p_index) = 0;
|
||||||
|
virtual int get_composition_layer_order(int p_index) = 0;
|
||||||
|
|
||||||
virtual ~OpenXRCompositionLayerProvider() {}
|
virtual ~OpenXRCompositionLayerProvider() {}
|
||||||
};
|
};
|
||||||
|
|
|
@ -39,7 +39,9 @@ void OpenXRExtensionWrapperExtension::_bind_methods() {
|
||||||
GDVIRTUAL_BIND(_set_session_create_and_get_next_pointer, "next_pointer");
|
GDVIRTUAL_BIND(_set_session_create_and_get_next_pointer, "next_pointer");
|
||||||
GDVIRTUAL_BIND(_set_swapchain_create_info_and_get_next_pointer, "next_pointer");
|
GDVIRTUAL_BIND(_set_swapchain_create_info_and_get_next_pointer, "next_pointer");
|
||||||
GDVIRTUAL_BIND(_set_hand_joint_locations_and_get_next_pointer, "hand_index", "next_pointer");
|
GDVIRTUAL_BIND(_set_hand_joint_locations_and_get_next_pointer, "hand_index", "next_pointer");
|
||||||
GDVIRTUAL_BIND(_get_composition_layer);
|
GDVIRTUAL_BIND(_get_composition_layer_count);
|
||||||
|
GDVIRTUAL_BIND(_get_composition_layer, "index");
|
||||||
|
GDVIRTUAL_BIND(_get_composition_layer_order, "index");
|
||||||
GDVIRTUAL_BIND(_get_suggested_tracker_names);
|
GDVIRTUAL_BIND(_get_suggested_tracker_names);
|
||||||
GDVIRTUAL_BIND(_on_register_metadata);
|
GDVIRTUAL_BIND(_on_register_metadata);
|
||||||
GDVIRTUAL_BIND(_on_before_instance_created);
|
GDVIRTUAL_BIND(_on_before_instance_created);
|
||||||
|
@ -140,16 +142,28 @@ PackedStringArray OpenXRExtensionWrapperExtension::get_suggested_tracker_names()
|
||||||
return PackedStringArray();
|
return PackedStringArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
XrCompositionLayerBaseHeader *OpenXRExtensionWrapperExtension::get_composition_layer() {
|
int OpenXRExtensionWrapperExtension::get_composition_layer_count() {
|
||||||
|
int count = 0;
|
||||||
|
GDVIRTUAL_CALL(_get_composition_layer_count, count);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
XrCompositionLayerBaseHeader *OpenXRExtensionWrapperExtension::get_composition_layer(int p_index) {
|
||||||
uint64_t pointer;
|
uint64_t pointer;
|
||||||
|
|
||||||
if (GDVIRTUAL_CALL(_get_composition_layer, pointer)) {
|
if (GDVIRTUAL_CALL(_get_composition_layer, p_index, pointer)) {
|
||||||
return reinterpret_cast<XrCompositionLayerBaseHeader *>(pointer);
|
return reinterpret_cast<XrCompositionLayerBaseHeader *>(pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int OpenXRExtensionWrapperExtension::get_composition_layer_order(int p_index) {
|
||||||
|
int order = 0;
|
||||||
|
GDVIRTUAL_CALL(_get_composition_layer_order, p_index, order);
|
||||||
|
return order;
|
||||||
|
}
|
||||||
|
|
||||||
void OpenXRExtensionWrapperExtension::on_register_metadata() {
|
void OpenXRExtensionWrapperExtension::on_register_metadata() {
|
||||||
GDVIRTUAL_CALL(_on_register_metadata);
|
GDVIRTUAL_CALL(_on_register_metadata);
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,9 @@ public:
|
||||||
virtual void *set_session_create_and_get_next_pointer(void *p_next_pointer) override;
|
virtual void *set_session_create_and_get_next_pointer(void *p_next_pointer) override;
|
||||||
virtual void *set_swapchain_create_info_and_get_next_pointer(void *p_next_pointer) override;
|
virtual void *set_swapchain_create_info_and_get_next_pointer(void *p_next_pointer) override;
|
||||||
virtual void *set_hand_joint_locations_and_get_next_pointer(int p_hand_index, void *p_next_pointer) override;
|
virtual void *set_hand_joint_locations_and_get_next_pointer(int p_hand_index, void *p_next_pointer) override;
|
||||||
virtual XrCompositionLayerBaseHeader *get_composition_layer() override;
|
virtual int get_composition_layer_count() override;
|
||||||
|
virtual XrCompositionLayerBaseHeader *get_composition_layer(int p_index) override;
|
||||||
|
virtual int get_composition_layer_order(int p_index) override;
|
||||||
|
|
||||||
//TODO workaround as GDExtensionPtr<void> return type results in build error in godot-cpp
|
//TODO workaround as GDExtensionPtr<void> return type results in build error in godot-cpp
|
||||||
GDVIRTUAL1R(uint64_t, _set_system_properties_and_get_next_pointer, GDExtensionPtr<void>);
|
GDVIRTUAL1R(uint64_t, _set_system_properties_and_get_next_pointer, GDExtensionPtr<void>);
|
||||||
|
@ -67,7 +69,9 @@ public:
|
||||||
GDVIRTUAL1R(uint64_t, _set_session_create_and_get_next_pointer, GDExtensionPtr<void>);
|
GDVIRTUAL1R(uint64_t, _set_session_create_and_get_next_pointer, GDExtensionPtr<void>);
|
||||||
GDVIRTUAL1R(uint64_t, _set_swapchain_create_info_and_get_next_pointer, GDExtensionPtr<void>);
|
GDVIRTUAL1R(uint64_t, _set_swapchain_create_info_and_get_next_pointer, GDExtensionPtr<void>);
|
||||||
GDVIRTUAL2R(uint64_t, _set_hand_joint_locations_and_get_next_pointer, int, GDExtensionPtr<void>);
|
GDVIRTUAL2R(uint64_t, _set_hand_joint_locations_and_get_next_pointer, int, GDExtensionPtr<void>);
|
||||||
GDVIRTUAL0R(uint64_t, _get_composition_layer);
|
GDVIRTUAL0R(int, _get_composition_layer_count);
|
||||||
|
GDVIRTUAL1R(uint64_t, _get_composition_layer, int);
|
||||||
|
GDVIRTUAL1R(int, _get_composition_layer_order, int);
|
||||||
|
|
||||||
virtual PackedStringArray get_suggested_tracker_names() override;
|
virtual PackedStringArray get_suggested_tracker_names() override;
|
||||||
|
|
||||||
|
|
|
@ -2080,18 +2080,29 @@ void OpenXRAPI::end_frame() {
|
||||||
projection_views[eye].pose = views[eye].pose;
|
projection_views[eye].pose = views[eye].pose;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector<const XrCompositionLayerBaseHeader *> layers_list;
|
Vector<OrderedCompositionLayer> ordered_layers_list;
|
||||||
|
bool projection_layer_is_first = true;
|
||||||
|
|
||||||
// Add composition layers from providers
|
// Add composition layers from providers
|
||||||
for (OpenXRCompositionLayerProvider *provider : composition_layer_providers) {
|
for (OpenXRCompositionLayerProvider *provider : composition_layer_providers) {
|
||||||
XrCompositionLayerBaseHeader *layer = provider->get_composition_layer();
|
for (int i = 0; i < provider->get_composition_layer_count(); i++) {
|
||||||
if (layer) {
|
OrderedCompositionLayer layer = {
|
||||||
layers_list.push_back(layer);
|
provider->get_composition_layer(i),
|
||||||
|
provider->get_composition_layer_order(i),
|
||||||
|
};
|
||||||
|
if (layer.composition_layer) {
|
||||||
|
ordered_layers_list.push_back(layer);
|
||||||
|
if (layer.sort_order == 0) {
|
||||||
|
WARN_PRINT_ONCE_ED("Composition layer returned sort order 0, it may be overwritten by projection layer.");
|
||||||
|
} else if (layer.sort_order < 0) {
|
||||||
|
projection_layer_is_first = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
XrCompositionLayerFlags layer_flags = XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT;
|
XrCompositionLayerFlags layer_flags = XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT;
|
||||||
if (layers_list.size() > 0 || environment_blend_mode != XR_ENVIRONMENT_BLEND_MODE_OPAQUE) {
|
if (!projection_layer_is_first || environment_blend_mode != XR_ENVIRONMENT_BLEND_MODE_OPAQUE) {
|
||||||
layer_flags |= XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT;
|
layer_flags |= XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2103,7 +2114,16 @@ void OpenXRAPI::end_frame() {
|
||||||
view_count, // viewCount
|
view_count, // viewCount
|
||||||
projection_views, // views
|
projection_views, // views
|
||||||
};
|
};
|
||||||
layers_list.push_back((const XrCompositionLayerBaseHeader *)&projection_layer);
|
ordered_layers_list.push_back({ (const XrCompositionLayerBaseHeader *)&projection_layer, 0 });
|
||||||
|
|
||||||
|
// Sort our layers.
|
||||||
|
ordered_layers_list.sort_custom<OrderedCompositionLayer>();
|
||||||
|
|
||||||
|
// Now make a list we can pass on to OpenXR.
|
||||||
|
Vector<const XrCompositionLayerBaseHeader *> layers_list;
|
||||||
|
for (OrderedCompositionLayer &ordered_layer : ordered_layers_list) {
|
||||||
|
layers_list.push_back(ordered_layer.composition_layer);
|
||||||
|
}
|
||||||
|
|
||||||
XrFrameEndInfo frame_end_info = {
|
XrFrameEndInfo frame_end_info = {
|
||||||
XR_TYPE_FRAME_END_INFO, // type
|
XR_TYPE_FRAME_END_INFO, // type
|
||||||
|
|
|
@ -287,6 +287,15 @@ private:
|
||||||
RID get_interaction_profile_rid(XrPath p_path);
|
RID get_interaction_profile_rid(XrPath p_path);
|
||||||
XrPath get_interaction_profile_path(RID p_interaction_profile);
|
XrPath get_interaction_profile_path(RID p_interaction_profile);
|
||||||
|
|
||||||
|
struct OrderedCompositionLayer {
|
||||||
|
const XrCompositionLayerBaseHeader *composition_layer;
|
||||||
|
int sort_order;
|
||||||
|
|
||||||
|
_FORCE_INLINE_ bool operator()(const OrderedCompositionLayer &a, const OrderedCompositionLayer &b) const {
|
||||||
|
return a.sort_order < b.sort_order || (a.sort_order == b.sort_order && uint64_t(a.composition_layer) < uint64_t(b.composition_layer));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// state changes
|
// state changes
|
||||||
bool poll_events();
|
bool poll_events();
|
||||||
bool on_state_idle();
|
bool on_state_idle();
|
||||||
|
|
Loading…
Reference in New Issue