partialy revert the scheduling changes and fix non xr crash

Signed-off-by: Schmarni <marnistromer@gmail.com>
This commit is contained in:
Schmarni
2024-07-12 08:20:50 +02:00
parent 3d773f86ba
commit 1eed718860
8 changed files with 111 additions and 100 deletions

2
Cargo.lock generated
View File

@@ -758,7 +758,7 @@ dependencies = [
"bevy", "bevy",
"bevy_mod_xr", "bevy_mod_xr",
"bevy_xr_utils", "bevy_xr_utils",
"d3d12 0.19.0", "d3d12 0.20.0",
"jni 0.20.0", "jni 0.20.0",
"ndk-context", "ndk-context",
"openxr", "openxr",

View File

@@ -6,13 +6,12 @@ use bevy_mod_openxr::{
action_set_attaching::OxrAttachActionSet, action_set_attaching::OxrAttachActionSet,
action_set_syncing::{OxrActionSetSyncSet, OxrSyncActionSet}, action_set_syncing::{OxrActionSetSyncSet, OxrSyncActionSet},
add_xr_plugins, add_xr_plugins,
init::create_xr_session,
resources::OxrInstance, resources::OxrInstance,
session::OxrSession, session::OxrSession,
spaces::OxrSpaceExt, spaces::OxrSpaceExt,
}; };
use bevy_mod_xr::{ use bevy_mod_xr::{
session::{session_available, XrCreateSession, XrTrackingRoot}, session::{session_available, session_running, XrSessionCreated, XrTrackingRoot},
spaces::XrSpace, spaces::XrSpace,
types::XrPose, types::XrPose,
}; };
@@ -21,9 +20,14 @@ use openxr::Posef;
fn main() { fn main() {
let mut app = App::new(); let mut app = App::new();
app.add_plugins(add_xr_plugins(DefaultPlugins)); app.add_plugins(add_xr_plugins(DefaultPlugins));
app.add_systems(XrCreateSession, spawn_hands.after(create_xr_session)); app.add_systems(XrSessionCreated, spawn_hands);
app.add_systems(XrCreateSession, attach_set.after(create_xr_session)); app.add_systems(XrSessionCreated, attach_set);
app.add_systems(PreUpdate, sync_actions.before(OxrActionSetSyncSet)); app.add_systems(
PreUpdate,
sync_actions
.before(OxrActionSetSyncSet)
.run_if(session_running),
);
app.add_systems(OxrSendActionBindings, suggest_action_bindings); app.add_systems(OxrSendActionBindings, suggest_action_bindings);
app.add_systems(Startup, create_actions.run_if(session_available)); app.add_systems(Startup, create_actions.run_if(session_available));
app.add_systems(Startup, setup); app.add_systems(Startup, setup);

View File

@@ -1,6 +1,6 @@
use bevy::prelude::*; use bevy::prelude::*;
use bevy_mod_xr::hands::{LeftHand, RightHand, XrHandBoneEntities, HAND_JOINT_COUNT}; use bevy_mod_xr::hands::{LeftHand, RightHand, XrHandBoneEntities, HAND_JOINT_COUNT};
use bevy_mod_xr::session::{XrCreateSession, XrDestroySession, XrTrackingRoot}; use bevy_mod_xr::session::{XrPreDestroySession, XrSessionCreated, XrTrackingRoot};
use bevy_mod_xr::spaces::{XrPrimaryReferenceSpace, XrReferenceSpace}; use bevy_mod_xr::spaces::{XrPrimaryReferenceSpace, XrReferenceSpace};
use bevy_mod_xr::{ use bevy_mod_xr::{
hands::{HandBone, HandBoneRadius}, hands::{HandBone, HandBoneRadius},
@@ -28,13 +28,8 @@ impl Plugin for HandTrackingPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.add_systems(PreUpdate, locate_hands.run_if(session_running)); app.add_systems(PreUpdate, locate_hands.run_if(session_running));
if self.default_hands { if self.default_hands {
app.add_systems(XrDestroySession, clean_up_default_hands) app.add_systems(XrPreDestroySession, clean_up_default_hands)
.add_systems( .add_systems(XrSessionCreated, spawn_default_hands);
XrCreateSession,
(spawn_default_hands, apply_deferred)
.chain()
.after(create_xr_session),
);
} }
} }
} }

