Merge pull request #184 from Schmarni-Dev/xr_space_sync_set

XrSpaceSyncSet and OxrSessionConfig
This commit is contained in:
Schmarni
2025-05-02 17:00:31 +02:00
committed by GitHub
13 changed files with 117 additions and 118 deletions

View File

@@ -1,27 +1,28 @@
//! A simple 3D scene with light shining over a cube sitting on a plane. //! A simple 3D scene with light shining over a cube sitting on a plane.
use bevy::{prelude::*, render::pipelined_rendering::PipelinedRenderingPlugin}; use bevy::{prelude::*, render::pipelined_rendering::PipelinedRenderingPlugin};
use bevy_mod_openxr::{add_xr_plugins, init::OxrInitPlugin}; use bevy_mod_openxr::{add_xr_plugins, resources::OxrSessionConfig};
use openxr::EnvironmentBlendMode; use openxr::EnvironmentBlendMode;
fn main() { fn main() -> AppExit {
App::new() App::new()
.add_plugins( .add_plugins(add_xr_plugins(
add_xr_plugins(DefaultPlugins.build().disable::<PipelinedRenderingPlugin>()).set( // Disabling Pipelined Rendering should reduce latency a little bit for button inputs
OxrInitPlugin { // and increase accuracy for hand tracking, controller positions and similar,
blend_modes: Some(vec![ // the views are updated right before rendering so they are as accurate as possible
EnvironmentBlendMode::ALPHA_BLEND, DefaultPlugins.build().disable::<PipelinedRenderingPlugin>(),
EnvironmentBlendMode::ADDITIVE, ))
EnvironmentBlendMode::OPAQUE, .insert_resource(OxrSessionConfig {
]), blend_modes: Some(vec![
..Default::default() EnvironmentBlendMode::ALPHA_BLEND,
}, EnvironmentBlendMode::OPAQUE,
), ]),
) ..default()
})
.add_plugins(bevy_xr_utils::hand_gizmos::HandGizmosPlugin) .add_plugins(bevy_xr_utils::hand_gizmos::HandGizmosPlugin)
.add_systems(Startup, setup) .add_systems(Startup, setup)
.insert_resource(ClearColor(Color::NONE)) .insert_resource(ClearColor(Color::NONE))
.run(); .run()
} }
/// set up a simple 3D scene /// set up a simple 3D scene

View File

@@ -3,7 +3,7 @@
use bevy::prelude::*; use bevy::prelude::*;
use bevy_mod_openxr::{ use bevy_mod_openxr::{
add_xr_plugins, features::overlay::OxrOverlaySessionEvent, init::OxrInitPlugin, add_xr_plugins, features::overlay::OxrOverlaySessionEvent, init::OxrInitPlugin,
types::OxrExtensions, resources::OxrSessionConfig, types::OxrExtensions,
}; };
use openxr::EnvironmentBlendMode; use openxr::EnvironmentBlendMode;
@@ -16,14 +16,17 @@ fn main() {
exts.extx_overlay = true; exts.extx_overlay = true;
exts exts
}, },
..OxrInitPlugin::default()
}))
.insert_resource(OxrSessionConfig {
blend_modes: Some({ blend_modes: Some({
vec![ vec![
EnvironmentBlendMode::ALPHA_BLEND, EnvironmentBlendMode::ALPHA_BLEND,
EnvironmentBlendMode::OPAQUE, EnvironmentBlendMode::OPAQUE,
] ]
}), }),
..OxrInitPlugin::default() ..OxrSessionConfig::default()
})) })
.insert_resource(ClearColor(Color::NONE)) .insert_resource(ClearColor(Color::NONE))
.add_plugins(bevy_xr_utils::hand_gizmos::HandGizmosPlugin) .add_plugins(bevy_xr_utils::hand_gizmos::HandGizmosPlugin)
.add_systems(Startup, setup) .add_systems(Startup, setup)

View File

