improve space cleanup

Signed-off-by: Schmarni <marnistromer@gmail.com>
This commit is contained in:
Schmarni
2024-06-24 22:22:01 +02:00
parent b7c4a05482
commit 08cdd232fc
3 changed files with 79 additions and 14 deletions

View File

@@ -52,6 +52,7 @@ pub fn add_xr_plugins<G: PluginGroup>(plugins: G) -> PluginGroupBuilder {
.add(action_set_syncing::OxrActionSyncingPlugin) .add(action_set_syncing::OxrActionSyncingPlugin)
.add(features::overlay::OxrOverlayPlugin) .add(features::overlay::OxrOverlayPlugin)
.add(spaces::OxrSpatialPlugin) .add(spaces::OxrSpatialPlugin)
.add(spaces::OxrSpacePatchingPlugin)
// .add(XrActionPlugin) // .add(XrActionPlugin)
// we should probably handle the exiting ourselfs so that we can correctly end the // we should probably handle the exiting ourselfs so that we can correctly end the
// session and instance // session and instance

View File

@@ -5,14 +5,14 @@ use bevy::{
render::{ render::{
extract_resource::{ExtractResource, ExtractResourcePlugin}, extract_resource::{ExtractResource, ExtractResourcePlugin},
RenderApp, RenderApp,
}, }, utils::HashSet,
}; };
use bevy_xr::{ use bevy_xr::{
session::{XrSessionCreated, XrSessionExiting}, 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 struct OxrReferenceSpacePlugin {
pub default_primary_ref_space: openxr::ReferenceSpaceType, pub default_primary_ref_space: openxr::ReferenceSpaceType,
@@ -48,10 +48,23 @@ impl Plugin for OxrReferenceSpacePlugin {
} }
} }
fn cleanup(mut cmds: Commands, query: Query<Entity, With<XrReferenceSpace>>) { fn cleanup(
query: Query<(Entity, &XrReferenceSpace)>,
mut cmds: Commands,
instance: Res<OxrInstance>,
ref_space: Option<Res<XrPrimaryReferenceSpace>>,
) {
let mut to_destroy = HashSet::<XrSpace>::new();
if let Some(space) = ref_space {
to_destroy.insert(***space);
}
cmds.remove_resource::<XrPrimaryReferenceSpace>(); cmds.remove_resource::<XrPrimaryReferenceSpace>();
for e in &query { for (e, space) in &query {
cmds.entity(e).remove::<XrReferenceSpace>(); cmds.entity(e).remove::<XrReferenceSpace>();
to_destroy.insert(**space);
}
for space in to_destroy.into_iter() {
let _ = instance.destroy_space(space);
} }
} }

View File

@@ -2,7 +2,7 @@ use std::{mem::MaybeUninit, ptr, sync::Mutex};
use bevy::{prelude::*, utils::hashbrown::HashSet}; use bevy::{prelude::*, utils::hashbrown::HashSet};
use bevy_xr::{ use bevy_xr::{
session::{session_available, session_running}, session::{session_available, session_running, XrSessionExiting},
spaces::{XrDestroySpace, XrPrimaryReferenceSpace, XrReferenceSpace, XrSpace, XrSpatialOffset}, spaces::{XrDestroySpace, XrPrimaryReferenceSpace, XrReferenceSpace, XrSpace, XrSpatialOffset},
types::XrPose, types::XrPose,
}; };
@@ -18,20 +18,43 @@ use crate::{
session::OxrSession, 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; pub struct OxrSpatialPlugin;
impl Plugin for OxrSpatialPlugin { impl Plugin for OxrSpatialPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.add_event::<XrDestroySpace>(); app.add_event::<XrDestroySpace>();
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(Startup, patch_destroy_space.run_if(session_available));
app.add_systems(OxrLast, destroy_space_event.before(OxrHandleEvents)); 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<XrDestroySpace>,
) {
let mut to_destroy = HashSet::<XrSpace>::new();
for (e, space) in &query {
to_destroy.insert(*space);
cmds.entity(e).remove::<XrSpace>();
}
for space in to_destroy.into_iter() {
sender.send(XrDestroySpace(space));
} }
} }
fn destroy_space_event(instance: Res<OxrInstance>, mut events: EventReader<XrDestroySpace>) { fn destroy_space_event(instance: Res<OxrInstance>, mut events: EventReader<XrDestroySpace>) {
for space in events.read() { for space in events.read() {
unsafe { match instance.destroy_space(space.0) {
(instance.fp().destroy_space)(space.as_raw_openxr_space()); 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 offset = offset.copied().unwrap_or_default();
let ref_space = ref_space.unwrap_or(&default_ref_space); let ref_space = ref_space.unwrap_or(&default_ref_space);
if let Ok(space_location) = session.locate_space( if let Ok(space_location) = session.locate_space(
&space, space,
ref_space, ref_space,
if pipelined.is_some() { if pipelined.is_some() {
openxr::Time::from_nanos( openxr::Time::from_nanos(
@@ -290,15 +313,29 @@ pub fn destroy_space(
instance: &openxr::Instance, instance: &openxr::Instance,
space: sys::Space, space: sys::Space,
) -> openxr::Result<sys::Result> { ) -> openxr::Result<sys::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) }; let result = unsafe { (instance.fp().destroy_space)(space) };
cvt(result) cvt(result)
} }
impl OxrSession { impl OxrSession {
pub fn destroy_space(&self, space: XrSpace) { pub fn allow_auto_destruct_of_openxr_space(&self, space: &openxr::Space) {
let _ = destroy_space(self.instance(), space.as_raw_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) { pub fn destroy_space(&self, space: XrSpace) -> openxr::Result<sys::Result> {
let _ = destroy_space(self.instance(), space.as_raw()); destroy_space(self.instance(), space.as_raw_openxr_space())
}
pub fn destroy_openxr_space(&self, space: openxr::Space) -> openxr::Result<sys::Result> {
destroy_space(self.instance(), space.as_raw())
} }
pub fn locate_views( pub fn locate_views(
&self, &self,
@@ -368,6 +405,20 @@ impl OxrSession {
} }
} }
impl OxrInstance { 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<sys::Result> {
destroy_space(self, space.as_raw_openxr_space())
}
pub fn destroy_openxr_space(&self, space: openxr::Space) -> openxr::Result<sys::Result> {
destroy_space(self, space.as_raw())
}
pub fn locate_space( pub fn locate_space(
&self, &self,
space: &XrSpace, space: &XrSpace,