View File

@@ -105,14 +105,30 @@ impl Plugin for OxrInitPlugin {
.add_systems( .add_systems(
XrFirst, XrFirst,
poll_events poll_events
.before(XrHandleEvents) .in_set(XrHandleEvents::Poll)
.run_if(not(state_equals(XrState::Unavailable))), .run_if(not(state_equals(XrState::Unavailable))),
) )
.add_systems(XrCreateSession, create_xr_session) .add_systems(
.add_systems(XrDestroySession, destroy_xr_session) XrFirst,
.add_systems(XrBeginSession, begin_xr_session) (
.add_systems(XrEndSession, end_xr_session) create_xr_session
.add_systems(XrRequestExit, request_exit_xr_session) .run_if(state_equals(XrState::Available))
.run_if(on_event::<XrCreateSessionEvent>()),
destroy_xr_session
.run_if(state_matches!(XrState::Exiting { .. }))
.run_if(on_event::<XrDestroySessionEvent>()),
begin_xr_session
.run_if(state_equals(XrState::Ready))
.run_if(on_event::<XrBeginSessionEvent>()),
end_xr_session
.run_if(state_equals(XrState::Stopping))
.run_if(on_event::<XrEndSessionEvent>()),
request_exit_xr_session
.run_if(session_created)
.run_if(on_event::<XrRequestExitEvent>()),
)
.in_set(XrHandleEvents::SessionStateUpdateEvents),
)
.insert_resource(instance.clone()) .insert_resource(instance.clone())
.insert_resource(system_id) .insert_resource(system_id)
.insert_resource(XrState::Available) .insert_resource(XrState::Available)
@@ -150,7 +166,7 @@ impl Plugin for OxrInitPlugin {
fn finish(&self, app: &mut App) { fn finish(&self, app: &mut App) {
app.sub_app_mut(RenderApp) app.sub_app_mut(RenderApp)
.add_systems(XrDestroySession, destroy_xr_session); .add_systems(XrPreDestroySession, destroy_xr_session);
} }
} }
@@ -468,9 +484,13 @@ pub fn create_xr_session(world: &mut World) {
Err(e) => error!("Failed to initialize XrSession: {e}"), Err(e) => error!("Failed to initialize XrSession: {e}"),
} }
world.insert_non_send_resource(chain); world.insert_non_send_resource(chain);
world.run_schedule(XrSessionCreated);
world.send_event(XrSessionCreatedEvent);
} }
pub fn destroy_xr_session(world: &mut World) { pub fn destroy_xr_session(world: &mut World) {
world.run_schedule(XrPreDestroySession);
world.insert_resource(XrDestroySessionRender);
world.remove_resource::<OxrSession>(); world.remove_resource::<OxrSession>();
world.remove_resource::<OxrFrameWaiter>(); world.remove_resource::<OxrFrameWaiter>();
world.remove_resource::<OxrFrameStream>(); world.remove_resource::<OxrFrameStream>();
@@ -480,18 +500,33 @@ pub fn destroy_xr_session(world: &mut World) {
world.insert_resource(XrState::Available); world.insert_resource(XrState::Available);
} }
pub fn begin_xr_session(session: Res<OxrSession>, mut session_started: ResMut<OxrSessionStarted>) { pub fn begin_xr_session(
world: &mut World,
// session: Res<OxrSession>, mut session_started: ResMut<OxrSessionStarted>
) {
let _span = info_span!("xr_begin_session"); let _span = info_span!("xr_begin_session");
session world
.get_resource::<OxrSession>()
.unwrap()
.begin(openxr::ViewConfigurationType::PRIMARY_STEREO) .begin(openxr::ViewConfigurationType::PRIMARY_STEREO)
.expect("Failed to begin session"); .expect("Failed to begin session");
session_started.0 = true; world.get_resource_mut::<OxrSessionStarted>().unwrap().0 = true;
world.run_schedule(XrBeginSession);
} }
pub fn end_xr_session(session: Res<OxrSession>, mut session_started: ResMut<OxrSessionStarted>) { pub fn end_xr_session(
world: &mut World,
// session: Res<OxrSession>, mut session_started: ResMut<OxrSessionStarted>
) {
// Maybe this could be an event?
world.run_schedule(XrEndSession);
let _span = info_span!("xr_end_session"); let _span = info_span!("xr_end_session");
session.end().expect("Failed to end session"); world
session_started.0 = false; .get_resource::<OxrSession>()
.unwrap()
.end()
.expect("Failed to end session");
world.get_resource_mut::<OxrSessionStarted>().unwrap().0 = false;
} }
pub fn request_exit_xr_session(session: Res<OxrSession>) { pub fn request_exit_xr_session(session: Res<OxrSession>) {

View File

@@ -3,7 +3,7 @@ use bevy::{
render::{extract_resource::ExtractResourcePlugin, RenderApp}, render::{extract_resource::ExtractResourcePlugin, RenderApp},
}; };
use bevy_mod_xr::{ use bevy_mod_xr::{
session::{XrCreateSession, XrDestroySession}, session::{XrPreDestroySession, XrSessionCreated},
spaces::{XrPrimaryReferenceSpace, XrReferenceSpace}, spaces::{XrPrimaryReferenceSpace, XrReferenceSpace},
}; };
@@ -38,15 +38,12 @@ impl Plugin for OxrReferenceSpacePlugin {
.insert_resource(OxrDefaultPrimaryReferenceSpaceType( .insert_resource(OxrDefaultPrimaryReferenceSpaceType(
self.default_primary_ref_space, self.default_primary_ref_space,
)) ))
.add_systems( .add_systems(XrSessionCreated, set_primary_ref_space)
XrCreateSession, .add_systems(XrPreDestroySession, cleanup);
set_primary_ref_space.after(create_xr_session),
)
.add_systems(XrDestroySession, cleanup);
let render_app = app.sub_app_mut(RenderApp); let render_app = app.sub_app_mut(RenderApp);
render_app.add_systems(XrDestroySession, cleanup); render_app.add_systems(XrPreDestroySession, cleanup);
} }
} }

