From 08cdd232fc177a01ff7add1c3e312cfbf9564c08 Mon Sep 17 00:00:00 2001 From: Schmarni Date: Mon, 24 Jun 2024 22:22:01 +0200 Subject: [PATCH] improve space cleanup Signed-off-by: Schmarni --- crates/bevy_openxr/src/openxr/mod.rs | 1 + .../bevy_openxr/src/openxr/reference_space.rs | 23 +++++-- crates/bevy_openxr/src/openxr/spaces.rs | 69 ++++++++++++++++--- 3 files changed, 79 insertions(+), 14 deletions(-) diff --git a/crates/bevy_openxr/src/openxr/mod.rs b/crates/bevy_openxr/src/openxr/mod.rs index 8ccc780..3f9f7e8 100644 --- a/crates/bevy_openxr/src/openxr/mod.rs +++ b/crates/bevy_openxr/src/openxr/mod.rs @@ -52,6 +52,7 @@ pub fn add_xr_plugins(plugins: G) -> PluginGroupBuilder { .add(action_set_syncing::OxrActionSyncingPlugin) .add(features::overlay::OxrOverlayPlugin) .add(spaces::OxrSpatialPlugin) + .add(spaces::OxrSpacePatchingPlugin) // .add(XrActionPlugin) // we should probably handle the exiting ourselfs so that we can correctly end the // session and instance diff --git a/crates/bevy_openxr/src/openxr/reference_space.rs b/crates/bevy_openxr/src/openxr/reference_space.rs index af76ff2..d4efdea 100644 --- a/crates/bevy_openxr/src/openxr/reference_space.rs +++ b/crates/bevy_openxr/src/openxr/reference_space.rs @@ -5,14 +5,14 @@ use bevy::{ render::{ extract_resource::{ExtractResource, ExtractResourcePlugin}, RenderApp, - }, + }, utils::HashSet, }; use bevy_xr::{ session::{XrSessionCreated, XrSessionExiting}, - spaces::{XrPrimaryReferenceSpace, XrReferenceSpace}, + spaces::{XrDestroySpace, XrPrimaryReferenceSpace, XrReferenceSpace, XrSpace}, }; -use crate::session::OxrSession; +use crate::{resources::OxrInstance, session::OxrSession}; pub struct OxrReferenceSpacePlugin { pub default_primary_ref_space: openxr::ReferenceSpaceType, @@ -48,10 +48,23 @@ impl Plugin for OxrReferenceSpacePlugin { } } -fn cleanup(mut cmds: Commands, query: Query>) { +fn cleanup( + query: Query<(Entity, &XrReferenceSpace)>, + mut cmds: Commands, + instance: Res, + ref_space: Option>, +) { + let mut to_destroy = HashSet::::new(); + if let Some(space) = ref_space { + to_destroy.insert(***space); + } cmds.remove_resource::(); - for e in &query { + for (e, space) in &query { cmds.entity(e).remove::(); + to_destroy.insert(**space); + } + for space in to_destroy.into_iter() { + let _ = instance.destroy_space(space); } } diff --git a/crates/bevy_openxr/src/openxr/spaces.rs b/crates/bevy_openxr/src/openxr/spaces.rs index b44b3a0..4b4eb7d 100644 --- a/crates/bevy_openxr/src/openxr/spaces.rs +++ b/crates/bevy_openxr/src/openxr/spaces.rs @@ -2,7 +2,7 @@ use std::{mem::MaybeUninit, ptr, sync::Mutex}; use bevy::{prelude::*, utils::hashbrown::HashSet}; use bevy_xr::{ - session::{session_available, session_running}, + session::{session_available, session_running, XrSessionExiting}, spaces::{XrDestroySpace, XrPrimaryReferenceSpace, XrReferenceSpace, XrSpace, XrSpatialOffset}, types::XrPose, }; @@ -18,20 +18,43 @@ use crate::{ session::OxrSession, }; +/// VERY IMPORTENT!! only disable when you know what you are doing +pub struct OxrSpacePatchingPlugin; +impl Plugin for OxrSpacePatchingPlugin { + fn build(&self, app: &mut App) { + app.add_systems(Startup, patch_destroy_space.run_if(session_available)); + } +} pub struct OxrSpatialPlugin; impl Plugin for OxrSpatialPlugin { fn build(&self, app: &mut App) { app.add_event::(); - app.add_systems(PreUpdate, update_spatial_transforms.run_if(session_running)); app.add_systems(Startup, patch_destroy_space.run_if(session_available)); app.add_systems(OxrLast, destroy_space_event.before(OxrHandleEvents)); + app.add_systems(XrSessionExiting, destroy_space_components); + } +} + +fn destroy_space_components( + query: Query<(Entity, &XrSpace)>, + mut cmds: Commands, + mut sender: EventWriter, +) { + let mut to_destroy = HashSet::::new(); + for (e, space) in &query { + to_destroy.insert(*space); + cmds.entity(e).remove::(); + } + for space in to_destroy.into_iter() { + sender.send(XrDestroySpace(space)); } } fn destroy_space_event(instance: Res, mut events: EventReader) { for space in events.read() { - unsafe { - (instance.fp().destroy_space)(space.as_raw_openxr_space()); + match instance.destroy_space(space.0) { + Ok(_) => (), + Err(err) => warn!("error while destroying space: {}", err), } } } @@ -89,7 +112,7 @@ fn update_spatial_transforms( let offset = offset.copied().unwrap_or_default(); let ref_space = ref_space.unwrap_or(&default_ref_space); if let Ok(space_location) = session.locate_space( - &space, + space, ref_space, if pipelined.is_some() { openxr::Time::from_nanos( @@ -290,15 +313,29 @@ pub fn destroy_space( instance: &openxr::Instance, space: sys::Space, ) -> openxr::Result { + OXR_DO_NOT_CALL_DESTOY_SPACE_FOR_SPACES + .lock() + .unwrap() + .as_mut() + .unwrap() + .remove(&space.into_raw()); let result = unsafe { (instance.fp().destroy_space)(space) }; cvt(result) } impl OxrSession { - pub fn destroy_space(&self, space: XrSpace) { - let _ = destroy_space(self.instance(), space.as_raw_openxr_space()); + pub fn allow_auto_destruct_of_openxr_space(&self, space: &openxr::Space) { + OXR_DO_NOT_CALL_DESTOY_SPACE_FOR_SPACES + .lock() + .unwrap() + .as_mut() + .unwrap() + .remove(&space.as_raw().into_raw()); } - pub fn destroy_openxr_space(&self, space: openxr::Space) { - let _ = destroy_space(self.instance(), space.as_raw()); + pub fn destroy_space(&self, space: XrSpace) -> openxr::Result { + destroy_space(self.instance(), space.as_raw_openxr_space()) + } + pub fn destroy_openxr_space(&self, space: openxr::Space) -> openxr::Result { + destroy_space(self.instance(), space.as_raw()) } pub fn locate_views( &self, @@ -368,6 +405,20 @@ impl OxrSession { } } impl OxrInstance { + pub fn allow_auto_destruct_of_openxr_space(&self, space: &openxr::Space) { + OXR_DO_NOT_CALL_DESTOY_SPACE_FOR_SPACES + .lock() + .unwrap() + .as_mut() + .unwrap() + .remove(&space.as_raw().into_raw()); + } + pub fn destroy_space(&self, space: XrSpace) -> openxr::Result { + destroy_space(self, space.as_raw_openxr_space()) + } + pub fn destroy_openxr_space(&self, space: openxr::Space) -> openxr::Result { + destroy_space(self, space.as_raw()) + } pub fn locate_space( &self, space: &XrSpace,