Merge pull request #154 from Schmarni-Dev/fix-destruction

fix session destroying
This commit is contained in:
Schmarni
2024-09-07 12:02:27 +02:00
committed by GitHub
5 changed files with 397 additions and 333 deletions

657
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -37,7 +37,7 @@ ash = { version = "0.37.3", optional = true }
[target.'cfg(target_family = "unix")'.dependencies]
openxr = { version = "0.18.0", features = ["mint"] }
wgpu = { version = "0.19.3", features = ["vulkan-portability"] }
wgpu = { version = "0.20", features = ["vulkan-portability"] }
[target.'cfg(target_family = "windows")'.dependencies]
openxr = { version = "0.18.0", features = ["mint", "static"] }

View File

@@ -6,7 +6,7 @@ use bevy_mod_xr::session::{XrSessionPlugin, XrState};
fn main() {
App::new()
.add_plugins(add_xr_plugins(DefaultPlugins).set(XrSessionPlugin { auto_handle: false }))
.add_plugins(add_xr_plugins(DefaultPlugins).set(XrSessionPlugin { auto_handle: true }))
.add_plugins(bevy_xr_utils::hand_gizmos::HandGizmosPlugin)
.add_systems(Startup, setup)
.add_systems(Update, handle_input)

View File

@@ -1,6 +1,9 @@
use std::sync::atomic::Ordering;
use std::sync::Arc;
use bevy::ecs::system::RunSystemOnce;
use bevy::prelude::*;
use bevy::render::extract_resource::ExtractResource;
use bevy::render::extract_resource::ExtractResourcePlugin;
use bevy::render::renderer::RenderAdapter;
use bevy::render::renderer::RenderAdapterInfo;
@@ -10,6 +13,7 @@ use bevy::render::renderer::RenderQueue;
use bevy::render::renderer::WgpuWrapper;
use bevy::render::settings::RenderCreation;
use bevy::render::MainWorld;
use bevy::render::Render;
use bevy::render::RenderApp;
use bevy::render::RenderPlugin;
use bevy::winit::UpdateMode;
@@ -116,7 +120,13 @@ impl Plugin for OxrInitPlugin {
create_xr_session
.run_if(state_equals(XrState::Available))
.run_if(on_event::<XrCreateSessionEvent>()),
destroy_xr_session
(
destroy_xr_session,
(|v: Res<XrDestroySessionRender>| {
v.0.store(true, Ordering::Relaxed);
info!("setting destroy render session");
}),
)
.run_if(state_matches!(XrState::Exiting { .. }))
.run_if(on_event::<XrDestroySessionEvent>()),
begin_xr_session
@@ -143,7 +153,7 @@ impl Plugin for OxrInitPlugin {
.init_non_send_resource::<OxrSessionCreateNextChain>();
app.world_mut()
.spawn((TransformBundle::default(), XrTrackingRoot));
.spawn((SpatialBundle::default(), XrTrackingRoot));
app.world_mut()
.resource_mut::<Events<XrStateChanged>>()
@@ -167,8 +177,17 @@ impl Plugin for OxrInitPlugin {
}
fn finish(&self, app: &mut App) {
app.sub_app_mut(RenderApp)
.add_systems(XrPreDestroySession, destroy_xr_session);
app.sub_app_mut(RenderApp).add_systems(
Render,
(destroy_xr_session, |v: Res<XrDestroySessionRender>| {
v.0.store(false, Ordering::Relaxed)
})
.run_if(
resource_exists::<XrDestroySessionRender>
.and_then(|v: Res<XrDestroySessionRender>| v.0.load(Ordering::Relaxed)),
)
.chain(),
);
}
}
@@ -488,6 +507,10 @@ pub fn create_xr_session(world: &mut World) {
swapchain,
images,
graphics_info,
session_destroy_flag: world
.get_resource::<XrDestroySessionRender>()
.expect("added by xr session plugin")
.clone(),
});
}
Err(e) => error!("Failed to initialize XrSession: {e}"),
@@ -499,7 +522,6 @@ pub fn create_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::<OxrFrameWaiter>();
world.remove_resource::<OxrFrameStream>();
@@ -550,6 +572,7 @@ struct OxrRenderResources {
swapchain: OxrSwapchain,
images: OxrSwapchainImages,
graphics_info: OxrGraphicsInfo,
session_destroy_flag: XrDestroySessionRender,
}
/// This system transfers important render resources from the main world to the render world when a session is created.
@@ -560,6 +583,7 @@ pub fn transfer_xr_resources(mut commands: Commands, mut world: ResMut<MainWorld
swapchain,
images,
graphics_info,
session_destroy_flag,
}) = world.remove_resource()
else {
return;
@@ -570,4 +594,5 @@ pub fn transfer_xr_resources(mut commands: Commands, mut world: ResMut<MainWorld
commands.insert_resource(swapchain);
commands.insert_resource(images);
commands.insert_resource(graphics_info);
commands.insert_resource(session_destroy_flag);
}

View File

@@ -1,3 +1,6 @@
use std::sync::atomic::AtomicBool;
use std::sync::Arc;
use bevy::app::{AppExit, MainScheduleOrder};
use bevy::ecs::schedule::ScheduleLabel;
use bevy::prelude::*;
@@ -22,8 +25,8 @@ pub struct XrSessionCreatedEvent;
pub struct XrDestroySessionEvent;
/// Resource flag thats inserted into the world and extracted to the render world to inform any session resources in the render world to drop.
#[derive(Resource, ExtractResource, Clone, Copy, Default)]
pub struct XrDestroySessionRender;
#[derive(Resource, Clone, Default)]
pub struct XrDestroySessionRender(pub Arc<AtomicBool>);
/// Schedule thats ran whenever the XrSession is about to be destroyed
#[derive(Clone, Copy, Default, PartialEq, Eq, Debug, Hash, ScheduleLabel)]
@@ -89,6 +92,7 @@ pub struct XrSessionPlugin {
impl Plugin for XrSessionPlugin {
fn build(&self, app: &mut App) {
app.init_resource::<XrDestroySessionRender>();
let mut xr_first = Schedule::new(XrFirst);
xr_first.set_executor_kind(bevy::ecs::schedule::ExecutorKind::Simple);
app.add_event::<XrCreateSessionEvent>()
@@ -120,10 +124,6 @@ impl Plugin for XrSessionPlugin {
.run_if(on_event::<AppExit>())
.run_if(session_created)
.in_set(XrHandleEvents::ExitEvents),
)
.add_systems(
XrFirst,
reset_per_frame_resources.in_set(XrHandleEvents::Cleanup),
);
app.world_mut()
.resource_mut::<MainScheduleOrder>()
@@ -142,7 +142,6 @@ impl Plugin for XrSessionPlugin {
app.add_plugins((
ExtractResourcePlugin::<XrState>::default(),
ExtractResourcePlugin::<XrDestroySessionRender>::default(),
ExtractResourcePlugin::<XrRootTransform>::default(),
))
.init_resource::<XrRootTransform>()
@@ -181,15 +180,6 @@ impl Plugin for XrSessionPlugin {
XrRenderSet::PostRender
.after(RenderSet::Render)
.before(RenderSet::Cleanup),
)
.add_systems(
Render,
(
// run_xr_destroy_session
// .run_if(resource_exists::<XrDestroySessionRender>)
// .in_set(XrRenderSet::HandleEvents),
reset_per_frame_resources.in_set(RenderSet::Cleanup),
),
);
}
}
@@ -225,21 +215,20 @@ pub enum XrState {
},
}
pub fn reset_per_frame_resources(world: &mut World) {
world.remove_resource::<XrDestroySessionRender>();
}
pub fn auto_handle_session(
mut state_changed: EventReader<XrStateChanged>,
mut create_session: EventWriter<XrCreateSessionEvent>,
mut begin_session: EventWriter<XrBeginSessionEvent>,
mut end_session: EventWriter<XrEndSessionEvent>,
mut destroy_session: EventWriter<XrDestroySessionEvent>,
mut no_auto_restart: Local<bool>,
) {
for XrStateChanged(state) in state_changed.read() {
match state {
XrState::Available => {
create_session.send_default();
if !*no_auto_restart {
create_session.send_default();
}
}
XrState::Ready => {
begin_session.send_default();
@@ -247,7 +236,8 @@ pub fn auto_handle_session(
XrState::Stopping => {
end_session.send_default();
}
XrState::Exiting { .. } => {
XrState::Exiting { should_restart } => {
*no_auto_restart = !should_restart;
destroy_session.send_default();
}
_ => (),