works but destroys the session manually because one space somewhere survives session exit

Signed-off-by: Schmarni <marnistromer@gmail.com>
This commit is contained in:
Schmarni
2024-05-24 17:11:38 +02:00
parent 31c1daf2d4
commit 546202fdfa
6 changed files with 53 additions and 25 deletions

View File

@@ -2,6 +2,7 @@
use bevy::prelude::*; use bevy::prelude::*;
use bevy_openxr::add_xr_plugins; use bevy_openxr::add_xr_plugins;
use bevy_xr::session::{XrSharedStatus, XrStatus};
fn main() { fn main() {
App::new() App::new()
@@ -18,6 +19,7 @@ fn handle_input(
mut destroy: EventWriter<bevy_xr::session::DestroyXrSession>, mut destroy: EventWriter<bevy_xr::session::DestroyXrSession>,
mut begin: EventWriter<bevy_xr::session::BeginXrSession>, mut begin: EventWriter<bevy_xr::session::BeginXrSession>,
mut create: EventWriter<bevy_xr::session::CreateXrSession>, mut create: EventWriter<bevy_xr::session::CreateXrSession>,
state: Res<XrSharedStatus>,
) { ) {
if keys.just_pressed(KeyCode::KeyE) { if keys.just_pressed(KeyCode::KeyE) {
info!("sending end"); info!("sending end");
@@ -35,6 +37,9 @@ fn handle_input(
info!("sending create"); info!("sending create");
create.send_default(); create.send_default();
} }
if keys.just_pressed(KeyCode::KeyI) {
info!("current state: {:?}", state.get());
}
} }
/// set up a simple 3D scene /// set up a simple 3D scene

View File

@@ -115,7 +115,8 @@ fn clean_up_default_hands(
query: Query<Entity, Or<(With<DefaultHandTracker>, With<DefaultHandBones>)>>, query: Query<Entity, Or<(With<DefaultHandTracker>, With<DefaultHandBones>)>>,
) { ) {
for e in &query { for e in &query {
cmds.entity(e).despawn(); info!("removing_hand_entity");
cmds.entity(e).despawn_recursive();
} }
} }

View File

@@ -24,6 +24,7 @@ use bevy_xr::session::CreateXrSession;
use bevy_xr::session::DestroyXrSession; use bevy_xr::session::DestroyXrSession;
use bevy_xr::session::EndXrSession; use bevy_xr::session::EndXrSession;
use bevy_xr::session::XrRenderSessionEnding; use bevy_xr::session::XrRenderSessionEnding;
use bevy_xr::session::XrSessionExiting;
use bevy_xr::session::XrSharedStatus; use bevy_xr::session::XrSharedStatus;
use bevy_xr::session::XrStatus; use bevy_xr::session::XrStatus;
use bevy_xr::session::XrStatusChanged; use bevy_xr::session::XrStatusChanged;
@@ -132,13 +133,11 @@ impl Plugin for OxrInitPlugin {
end_xr_session end_xr_session
.run_if(on_event::<EndXrSession>()) .run_if(on_event::<EndXrSession>())
.run_if(status_equals(XrStatus::Running)), .run_if(status_equals(XrStatus::Running)),
destroy_xr_session
.run_if(on_event::<DestroyXrSession>())
.run_if(status_equals(XrStatus::Exiting)),
) )
.in_set(OxrPreUpdateSet::HandleEvents), .in_set(OxrPreUpdateSet::HandleEvents),
), ),
) )
.add_systems(XrSessionExiting, destroy_xr_session)
.add_systems( .add_systems(
PostUpdate, PostUpdate,
update_root_transform.after(TransformSystem::TransformPropagate), update_root_transform.after(TransformSystem::TransformPropagate),
@@ -456,6 +455,7 @@ pub fn create_xr_session(
system_id: Res<OxrSystemId>, system_id: Res<OxrSystemId>,
mut commands: Commands, mut commands: Commands,
) { ) {
info!("creating session!");
match init_xr_session( match init_xr_session(
device.wgpu_device(), device.wgpu_device(),
&instance, &instance,
@@ -481,6 +481,7 @@ pub fn create_xr_session(
pub fn begin_xr_session(session: Res<OxrSession>, session_started: Res<OxrSessionStarted>) { pub fn begin_xr_session(session: Res<OxrSession>, session_started: Res<OxrSessionStarted>) {
let _span = info_span!("xr_begin_session"); let _span = info_span!("xr_begin_session");
info!("begining session!");
session session
.begin(openxr::ViewConfigurationType::PRIMARY_STEREO) .begin(openxr::ViewConfigurationType::PRIMARY_STEREO)
.expect("Failed to begin session"); .expect("Failed to begin session");
@@ -489,6 +490,7 @@ pub fn begin_xr_session(session: Res<OxrSession>, session_started: Res<OxrSessio
pub fn end_xr_session(session: Res<OxrSession>, session_started: Res<OxrSessionStarted>) { pub fn end_xr_session(session: Res<OxrSession>, session_started: Res<OxrSessionStarted>) {
let _span = info_span!("xr_end_session"); let _span = info_span!("xr_end_session");
info!("ending session!");
session session
.request_exit() .request_exit()
.expect("Failed to request session exit"); .expect("Failed to request session exit");
@@ -542,6 +544,7 @@ pub fn poll_events(
SessionState::IDLE => { SessionState::IDLE => {
if status.get() == XrStatus::Available { if status.get() == XrStatus::Available {
session_status_events.send(OxrSessionStatusEvent::Created); session_status_events.send(OxrSessionStatusEvent::Created);
info!("sending create info");
} }
XrStatus::Idle XrStatus::Idle
} }
@@ -552,6 +555,7 @@ pub fn poll_events(
SessionState::STOPPING => XrStatus::Stopping, SessionState::STOPPING => XrStatus::Stopping,
SessionState::EXITING | SessionState::LOSS_PENDING => { SessionState::EXITING | SessionState::LOSS_PENDING => {
session_status_events.send(OxrSessionStatusEvent::AboutToBeDestroyed); session_status_events.send(OxrSessionStatusEvent::AboutToBeDestroyed);
info!("sending destroy info");
XrStatus::Exiting XrStatus::Exiting
} }
_ => unreachable!(), _ => unreachable!(),
@@ -583,4 +587,10 @@ pub fn destroy_xr_session_render(world: &mut World) {
world.remove_resource::<OxrGraphicsInfo>(); world.remove_resource::<OxrGraphicsInfo>();
world.run_schedule(XrRenderSessionEnding); world.run_schedule(XrRenderSessionEnding);
world.run_system_once(apply_deferred); world.run_system_once(apply_deferred);
if let Some(sess) = world.remove_resource::<OxrSession>() {
unsafe {
(sess.instance().fp().destroy_session)(sess.as_raw());
}
Box::leak(Box::new(sess));
}
} }

View File

@@ -148,7 +148,6 @@ impl OxrInstance {
} }
} }
/// Graphics agnostic wrapper around [openxr::FrameStream] /// Graphics agnostic wrapper around [openxr::FrameStream]
#[derive(Resource)] #[derive(Resource)]
pub struct OxrFrameStream(pub GraphicsWrap<Self>); pub struct OxrFrameStream(pub GraphicsWrap<Self>);
@@ -283,20 +282,15 @@ impl OxrSwapchain {
images.push(Api::to_wgpu_img(image, device, format, resolution)?); images.push(Api::to_wgpu_img(image, device, format, resolution)?);
} }
} }
Ok(OxrSwapchainImages(images.into())) Ok(OxrSwapchainImages(images.leak()))
} }
) )
} }
} }
/// Stores the generated swapchain images. /// Stores the generated swapchain images.
#[derive(Debug, Deref, Resource, Clone)] #[derive(Debug, Deref, Resource, Clone, Copy)]
pub struct OxrSwapchainImages(pub Arc<Vec<wgpu::Texture>>); pub struct OxrSwapchainImages(pub &'static [wgpu::Texture]);
impl Drop for OxrSwapchainImages {
fn drop(&mut self) {
info!("Dropping Swapchain Images");
}
}
/// Thread safe wrapper around [openxr::Space] representing the stage. /// Thread safe wrapper around [openxr::Space] representing the stage.
// #[derive(Deref, Clone, Resource)] // #[derive(Deref, Clone, Resource)]

View File

@@ -5,8 +5,11 @@ use crate::resources::{
use crate::types::{Result, SwapchainCreateInfo}; use crate::types::{Result, SwapchainCreateInfo};
use bevy::ecs::system::{RunSystemOnce, SystemState}; use bevy::ecs::system::{RunSystemOnce, SystemState};
use bevy::prelude::*; use bevy::prelude::*;
use bevy::render::extract_resource::ExtractResourcePlugin;
use bevy::render::RenderApp;
use bevy_xr::session::{ use bevy_xr::session::{
status_changed_to, XrRenderSessionEnding, XrSessionCreated, XrSessionExiting, XrStatus, status_changed_to, XrRenderSessionEnding, XrSessionCreated, XrSessionExiting, XrSharedStatus,
XrStatus,
}; };
use openxr::AnyGraphics; use openxr::AnyGraphics;
@@ -28,10 +31,11 @@ impl Plugin for OxrSessionPlugin {
run_session_status_schedules.in_set(OxrPreUpdateSet::HandleEvents), run_session_status_schedules.in_set(OxrPreUpdateSet::HandleEvents),
); );
app.add_systems(XrSessionExiting, clean_session); app.add_systems(XrSessionExiting, clean_session);
app.add_systems(XrRenderSessionEnding, |mut cmds: Commands| { app.sub_app_mut(RenderApp)
cmds.remove_resource::<OxrSession>(); .add_systems(XrRenderSessionEnding, |mut cmds: Commands| {
cmds.remove_resource::<OxrCleanupSession>(); // cmds.remove_resource::<OxrSession>();
}); cmds.remove_resource::<OxrCleanupSession>();
});
app.add_systems( app.add_systems(
PreUpdate, PreUpdate,
handle_stopping_state.run_if(status_changed_to(XrStatus::Stopping)), handle_stopping_state.run_if(status_changed_to(XrStatus::Stopping)),
@@ -44,9 +48,13 @@ fn handle_stopping_state(session: Res<OxrSession>, session_started: Res<OxrSessi
session_started.set(false); session_started.set(false);
} }
fn clean_session(mut cmds: Commands) { fn clean_session(world: &mut World) {
cmds.remove_resource::<OxrSession>(); world.insert_resource(OxrCleanupSession(true));
cmds.insert_resource(OxrCleanupSession(true)); // It should be impossible to call this if the session is Unavailable
world
.get_resource::<XrSharedStatus>()
.unwrap()
.set(XrStatus::Available);
} }
fn run_session_status_schedules(world: &mut World) { fn run_session_status_schedules(world: &mut World) {
@@ -62,6 +70,11 @@ fn run_session_status_schedules(world: &mut World) {
OxrSessionStatusEvent::AboutToBeDestroyed => { OxrSessionStatusEvent::AboutToBeDestroyed => {
world.run_schedule(XrSessionExiting); world.run_schedule(XrSessionExiting);
world.run_system_once(apply_deferred); world.run_system_once(apply_deferred);
if let Some(sess) = world.remove_resource::<OxrSession>() {
// unsafe {
// (sess.instance().fp().destroy_session)(sess.as_raw());
// }
}
} }
} }
} }
@@ -80,6 +93,11 @@ pub struct OxrSession(
/// This is so that we can still operate on functions that don't take [`AnyGraphics`] as the generic. /// This is so that we can still operate on functions that don't take [`AnyGraphics`] as the generic.
pub(crate) GraphicsWrap<Self>, pub(crate) GraphicsWrap<Self>,
); );
impl Drop for OxrSession {
fn drop(&mut self) {
info!("dropping session");
}
}
impl GraphicsType for OxrSession { impl GraphicsType for OxrSession {
type Inner<G: GraphicsExt> = openxr::Session<G>; type Inner<G: GraphicsExt> = openxr::Session<G>;

View File

@@ -13,10 +13,10 @@ impl Plugin for XrSessionPlugin {
.add_event::<BeginXrSession>() .add_event::<BeginXrSession>()
.add_event::<EndXrSession>() .add_event::<EndXrSession>()
.add_event::<XrStatusChanged>() .add_event::<XrStatusChanged>()
.add_systems( // .add_systems(
PreUpdate, // PreUpdate,
handle_session.run_if(resource_exists::<XrSharedStatus>), // handle_session.run_if(resource_exists::<XrSharedStatus>),
); /* ) */;
} }
fn finish(&self, app: &mut App) { fn finish(&self, app: &mut App) {
// This is in finnish because we need the RenderPlugin to already be added. // This is in finnish because we need the RenderPlugin to already be added.