View File

@@ -13,7 +13,7 @@ use bevy::{
use bevy_mod_xr::{ use bevy_mod_xr::{
camera::{XrCamera, XrCameraBundle, XrProjection}, camera::{XrCamera, XrCameraBundle, XrProjection},
session::{ session::{
XrDestroySession, XrFirst, XrHandleEvents, XrRenderSet, XrRootTransform, XrTrackingRoot, XrFirst, XrHandleEvents, XrPreDestroySession, XrRenderSet, XrRootTransform, XrTrackingRoot,
}, },
spaces::XrPrimaryReferenceSpace, spaces::XrPrimaryReferenceSpace,
}; };
@@ -46,7 +46,7 @@ impl Plugin for OxrRenderPlugin {
ExtractResourcePlugin::<OxrSwapchainImages>::default(), ExtractResourcePlugin::<OxrSwapchainImages>::default(),
ExtractResourcePlugin::<OxrViews>::default(), ExtractResourcePlugin::<OxrViews>::default(),
)) ))
.add_systems(XrDestroySession, clean_views) .add_systems(XrPreDestroySession, clean_views)
.add_systems( .add_systems(
XrFirst, XrFirst,
( (
@@ -55,7 +55,7 @@ impl Plugin for OxrRenderPlugin {
init_views.run_if(resource_added::<OxrSession>), init_views.run_if(resource_added::<OxrSession>),
) )
.chain() .chain()
.after(XrHandleEvents), .in_set(XrHandleEvents::FrameLoop),
) )
.add_systems( .add_systems(
PostUpdate, PostUpdate,
@@ -70,7 +70,7 @@ impl Plugin for OxrRenderPlugin {
let render_app = app.sub_app_mut(RenderApp); let render_app = app.sub_app_mut(RenderApp);
render_app render_app
.add_systems(XrDestroySession, clean_views) .add_systems(XrPreDestroySession, clean_views)
.add_systems( .add_systems(
Render, Render,
( (

View File

@@ -31,7 +31,12 @@ 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>()
.add_systems(XrFirst, destroy_space_event.before(XrHandleEvents)) .add_systems(
XrFirst,
destroy_space_event
.before(XrHandleEvents::Poll)
.run_if(session_available),
)
.add_systems( .add_systems(
PreUpdate, PreUpdate,
update_space_transforms update_space_transforms

View File

@@ -10,7 +10,7 @@ pub struct XrCreateSessionEvent;
/// A schedule thats ran whenever an [`XrCreateSessionEvent`] is recieved while the [`XrState`] is [`Available`](XrState::Available) /// A schedule thats ran whenever an [`XrCreateSessionEvent`] is recieved while the [`XrState`] is [`Available`](XrState::Available)
#[derive(Clone, Copy, Default, PartialEq, Eq, Debug, Hash, ScheduleLabel)] #[derive(Clone, Copy, Default, PartialEq, Eq, Debug, Hash, ScheduleLabel)]
pub struct XrCreateSession; pub struct XrSessionCreated;
/// Event sent when [`XrCreateSession`] is ran /// Event sent when [`XrCreateSession`] is ran
#[derive(Event, Clone, Copy, Default)] #[derive(Event, Clone, Copy, Default)]
@@ -27,7 +27,7 @@ pub struct XrDestroySessionRender;
/// Schedule thats ran whenever an [`XrDestroySessionEvent`] is recieved while the [`XrState`] is [`Exiting`](XrState::Exiting). /// Schedule thats ran whenever an [`XrDestroySessionEvent`] is recieved while the [`XrState`] is [`Exiting`](XrState::Exiting).
#[derive(Clone, Copy, Default, PartialEq, Eq, Debug, Hash, ScheduleLabel)] #[derive(Clone, Copy, Default, PartialEq, Eq, Debug, Hash, ScheduleLabel)]
pub struct XrDestroySession; pub struct XrPreDestroySession;
/// Event sent to instruct backends to begin an XR session. Only works when the [`XrState`] is [`Ready`](XrState::Ready). /// Event sent to instruct backends to begin an XR session. Only works when the [`XrState`] is [`Ready`](XrState::Ready).
#[derive(Event, Clone, Copy, Default)] #[derive(Event, Clone, Copy, Default)]
@@ -49,16 +49,19 @@ pub struct XrEndSession;
#[derive(Event, Clone, Copy, Default)] #[derive(Event, Clone, Copy, Default)]
pub struct XrRequestExitEvent; pub struct XrRequestExitEvent;
#[derive(Clone, Copy, Default, PartialEq, Eq, Debug, Hash, ScheduleLabel)]
pub struct XrRequestExit;
/// Schedule ran before [`First`] to handle XR events. /// Schedule ran before [`First`] to handle XR events.
#[derive(Clone, Copy, Default, PartialEq, Eq, Debug, Hash, ScheduleLabel)] #[derive(Clone, Copy, Default, PartialEq, Eq, Debug, Hash, ScheduleLabel)]
pub struct XrFirst; pub struct XrFirst;
/// System set for systems related to handling XR session events and updating the [`XrState`] /// System sets for systems related to handling XR session events and updating the [`XrState`]
#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy, SystemSet)] #[derive(Debug, Hash, PartialEq, Eq, Clone, Copy, SystemSet)]
pub struct XrHandleEvents; pub enum XrHandleEvents {
Poll,
ExitEvents,
SessionStateUpdateEvents,
Cleanup,
FrameLoop,
}
/// System sets ran in the render world for XR. /// System sets ran in the render world for XR.
#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy, SystemSet)] #[derive(Debug, Hash, PartialEq, Eq, Clone, Copy, SystemSet)]
@@ -95,39 +98,33 @@ impl Plugin for XrSessionPlugin {
.add_event::<XrRequestExitEvent>() .add_event::<XrRequestExitEvent>()
.add_event::<XrStateChanged>() .add_event::<XrStateChanged>()
.add_event::<XrSessionCreatedEvent>() .add_event::<XrSessionCreatedEvent>()
.init_schedule(XrCreateSession) .init_schedule(XrSessionCreated)
.init_schedule(XrDestroySession) .init_schedule(XrPreDestroySession)
.init_schedule(XrBeginSession) .init_schedule(XrBeginSession)
.init_schedule(XrEndSession) .init_schedule(XrEndSession)
.init_schedule(XrRequestExit)
.add_schedule(xr_first) .add_schedule(xr_first)
.add_systems( .configure_sets(
XrFirst, XrFirst,
( (
XrHandleEvents::Poll,
XrHandleEvents::ExitEvents,
XrHandleEvents::SessionStateUpdateEvents,
XrHandleEvents::Cleanup,
XrHandleEvents::FrameLoop,
)
.chain(),
)
.add_systems(
XrFirst,
exits_session_on_app_exit exits_session_on_app_exit
.run_if(on_event::<AppExit>()) .run_if(on_event::<AppExit>())
.run_if(session_created),
reset_per_frame_resources,
run_xr_create_session
.run_if(state_equals(XrState::Available))
.run_if(on_event::<XrCreateSessionEvent>()),
run_xr_destroy_session
.run_if(state_matches!(XrState::Exiting { .. }))
.run_if(on_event::<XrDestroySessionEvent>()),
run_xr_begin_session
.run_if(state_equals(XrState::Ready))
.run_if(on_event::<XrBeginSessionEvent>()),
run_xr_end_session
.run_if(state_equals(XrState::Stopping))
.run_if(on_event::<XrEndSessionEvent>()),
run_xr_request_exit
.run_if(session_created) .run_if(session_created)
.run_if(on_event::<XrRequestExitEvent>()), .in_set(XrHandleEvents::ExitEvents),
) )
.chain() .add_systems(
.in_set(XrHandleEvents), XrFirst,
reset_per_frame_resources.in_set(XrHandleEvents::Cleanup),
); );
app.world_mut() app.world_mut()
.resource_mut::<MainScheduleOrder>() .resource_mut::<MainScheduleOrder>()
.labels .labels
@@ -156,14 +153,14 @@ impl Plugin for XrSessionPlugin {
.add_systems( .add_systems(
XrFirst, XrFirst,
exits_session_on_app_exit exits_session_on_app_exit
.before(XrHandleEvents) .before(XrHandleEvents::ExitEvents)
.run_if(on_event::<AppExit>().and_then(session_running)), .run_if(on_event::<AppExit>().and_then(session_running)),
); );
let render_app = app.sub_app_mut(RenderApp); let render_app = app.sub_app_mut(RenderApp);
render_app render_app
.init_schedule(XrDestroySession) .init_schedule(XrPreDestroySession)
.init_resource::<XrRootTransform>() .init_resource::<XrRootTransform>()
.configure_sets( .configure_sets(
Render, Render,
@@ -188,9 +185,9 @@ impl Plugin for XrSessionPlugin {
.add_systems( .add_systems(
Render, Render,
( (
run_xr_destroy_session // run_xr_destroy_session
.run_if(resource_exists::<XrDestroySessionRender>) // .run_if(resource_exists::<XrDestroySessionRender>)
.in_set(XrRenderSet::HandleEvents), // .in_set(XrRenderSet::HandleEvents),
reset_per_frame_resources.in_set(RenderSet::Cleanup), reset_per_frame_resources.in_set(RenderSet::Cleanup),
), ),
); );
@@ -228,28 +225,6 @@ pub enum XrState {
}, },
} }
pub fn run_xr_create_session(world: &mut World) {
world.run_schedule(XrCreateSession);
world.send_event(XrSessionCreatedEvent);
}
pub fn run_xr_destroy_session(world: &mut World) {
world.run_schedule(XrDestroySession);
world.insert_resource(XrDestroySessionRender);
}
pub fn run_xr_begin_session(world: &mut World) {
world.run_schedule(XrBeginSession);
}
pub fn run_xr_end_session(world: &mut World) {
world.run_schedule(XrEndSession);
}
pub fn run_xr_request_exit(world: &mut World) {
world.run_schedule(XrRequestExit);
}
pub fn reset_per_frame_resources(world: &mut World) { pub fn reset_per_frame_resources(world: &mut World) {
world.remove_resource::<XrDestroySessionRender>(); world.remove_resource::<XrDestroySessionRender>();
} }
@@ -330,7 +305,7 @@ pub fn state_equals(status: XrState) -> impl FnMut(Option<Res<XrState>>) -> bool
#[macro_export] #[macro_export]
macro_rules! state_matches { macro_rules! state_matches {
($match:pat) => { ($match:pat) => {
(|state: Option<Res<XrState>>| core::matches!(state.as_deref(), Some($match))) |state: Option<Res<XrState>>| core::matches!(state.as_deref(), Some($match))
}; };
} }