pipelined rendering, quest handtracking fix for examples, choose exiting behaviour, and allow not starting a session at startup

This commit is contained in:
Schmarni
2024-02-22 10:02:50 +01:00
parent 889ee3cc5d
commit bc6f2639c1
4 changed files with 58 additions and 24 deletions

View File

@@ -12,6 +12,8 @@ android:
required: true required: true
- name: "com.oculus.experimental.enabled" - name: "com.oculus.experimental.enabled"
required: true required: true
uses_permission:
- name: "com.oculus.permission.HAND_TRACKING"
application: application:
label: "Bevy Openxr Android" label: "Bevy Openxr Android"
theme: "@android:style/Theme.DeviceDefault.NoActionBar.Fullscreen" theme: "@android:style/Theme.DeviceDefault.NoActionBar.Fullscreen"

View File

@@ -12,6 +12,8 @@ android:
required: true required: true
- name: "com.oculus.experimental.enabled" - name: "com.oculus.experimental.enabled"
required: true required: true
uses_permission:
- name: "com.oculus.permission.HAND_TRACKING"
application: application:
label: "Bevy Openxr Android" label: "Bevy Openxr Android"
theme: "@android:style/Theme.DeviceDefault.NoActionBar.Fullscreen" theme: "@android:style/Theme.DeviceDefault.NoActionBar.Fullscreen"

View File