@@ -1,24 +1,17 @@
//! A simple 3D scene with light shining over a cube sitting on a plane. //! A simple 3D scene with light shining over a cube sitting on a plane.
use bevy::prelude::*; use bevy::prelude::*;
use bevy_mod_openxr::{add_xr_plugins, init::OxrInitPlugin}; use bevy_mod_openxr::add_xr_plugins;
use bevy_mod_xr::session::{XrSessionPlugin, XrState}; use bevy_mod_xr::session::{XrSessionPlugin, XrState};
fn main() { fn main() -> AppExit {
App::new() App::new()
.add_plugins( .add_plugins(add_xr_plugins(DefaultPlugins).set(XrSessionPlugin { auto_handle: true }))
add_xr_plugins(DefaultPlugins)
.set(XrSessionPlugin { auto_handle: true })
.set(OxrInitPlugin {
blend_modes: Some(vec![openxr::EnvironmentBlendMode::OPAQUE]),
..Default::default()
}),
)
.add_plugins(bevy_xr_utils::hand_gizmos::HandGizmosPlugin) .add_plugins(bevy_xr_utils::hand_gizmos::HandGizmosPlugin)
.add_systems(Startup, setup) .add_systems(Startup, setup)
.add_systems(Update, handle_input) .add_systems(Update, handle_input)
.insert_resource(AmbientLight::default()) .insert_resource(AmbientLight::default())
.run(); .run()
} }
fn handle_input( fn handle_input(

View File

@@ -6,8 +6,8 @@ use bevy_mod_xr::hands::{
use bevy_mod_xr::hands::{LeftHand, RightHand, XrHandBoneEntities}; use bevy_mod_xr::hands::{LeftHand, RightHand, XrHandBoneEntities};
use bevy_mod_xr::session::{XrPreDestroySession, XrSessionCreated}; use bevy_mod_xr::session::{XrPreDestroySession, XrSessionCreated};
use bevy_mod_xr::spaces::{ use bevy_mod_xr::spaces::{
XrPrimaryReferenceSpace, XrReferenceSpace, XrSpaceLocationFlags, XrSpaceVelocityFlags, XrPrimaryReferenceSpace, XrReferenceSpace, XrSpaceLocationFlags, XrSpaceSyncSet,
XrVelocity, XrSpaceVelocityFlags, XrVelocity,
}; };
use openxr::{SpaceLocationFlags, SpaceVelocityFlags}; use openxr::{SpaceLocationFlags, SpaceVelocityFlags};
@@ -31,7 +31,12 @@ impl Default for HandTrackingPlugin {
impl Plugin for HandTrackingPlugin { impl Plugin for HandTrackingPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.add_systems(PreUpdate, locate_hands.run_if(openxr_session_running)); app.add_systems(
PreUpdate,
locate_hands
.in_set(XrSpaceSyncSet)
.run_if(openxr_session_running),
);
if self.default_hands { if self.default_hands {
app.add_systems(XrPreDestroySession, clean_up_default_hands) app.add_systems(XrPreDestroySession, clean_up_default_hands)
.add_systems(XrSessionCreated, spawn_default_hands); .add_systems(XrSessionCreated, spawn_default_hands);

View File

@@ -5,6 +5,7 @@ use bevy::render::RenderSet;
use openxr::sys::SystemPassthroughProperties2FB; use openxr::sys::SystemPassthroughProperties2FB;
use openxr::PassthroughCapabilityFlagsFB; use openxr::PassthroughCapabilityFlagsFB;
use crate::exts::OxrEnabledExtensions;
use crate::layer_builder::PassthroughLayer; use crate::layer_builder::PassthroughLayer;
use crate::resources::*; use crate::resources::*;
use crate::session::OxrSession; use crate::session::OxrSession;
@@ -14,25 +15,31 @@ pub struct OxrPassthroughPlugin;
impl Plugin for OxrPassthroughPlugin { impl Plugin for OxrPassthroughPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
let resources = app if app
.world() .world()
.get_resource::<OxrInstance>() .get_resource::<OxrEnabledExtensions>()
.and_then(|instance| { .is_some_and(|e| e.fb_passthrough)
app.world() {
.get_resource::<OxrSystemId>() let resources = app
.map(|system_id| (instance, system_id)) .world()
}); .get_resource::<OxrInstance>()
if resources.is_some_and(|(instance, system)| { .and_then(|instance| {
supports_passthrough(instance, *system).is_ok_and(|s| s) app.world()
}) { .get_resource::<OxrSystemId>()
app.sub_app_mut(RenderApp).add_systems( .map(|system_id| (instance, system_id))
Render, });
insert_passthrough if resources.is_some_and(|(instance, system)| {
.in_set(RenderSet::PrepareAssets) supports_passthrough(instance, *system).is_ok_and(|s| s)
.run_if(resource_added::<OxrSession>), }) {
); app.sub_app_mut(RenderApp).add_systems(
} else { Render,
error!("Passthrough is not supported with this runtime") insert_passthrough
.in_set(RenderSet::PrepareAssets)
.run_if(resource_added::<OxrSession>),
);
} else {
error!("Passthrough is not supported with this runtime")
}
} }
} }
} }
@@ -82,10 +89,7 @@ pub fn create_passthrough(
} }
#[inline] #[inline]
pub fn supports_passthrough( pub fn supports_passthrough(instance: &OxrInstance, system: OxrSystemId) -> OxrResult<bool> {
instance: &OxrInstance,
system: OxrSystemId,
) -> OxrResult<bool> {
if instance.exts().fb_passthrough.is_none() { if instance.exts().fb_passthrough.is_none() {
return Ok(false); return Ok(false);
} }

View File

@@ -54,14 +54,8 @@ pub struct OxrInitPlugin {
/// Extensions wanted for this session. /// Extensions wanted for this session.
// TODO!() This should be changed to take a simpler list of features wanted that this crate supports. i.e. hand tracking // TODO!() This should be changed to take a simpler list of features wanted that this crate supports. i.e. hand tracking
pub exts: OxrExtensions, pub exts: OxrExtensions,
/// List of blend modes the openxr session can use. If [None], pick the first available blend mode.
pub blend_modes: Option<Vec<EnvironmentBlendMode>>,
/// List of backends the openxr session can use. If [None], pick the first available backend. /// List of backends the openxr session can use. If [None], pick the first available backend.
pub backends: Option<Vec<GraphicsBackend>>, pub backends: Option<Vec<GraphicsBackend>>,
/// List of formats the openxr session can use. If [None], pick the first available format
pub formats: Option<Vec<wgpu::TextureFormat>>,
/// List of resolutions that the openxr swapchain can use. If [None] pick the first available resolution.
pub resolutions: Option<Vec<UVec2>>,
/// Passed into the render plugin when added to the app. /// Passed into the render plugin when added to the app.
pub synchronous_pipeline_compilation: bool, pub synchronous_pipeline_compilation: bool,
pub render_debug_flags: RenderDebugFlags, pub render_debug_flags: RenderDebugFlags,
@@ -76,10 +70,7 @@ impl Default for OxrInitPlugin {
exts.enable_hand_tracking(); exts.enable_hand_tracking();
exts exts
}, },
blend_modes: Some(vec![openxr::EnvironmentBlendMode::OPAQUE]),
backends: default(), backends: default(),
formats: Some(vec![wgpu::TextureFormat::Rgba8UnormSrgb]),
resolutions: default(),
synchronous_pipeline_compilation: false, synchronous_pipeline_compilation: false,
render_debug_flags: default(), render_debug_flags: default(),
} }
@@ -89,13 +80,14 @@ impl Default for OxrInitPlugin {
impl Plugin for OxrInitPlugin { impl Plugin for OxrInitPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.add_event::<OxrInteractionProfileChanged>(); app.add_event::<OxrInteractionProfileChanged>();
app.init_resource::<OxrSessionConfig>();
match self.init_xr() { match self.init_xr() {
Ok(( Ok((
instance, instance,
system_id, system_id,
WgpuGraphics(device, queue, adapter_info, adapter, wgpu_instance), WgpuGraphics(device, queue, adapter_info, adapter, wgpu_instance),
session_create_info,
enabled_exts, enabled_exts,
graphics_info,
)) => { )) => {
app.insert_resource(enabled_exts) app.insert_resource(enabled_exts)
.add_plugins(( .add_plugins((
@@ -150,7 +142,7 @@ impl Plugin for OxrInitPlugin {
unfocused_mode: UpdateMode::Continuous, unfocused_mode: UpdateMode::Continuous,
}) })
.insert_resource(OxrSessionStarted(false)) .insert_resource(OxrSessionStarted(false))
.insert_non_send_resource(session_create_info) .insert_non_send_resource(graphics_info)
.init_non_send_resource::<OxrSessionCreateNextChain>(); .init_non_send_resource::<OxrSessionCreateNextChain>();
app.world_mut() app.world_mut()
@@ -215,8 +207,8 @@ impl OxrInitPlugin {
OxrInstance, OxrInstance,
OxrSystemId, OxrSystemId,
WgpuGraphics, WgpuGraphics,
SessionConfigInfo,
OxrEnabledExtensions, OxrEnabledExtensions,
SessionGraphicsCreateInfo,
)> { )> {
#[cfg(windows)] #[cfg(windows)]
let entry = OxrEntry(openxr::Entry::linked()); let entry = OxrEntry(openxr::Entry::linked());
@@ -282,19 +274,12 @@ impl OxrInitPlugin {
let (graphics, graphics_info) = instance.init_graphics(system_id)?; let (graphics, graphics_info) = instance.init_graphics(system_id)?;
let session_create_info = SessionConfigInfo {
blend_modes: self.blend_modes.clone(),
formats: self.formats.clone(),
resolutions: self.resolutions.clone(),
graphics_info,
};
Ok(( Ok((
instance, instance,
OxrSystemId(system_id), OxrSystemId(system_id),
graphics, graphics,
session_create_info,
OxrEnabledExtensions(exts), OxrEnabledExtensions(exts),
graphics_info,
)) ))
} }
} }
@@ -349,19 +334,19 @@ fn init_xr_session(
instance: &OxrInstance, instance: &OxrInstance,
system_id: openxr::SystemId, system_id: openxr::SystemId,
chain: &mut OxrSessionCreateNextChain, chain: &mut OxrSessionCreateNextChain,
SessionConfigInfo { OxrSessionConfig {
blend_modes, blend_modes,
formats, formats,
resolutions, resolutions,
graphics_info, }: OxrSessionConfig,
}: SessionConfigInfo, graphics_info: SessionGraphicsCreateInfo,
) -> OxrResult<( ) -> OxrResult<(
OxrSession, OxrSession,
OxrFrameWaiter, OxrFrameWaiter,
OxrFrameStream, OxrFrameStream,
OxrSwapchain, OxrSwapchain,
OxrSwapchainImages, OxrSwapchainImages,
OxrGraphicsInfo, OxrCurrentSessionConfig,
)> { )> {
let (session, frame_waiter, frame_stream) = let (session, frame_waiter, frame_stream) =
unsafe { instance.create_session(system_id, graphics_info, chain)? }; unsafe { instance.create_session(system_id, graphics_info, chain)? };
@@ -463,7 +448,7 @@ fn init_xr_session(
} }
.ok_or(OxrError::NoAvailableBlendMode)?; .ok_or(OxrError::NoAvailableBlendMode)?;
let graphics_info = OxrGraphicsInfo { let graphics_info = OxrCurrentSessionConfig {
blend_mode, blend_mode,
resolution, resolution,
format, format,
@@ -485,14 +470,16 @@ pub fn create_xr_session(world: &mut World) {
.unwrap(); .unwrap();
let device = world.resource::<RenderDevice>(); let device = world.resource::<RenderDevice>();
let instance = world.resource::<OxrInstance>(); let instance = world.resource::<OxrInstance>();
let create_info = world.non_send_resource::<SessionConfigInfo>(); let session_config = world.resource::<OxrSessionConfig>();
let session_create_info = world.non_send_resource::<SessionGraphicsCreateInfo>();
let system_id = world.resource::<OxrSystemId>(); let system_id = world.resource::<OxrSystemId>();
match init_xr_session( match init_xr_session(
device.wgpu_device(), device.wgpu_device(),
instance, instance,
**system_id, **system_id,
&mut chain, &mut chain,
create_info.clone(), session_config.clone(),
session_create_info.clone(),
) { ) {
Ok((session, frame_waiter, frame_stream, swapchain, images, graphics_info)) => { Ok((session, frame_waiter, frame_stream, swapchain, images, graphics_info)) => {
world.insert_resource(session.clone()); world.insert_resource(session.clone());
@@ -525,7 +512,7 @@ pub fn destroy_xr_session(world: &mut World) {
world.remove_resource::<OxrFrameStream>(); world.remove_resource::<OxrFrameStream>();
world.remove_resource::<OxrSwapchain>(); world.remove_resource::<OxrSwapchain>();
world.remove_resource::<OxrSwapchainImages>(); world.remove_resource::<OxrSwapchainImages>();
world.remove_resource::<OxrGraphicsInfo>(); world.remove_resource::<OxrCurrentSessionConfig>();
world.insert_resource(XrState::Available); world.insert_resource(XrState::Available);
} }
@@ -570,7 +557,7 @@ struct OxrRenderResources {
frame_stream: OxrFrameStream, frame_stream: OxrFrameStream,
swapchain: OxrSwapchain, swapchain: OxrSwapchain,
images: OxrSwapchainImages, images: OxrSwapchainImages,
graphics_info: OxrGraphicsInfo, graphics_info: OxrCurrentSessionConfig,
session_destroy_flag: XrDestroySessionRender, session_destroy_flag: XrDestroySessionRender,
} }

View File

@@ -21,7 +21,7 @@ impl LayerProvider for ProjectionLayer {
let stage = world.get_resource::<XrPrimaryReferenceSpace>()?; let stage = world.get_resource::<XrPrimaryReferenceSpace>()?;
let openxr_views = world.get_resource::<OxrViews>()?; let openxr_views = world.get_resource::<OxrViews>()?;
let swapchain = world.get_resource::<OxrSwapchain>()?; let swapchain = world.get_resource::<OxrSwapchain>()?;
let graphics_info = world.get_resource::<OxrGraphicsInfo>()?; let graphics_info = world.get_resource::<OxrCurrentSessionConfig>()?;
let rect = openxr::Rect2Di { let rect = openxr::Rect2Di {
offset: openxr::Offset2Di { x: 0, y: 0 }, offset: openxr::Offset2Di { x: 0, y: 0 },
extent: openxr::Extent2Di { extent: openxr::Extent2Di {

View File

@@ -48,7 +48,7 @@ impl Plugin for OxrRenderPlugin {
app.add_plugins(( app.add_plugins((
ExtractResourcePlugin::<OxrFrameState>::default(), ExtractResourcePlugin::<OxrFrameState>::default(),
ExtractResourcePlugin::<OxrGraphicsInfo>::default(), ExtractResourcePlugin::<OxrCurrentSessionConfig>::default(),
ExtractResourcePlugin::<OxrSwapchainImages>::default(), ExtractResourcePlugin::<OxrSwapchainImages>::default(),
ExtractResourcePlugin::<OxrViews>::default(), ExtractResourcePlugin::<OxrViews>::default(),
)) ))
@@ -151,7 +151,7 @@ pub fn clean_views(
} }
pub fn init_views<const SPAWN_CAMERAS: bool>( pub fn init_views<const SPAWN_CAMERAS: bool>(
graphics_info: Res<OxrGraphicsInfo>, graphics_info: Res<OxrCurrentSessionConfig>,
mut manual_texture_views: ResMut<ManualTextureViews>, mut manual_texture_views: ResMut<ManualTextureViews>,
swapchain_images: Res<OxrSwapchainImages>, swapchain_images: Res<OxrSwapchainImages>,
mut commands: Commands, mut commands: Commands,
@@ -304,7 +304,7 @@ pub fn insert_texture_views(
swapchain_images: Res<OxrSwapchainImages>, swapchain_images: Res<OxrSwapchainImages>,
mut swapchain: ResMut<OxrSwapchain>, mut swapchain: ResMut<OxrSwapchain>,
mut manual_texture_views: ResMut<ManualTextureViews>, mut manual_texture_views: ResMut<ManualTextureViews>,
graphics_info: Res<OxrGraphicsInfo>, graphics_info: Res<OxrCurrentSessionConfig>,
) { ) {
let index = swapchain.acquire_image().expect("Failed to acquire image"); let index = swapchain.acquire_image().expect("Failed to acquire image");
let image = &swapchain_images[index as usize]; let image = &swapchain_images[index as usize];
@@ -324,7 +324,7 @@ pub fn wait_image(mut swapchain: ResMut<OxrSwapchain>) {
pub fn add_texture_view( pub fn add_texture_view(
manual_texture_views: &mut ManualTextureViews, manual_texture_views: &mut ManualTextureViews,
texture: &wgpu::Texture, texture: &wgpu::Texture,
info: &OxrGraphicsInfo, info: &OxrCurrentSessionConfig,
index: u32, index: u32,
) -> ManualTextureViewHandle { ) -> ManualTextureViewHandle {
let view = texture.create_view(&wgpu::TextureViewDescriptor { let view = texture.create_view(&wgpu::TextureViewDescriptor {
@@ -381,7 +381,7 @@ pub fn end_frame(world: &mut World) {
let _span = debug_span!("xr_end_frame").entered(); let _span = debug_span!("xr_end_frame").entered();
if let Err(e) = frame_stream.end( if let Err(e) = frame_stream.end(
frame_state.predicted_display_time, frame_state.predicted_display_time,
world.resource::<OxrGraphicsInfo>().blend_mode, world.resource::<OxrCurrentSessionConfig>().blend_mode,
&layers, &layers,
) { ) {
error!("Failed to end frame stream: {e}"); error!("Failed to end frame stream: {e}");

View File

@@ -106,13 +106,13 @@ impl OxrInstance {
pub fn init_graphics( pub fn init_graphics(
&self, &self,
system_id: openxr::SystemId, system_id: openxr::SystemId,
) -> OxrResult<(WgpuGraphics, SessionCreateInfo)> { ) -> OxrResult<(WgpuGraphics, SessionGraphicsCreateInfo)> {
graphics_match!( graphics_match!(
self.1; self.1;
_ => { _ => {
let (graphics, session_info) = Api::init_graphics(&self.2, self, system_id)?; let (graphics, session_info) = Api::init_graphics(&self.2, self, system_id)?;
Ok((graphics, SessionCreateInfo(Api::wrap(session_info)))) Ok((graphics, SessionGraphicsCreateInfo(Api::wrap(session_info))))
} }
) )
} }
@@ -127,12 +127,12 @@ impl OxrInstance {
pub unsafe fn create_session( pub unsafe fn create_session(
&self, &self,
system_id: openxr::SystemId, system_id: openxr::SystemId,
info: SessionCreateInfo, info: SessionGraphicsCreateInfo,
chain: &mut OxrSessionCreateNextChain, chain: &mut OxrSessionCreateNextChain,
) -> OxrResult<(OxrSession, OxrFrameWaiter, OxrFrameStream)> { ) -> OxrResult<(OxrSession, OxrFrameWaiter, OxrFrameStream)> {
if !info.0.using_graphics_of_val(&self.1) { if !info.0.using_graphics_of_val(&self.1) {
return OxrResult::Err(OxrError::GraphicsBackendMismatch { return OxrResult::Err(OxrError::GraphicsBackendMismatch {
item: std::any::type_name::<SessionCreateInfo>(), item: std::any::type_name::<SessionGraphicsCreateInfo>(),
backend: info.0.graphics_name(), backend: info.0.graphics_name(),
expected_backend: self.1.graphics_name(), expected_backend: self.1.graphics_name(),
}); });
@@ -330,23 +330,39 @@ pub struct OxrRenderLayers(pub Vec<Box<dyn LayerProvider + Send + Sync>>);
/// Resource storing graphics info for the currently running session. /// Resource storing graphics info for the currently running session.
#[derive(Clone, Copy, Resource, ExtractResource)] #[derive(Clone, Copy, Resource, ExtractResource)]
pub struct OxrGraphicsInfo { pub struct OxrCurrentSessionConfig {
pub blend_mode: EnvironmentBlendMode, pub blend_mode: EnvironmentBlendMode,
pub resolution: UVec2, pub resolution: UVec2,
pub format: wgpu::TextureFormat, pub format: wgpu::TextureFormat,
} }
#[derive(Clone)] #[derive(Clone, Resource, Debug)]
/// This is used to store information from startup that is needed to create the session after the instance has been created. /// This is used to store information from startup that is needed to create the session after the instance has been created.
pub struct SessionConfigInfo { pub struct OxrSessionConfig {
/// List of blend modes the openxr session can use. If [None], pick the first available blend mode. /// List of blend modes the openxr session can use. If [None], pick the first available blend mode.
pub blend_modes: Option<Vec<EnvironmentBlendMode>>, pub blend_modes: Option<Vec<EnvironmentBlendMode>>,
/// List of formats the openxr session can use. If [None], pick the first available format /// List of formats the openxr session can use. If [None], pick the first available format
pub formats: Option<Vec<wgpu::TextureFormat>>, pub formats: Option<Vec<wgpu::TextureFormat>>,
/// List of resolutions that the openxr swapchain can use. If [None] pick the first available resolution. /// List of resolutions that the openxr swapchain can use. If [None] pick the first available resolution.
pub resolutions: Option<Vec<UVec2>>, pub resolutions: Option<Vec<UVec2>>,
/// Graphics info used to create a session. }
pub graphics_info: SessionCreateInfo, impl Default for OxrSessionConfig {
fn default() -> Self {
Self {
blend_modes: Some(vec![openxr::EnvironmentBlendMode::OPAQUE]),
formats: Some(vec![wgpu::TextureFormat::Rgba8UnormSrgb]),
resolutions: default(),
}
}
}
/// Info needed to create a session. Mostly contains graphics info.
/// This is an API agnostic version of [openxr::Graphics::SessionCreateInfo] used for some of this library's functions
#[derive(Clone)]
pub struct SessionGraphicsCreateInfo(pub GraphicsWrap<Self>);
impl GraphicsType for SessionGraphicsCreateInfo {
type Inner<G: GraphicsExt> = G::SessionCreateInfo;
} }
#[derive(ExtractResource, Resource, Clone, Default)] #[derive(ExtractResource, Resource, Clone, Default)]

View File

@@ -4,8 +4,7 @@ use bevy::{platform::collections::hash_set::HashSet, prelude::*};
use bevy_mod_xr::{ use bevy_mod_xr::{
session::{XrFirst, XrHandleEvents}, session::{XrFirst, XrHandleEvents},
spaces::{ spaces::{
XrDestroySpace, XrPrimaryReferenceSpace, XrReferenceSpace, XrSpace, XrSpaceLocationFlags, XrDestroySpace, XrPrimaryReferenceSpace, XrReferenceSpace, XrSpace, XrSpaceLocationFlags, XrSpaceSyncSet, XrSpaceVelocityFlags, XrVelocity
XrSpaceVelocityFlags, XrVelocity,
}, },
}; };
use openxr::{ use openxr::{
@@ -20,9 +19,6 @@ use crate::{
session::OxrSession, session::OxrSession,
}; };
#[derive(SystemSet, Hash, Debug, Clone, Copy, PartialEq, Eq)]
pub struct OxrSpaceSyncSet;
/// VERY IMPORTANT!! only disable when you know what you are doing /// VERY IMPORTANT!! only disable when you know what you are doing
pub struct OxrSpacePatchingPlugin; pub struct OxrSpacePatchingPlugin;
impl Plugin for OxrSpacePatchingPlugin { impl Plugin for OxrSpacePatchingPlugin {
@@ -47,7 +43,7 @@ impl Plugin for OxrSpatialPlugin {
.add_systems( .add_systems(
PreUpdate, PreUpdate,
update_space_transforms update_space_transforms
.in_set(OxrSpaceSyncSet) .in_set(XrSpaceSyncSet)
.run_if(openxr_session_running), .run_if(openxr_session_running),
) )
.register_required_components::<XrSpaceLocationFlags, OxrSpaceLocationFlags>() .register_required_components::<XrSpaceLocationFlags, OxrSpaceLocationFlags>()

View File

@@ -87,12 +87,3 @@ impl<G: GraphicsExt> TryFrom<SwapchainCreateInfo> for openxr::SwapchainCreateInf
}) })
} }
} }
/// Info needed to create a session. Mostly contains graphics info.
/// This is an API agnostic version of [openxr::Graphics::SessionCreateInfo] used for some of this library's functions
#[derive(Clone)]
pub struct SessionCreateInfo(pub GraphicsWrap<Self>);
impl GraphicsType for SessionCreateInfo {
type Inner<G: GraphicsExt> = G::SessionCreateInfo;
}

View File

@@ -5,6 +5,9 @@ use bevy::{
use crate::session::XrTracker; use crate::session::XrTracker;
#[derive(SystemSet, Hash, Debug, Clone, Copy, PartialEq, Eq)]
pub struct XrSpaceSyncSet;
/// Any Spaces will be invalid after the owning session exits /// Any Spaces will be invalid after the owning session exits
#[repr(transparent)] #[repr(transparent)]
#[derive(Component, Clone, Copy, Hash, PartialEq, Eq, Reflect, Debug, ExtractComponent)] #[derive(Component, Clone, Copy, Hash, PartialEq, Eq, Reflect, Debug, ExtractComponent)]

View File

@@ -7,11 +7,11 @@ use bevy_mod_openxr::{
openxr_session_available, openxr_session_running, openxr_session_available, openxr_session_running,
resources::{OxrFrameState, OxrInstance, Pipelined}, resources::{OxrFrameState, OxrInstance, Pipelined},
session::OxrSession, session::OxrSession,
spaces::{OxrSpaceLocationFlags, OxrSpaceSyncSet}, spaces::OxrSpaceLocationFlags,
}; };
use bevy_mod_xr::{ use bevy_mod_xr::{
session::{XrSessionCreated, XrTracker, XrTrackingRoot}, session::{XrSessionCreated, XrTracker, XrTrackingRoot},
spaces::{XrPrimaryReferenceSpace, XrReferenceSpace}, spaces::{XrPrimaryReferenceSpace, XrReferenceSpace, XrSpaceSyncSet},
}; };
use openxr::Posef; use openxr::Posef;
@@ -47,7 +47,7 @@ impl Plugin for TrackingUtilitiesPlugin {
app.add_systems( app.add_systems(
PreUpdate, PreUpdate,
update_head_transforms update_head_transforms
.in_set(OxrSpaceSyncSet) .in_set(XrSpaceSyncSet)
.run_if(openxr_session_running), .run_if(openxr_session_running),
); );
//external //external
@@ -73,8 +73,8 @@ impl Plugin for TrackingUtilitiesPlugin {
//create actions //create actions
app.add_systems(Startup, create_actions.run_if(openxr_session_available)); app.add_systems(Startup, create_actions.run_if(openxr_session_available));
app.add_systems(PreUpdate, update_left_grip.after(OxrSpaceSyncSet)); app.add_systems(PreUpdate, update_left_grip.after(XrSpaceSyncSet));
app.add_systems(PreUpdate, update_right_grip.after(OxrSpaceSyncSet)); app.add_systems(PreUpdate, update_right_grip.after(XrSpaceSyncSet));
} }
} }