@@ -29,8 +29,9 @@ use openxr as xr;
use passthrough::{PassthroughPlugin, XrPassthroughLayer, XrPassthroughState}; use passthrough::{PassthroughPlugin, XrPassthroughLayer, XrPassthroughState};
use resources::*; use resources::*;
use xr_init::{ use xr_init::{
xr_after_wait_only, xr_only, xr_render_only, CleanupRenderWorld, CleanupXrData, SetupXrData, xr_after_wait_only, xr_only, xr_render_only, CleanupRenderWorld, CleanupXrData,
XrCleanup, XrEarlyInitPlugin, XrHasWaited, XrPostCleanup, XrShouldRender, XrStatus, ExitAppOnSessionExit, SetupXrData, StartSessionOnStartup, XrCleanup, XrEarlyInitPlugin,
XrHasWaited, XrPostCleanup, XrShouldRender, XrStatus,
}; };
use xr_input::actions::XrActionsPlugin; use xr_input::actions::XrActionsPlugin;
use xr_input::hands::emulated::HandEmulationPlugin; use xr_input::hands::emulated::HandEmulationPlugin;
@@ -55,6 +56,7 @@ pub struct OpenXrPlugin {
impl Plugin for OpenXrPlugin { impl Plugin for OpenXrPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.insert_resource(XrSessionRunning::new(AtomicBool::new(false))); app.insert_resource(XrSessionRunning::new(AtomicBool::new(false)));
app.insert_resource(ExitAppOnSessionExit::default());
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
match graphics::initialize_xr_instance( match graphics::initialize_xr_instance(
SystemState::<Query<&RawHandleWrapper, With<PrimaryWindow>>>::new(&mut app.world) SystemState::<Query<&RawHandleWrapper, With<PrimaryWindow>>>::new(&mut app.world)
@@ -99,7 +101,7 @@ impl Plugin for OpenXrPlugin {
synchronous_pipeline_compilation: true, synchronous_pipeline_compilation: true,
}); });
app.insert_resource(XrStatus::Disabled); app.insert_resource(XrStatus::Disabled);
app.world.send_event(StartXrSession); // app.world.send_event(StartXrSession);
} }
Err(err) => { Err(err) => {
warn!("OpenXR Instance Failed to initialize: {}", err); warn!("OpenXR Instance Failed to initialize: {}", err);
@@ -123,7 +125,6 @@ impl Plugin for OpenXrPlugin {
( (
xr_reset_per_frame_resources, xr_reset_per_frame_resources,
xr_wait_frame.run_if(xr_only()), xr_wait_frame.run_if(xr_only()),
// xr_begin_frame.run_if(xr_only()),
locate_views.run_if(xr_only()), locate_views.run_if(xr_only()),
apply_deferred, apply_deferred,
) )
@@ -131,15 +132,6 @@ impl Plugin for OpenXrPlugin {
.after(xr_poll_events), .after(xr_poll_events),
); );
let render_app = app.sub_app_mut(RenderApp); let render_app = app.sub_app_mut(RenderApp);
// render_app.add_systems(
// Render,
// xr_begin_frame
// .run_if(xr_only())
// .run_if(xr_after_wait_only())
// // .run_if(xr_render_only())
// .after(RenderSet::ExtractCommands)
// .before(xr_pre_frame),
// );
render_app.add_systems( render_app.add_systems(
Render, Render,
xr_pre_frame xr_pre_frame
@@ -148,7 +140,6 @@ impl Plugin for OpenXrPlugin {
.run_if(xr_render_only()) .run_if(xr_render_only())
.before(render_system) .before(render_system)
.after(RenderSet::ExtractCommands), .after(RenderSet::ExtractCommands),
// .in_set(RenderSet::Prepare),
); );
render_app.add_systems( render_app.add_systems(
Render, Render,
@@ -252,7 +243,7 @@ impl PluginGroup for DefaultXrPlugins {
..default() ..default()
}, },
}) })
.disable::<PipelinedRenderingPlugin>() // .disable::<PipelinedRenderingPlugin>()
.disable::<RenderPlugin>() .disable::<RenderPlugin>()
.add_before::<RenderPlugin, _>(OpenXrPlugin { .add_before::<RenderPlugin, _>(OpenXrPlugin {
prefered_blend_mode: self.prefered_blend_mode, prefered_blend_mode: self.prefered_blend_mode,
@@ -269,6 +260,7 @@ impl PluginGroup for DefaultXrPlugins {
.add(HandEmulationPlugin) .add(HandEmulationPlugin)
.add(PassthroughPlugin) .add(PassthroughPlugin)
.add(XrResourcePlugin) .add(XrResourcePlugin)
.add(StartSessionOnStartup)
.set(WindowPlugin { .set(WindowPlugin {
#[cfg(not(target_os = "android"))] #[cfg(not(target_os = "android"))]
primary_window: Some(Window { primary_window: Some(Window {
@@ -300,7 +292,9 @@ fn xr_poll_events(
instance: Option<Res<XrInstance>>, instance: Option<Res<XrInstance>>,
session: Option<Res<XrSession>>, session: Option<Res<XrSession>>,
session_running: Res<XrSessionRunning>, session_running: Res<XrSessionRunning>,
exit_type: Res<ExitAppOnSessionExit>,
mut app_exit: EventWriter<AppExit>, mut app_exit: EventWriter<AppExit>,
mut start_session: EventWriter<StartXrSession>,
mut setup_xr: EventWriter<SetupXrData>, mut setup_xr: EventWriter<SetupXrData>,
mut cleanup_xr: EventWriter<CleanupXrData>, mut cleanup_xr: EventWriter<CleanupXrData>,
) { ) {
@@ -325,8 +319,20 @@ fn xr_poll_events(
session_running.store(false, std::sync::atomic::Ordering::Relaxed); session_running.store(false, std::sync::atomic::Ordering::Relaxed);
cleanup_xr.send_default(); cleanup_xr.send_default();
} }
xr::SessionState::EXITING | xr::SessionState::LOSS_PENDING => { xr::SessionState::EXITING => {
// app_exit.send(AppExit); if *exit_type == ExitAppOnSessionExit::Always
|| *exit_type == ExitAppOnSessionExit::OnlyOnExit
{
app_exit.send_default();
}
}
xr::SessionState::LOSS_PENDING => {
if *exit_type == ExitAppOnSessionExit::Always {
app_exit.send_default();
}
if *exit_type == ExitAppOnSessionExit::OnlyOnExit {
start_session.send_default();
}
} }
_ => {} _ => {}
@@ -344,11 +350,6 @@ fn xr_poll_events(
} }
} }
fn xr_begin_frame(swapchain: Res<XrSwapchain>) {
let _span = info_span!("xr_begin_frame").entered();
swapchain.begin().unwrap()
}
pub fn xr_wait_frame( pub fn xr_wait_frame(
world: &mut World, world: &mut World,
// mut frame_state: ResMut<XrFrameState>, // mut frame_state: ResMut<XrFrameState>,
@@ -368,11 +369,19 @@ pub fn xr_wait_frame(
} }
}; };
let should_render = world.get_resource::<XrFrameState>().unwrap().should_render; let should_render = world.get_resource::<XrFrameState>().unwrap().should_render;
// frame_state.predicted_display_time = xr::Time::from_nanos(frame_state.predicted_display_time.as_nanos() + frame_state.predicted_display_period.as_nanos()); let mut frame_state = world.resource_mut::<XrFrameState>();
frame_state.predicted_display_time = xr::Time::from_nanos(
frame_state.predicted_display_time.as_nanos()
+ frame_state.predicted_display_period.as_nanos(),
);
**world.get_resource_mut::<XrShouldRender>().unwrap() = should_render; **world.get_resource_mut::<XrShouldRender>().unwrap() = should_render;
**world.get_resource_mut::<XrHasWaited>().unwrap() = true; **world.get_resource_mut::<XrHasWaited>().unwrap() = true;
} }
world.get_resource::<XrSwapchain>().unwrap().begin().unwrap(); world
.get_resource::<XrSwapchain>()
.unwrap()
.begin()
.unwrap();
} }
pub fn xr_pre_frame( pub fn xr_pre_frame(

View File

@@ -94,6 +94,27 @@ impl Plugin for XrInitPlugin {
} }
} }
#[derive(Resource, Clone, Copy, PartialEq, Eq,Default)]
pub enum ExitAppOnSessionExit {
#[default]
/// Restart XrSession when session is lost
OnlyOnExit,
/// Always exit the app
Always,
/// Keep app open when XrSession wants to exit or is lost
Never,
}
pub struct StartSessionOnStartup;
impl Plugin for StartSessionOnStartup {
fn build(&self, app: &mut App) {
app.add_systems(Startup, |mut event: EventWriter<StartXrSession>| {
event.send_default();
});
}
}
fn set_cleanup_res(mut commands: Commands) { fn set_cleanup_res(mut commands: Commands) {
info!("Set Cleanup Res"); info!("Set Cleanup Res");
commands.insert_resource(CleanupRenderWorld); commands.insert_resource(CleanupRenderWorld);