refactor(openxr): make environment blend modes a completely runtime feature, like it should and remove the fb_passthrough plugin from the default oxr plugins as quests now support blendmode based passthrough
Signed-off-by: Schmarni <marnistromer@gmail.com>
This commit is contained in:
39
crates/bevy_openxr/src/openxr/environment_blend_mode.rs
Normal file
39
crates/bevy_openxr/src/openxr/environment_blend_mode.rs
Normal file
@@ -0,0 +1,39 @@
|
||||
use bevy::{ecs::resource::Resource, render::extract_resource::ExtractResource};
|
||||
use openxr::EnvironmentBlendMode;
|
||||
|
||||
#[derive(Resource, ExtractResource, Clone)]
|
||||
pub struct OxrEnvironmentBlendModes {
|
||||
available_blend_modes: Vec<EnvironmentBlendMode>,
|
||||
current_blend_mode: EnvironmentBlendMode,
|
||||
}
|
||||
|
||||
impl OxrEnvironmentBlendModes {
|
||||
pub(crate) fn new(
|
||||
available_modes: Vec<EnvironmentBlendMode>,
|
||||
preferences: &[EnvironmentBlendMode],
|
||||
) -> Option<OxrEnvironmentBlendModes> {
|
||||
let blend_mode = preferences.iter().find(|m| available_modes.contains(m))?;
|
||||
|
||||
Some(Self {
|
||||
available_blend_modes: available_modes,
|
||||
current_blend_mode: *blend_mode,
|
||||
})
|
||||
}
|
||||
|
||||
/// returns whether the blend_mode was changed
|
||||
pub fn set_blend_mode(&mut self, blend_mode: EnvironmentBlendMode) -> bool {
|
||||
if self.available_blend_modes.contains(&blend_mode) {
|
||||
self.current_blend_mode = blend_mode;
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
pub fn blend_mode(&self) -> EnvironmentBlendMode {
|
||||
self.current_blend_mode
|
||||
}
|
||||
|
||||
pub fn available_blend_modes(&self) -> &[EnvironmentBlendMode] {
|
||||
&self.available_blend_modes
|
||||
}
|
||||
}
|
||||
@@ -11,9 +11,9 @@ use crate::resources::*;
|
||||
use crate::session::OxrSession;
|
||||
use crate::types::Result as OxrResult;
|
||||
|
||||
pub struct OxrPassthroughPlugin;
|
||||
pub struct OxrFbPassthroughPlugin;
|
||||
|
||||
impl Plugin for OxrPassthroughPlugin {
|
||||
impl Plugin for OxrFbPassthroughPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
if app
|
||||
.world()
|
||||
@@ -94,12 +94,12 @@ pub fn supports_passthrough(instance: &OxrInstance, system: OxrSystemId) -> OxrR
|
||||
return Ok(false);
|
||||
}
|
||||
unsafe {
|
||||
let mut hand = openxr::sys::SystemPassthroughProperties2FB {
|
||||
let mut properties = openxr::sys::SystemPassthroughProperties2FB {
|
||||
ty: SystemPassthroughProperties2FB::TYPE,
|
||||
next: std::ptr::null(),
|
||||
capabilities: PassthroughCapabilityFlagsFB::PASSTHROUGH_CAPABILITY,
|
||||
};
|
||||
let mut p = openxr::sys::SystemProperties::out(&mut hand as *mut _ as _);
|
||||
let mut p = openxr::sys::SystemProperties::out(&mut properties as *mut _ as _);
|
||||
cvt((instance.fp().get_system_properties)(
|
||||
instance.as_raw(),
|
||||
system.0,
|
||||
@@ -107,10 +107,10 @@ pub fn supports_passthrough(instance: &OxrInstance, system: OxrSystemId) -> OxrR
|
||||
))?;
|
||||
bevy::log::info!(
|
||||
"From supports_passthrough: Passthrough capabilities: {:?}",
|
||||
hand.capabilities
|
||||
properties.capabilities
|
||||
);
|
||||
Ok(
|
||||
(hand.capabilities & PassthroughCapabilityFlagsFB::PASSTHROUGH_CAPABILITY)
|
||||
(properties.capabilities & PassthroughCapabilityFlagsFB::PASSTHROUGH_CAPABILITY)
|
||||
== PassthroughCapabilityFlagsFB::PASSTHROUGH_CAPABILITY,
|
||||
)
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
pub mod handtracking;
|
||||
#[cfg(feature = "passthrough")]
|
||||
pub mod passthrough;
|
||||
pub mod fb_passthrough;
|
||||
pub mod overlay;
|
||||
|
||||
@@ -28,6 +28,7 @@ use crate::session::OxrSessionCreateNextChain;
|
||||
use crate::types::Result as OxrResult;
|
||||
use crate::types::*;
|
||||
|
||||
use super::environment_blend_mode::OxrEnvironmentBlendModes;
|
||||
use super::exts::OxrEnabledExtensions;
|
||||
use super::poll_events::OxrEventHandlerExt;
|
||||
use super::poll_events::OxrEventIn;
|
||||
@@ -66,7 +67,6 @@ impl Default for OxrInitPlugin {
|
||||
app_info: default(),
|
||||
exts: {
|
||||
let mut exts = OxrExtensions::default();
|
||||
exts.enable_fb_passthrough();
|
||||
exts.enable_hand_tracking();
|
||||
exts
|
||||
},
|
||||
@@ -104,6 +104,7 @@ impl Plugin for OxrInitPlugin {
|
||||
debug_flags: self.render_debug_flags,
|
||||
},
|
||||
ExtractResourcePlugin::<OxrSessionStarted>::default(),
|
||||
ExtractResourcePlugin::<OxrEnvironmentBlendModes>::default(),
|
||||
))
|
||||
.add_oxr_event_handler(handle_events)
|
||||
.add_systems(
|
||||
@@ -249,7 +250,7 @@ impl OxrInitPlugin {
|
||||
|
||||
// check available extensions and send a warning for any wanted extensions that aren't available.
|
||||
for ext in available_exts.unavailable_exts(&self.exts) {
|
||||
error!(
|
||||
warn!(
|
||||
"Extension \"{ext}\" not available in the current OpenXR runtime. Disabling extension."
|
||||
);
|
||||
}
|
||||
@@ -273,13 +274,7 @@ impl OxrInitPlugin {
|
||||
|
||||
let exts = self.exts.clone() & available_exts;
|
||||
|
||||
let instance = entry.create_instance(
|
||||
self.app_info.clone(),
|
||||
exts.clone(),
|
||||
// &["XR_APILAYER_LUNARG_api_dump"],
|
||||
&[],
|
||||
backend,
|
||||
)?;
|
||||
let instance = entry.create_instance(self.app_info.clone(), exts.clone(), &[], backend)?;
|
||||
let instance_props = instance.properties()?;
|
||||
|
||||
info!(
|
||||
@@ -362,7 +357,7 @@ fn init_xr_session(
|
||||
system_id: openxr::SystemId,
|
||||
chain: &mut OxrSessionCreateNextChain,
|
||||
OxrSessionConfig {
|
||||
blend_modes,
|
||||
blend_mode_preference,
|
||||
formats,
|
||||
resolutions,
|
||||
}: OxrSessionConfig,
|
||||
@@ -374,6 +369,7 @@ fn init_xr_session(
|
||||
OxrSwapchain,
|
||||
OxrSwapchainImages,
|
||||
OxrCurrentSessionConfig,
|
||||
OxrEnvironmentBlendModes,
|
||||
)> {
|
||||
let (session, frame_waiter, frame_stream) =
|
||||
unsafe { instance.create_session(system_id, graphics_info, chain)? };
|
||||
@@ -461,25 +457,10 @@ fn init_xr_session(
|
||||
instance.enumerate_environment_blend_modes(system_id, view_configuration_type)?;
|
||||
|
||||
// blend mode selection
|
||||
let blend_mode = if let Some(wanted_blend_modes) = &blend_modes {
|
||||
let mut blend_mode = None;
|
||||
for wanted_blend_mode in wanted_blend_modes {
|
||||
if available_blend_modes.contains(wanted_blend_mode) {
|
||||
blend_mode = Some(*wanted_blend_mode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
blend_mode
|
||||
} else {
|
||||
available_blend_modes.first().copied()
|
||||
}
|
||||
.ok_or(OxrError::NoAvailableBlendMode)?;
|
||||
let blend_modes = OxrEnvironmentBlendModes::new(available_blend_modes, &blend_mode_preference)
|
||||
.ok_or(OxrError::NoAvailableBlendMode)?;
|
||||
|
||||
let graphics_info = OxrCurrentSessionConfig {
|
||||
blend_mode,
|
||||
resolution,
|
||||
format,
|
||||
};
|
||||
let graphics_info = OxrCurrentSessionConfig { resolution, format };
|
||||
|
||||
Ok((
|
||||
session,
|
||||
@@ -488,6 +469,7 @@ fn init_xr_session(
|
||||
swapchain,
|
||||
images,
|
||||
graphics_info,
|
||||
blend_modes,
|
||||
))
|
||||
}
|
||||
|
||||
@@ -508,7 +490,15 @@ pub fn create_xr_session(world: &mut World) {
|
||||
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,
|
||||
blend_modes,
|
||||
)) => {
|
||||
world.insert_resource(session.clone());
|
||||
world.insert_resource(frame_waiter);
|
||||
world.insert_resource(images);
|
||||
@@ -524,6 +514,7 @@ pub fn create_xr_session(world: &mut World) {
|
||||
.expect("added by xr session plugin")
|
||||
.clone(),
|
||||
});
|
||||
world.insert_resource(blend_modes);
|
||||
}
|
||||
Err(e) => error!("Failed to initialize XrSession: {e}"),
|
||||
}
|
||||
|
||||
@@ -14,14 +14,12 @@ use render::OxrRenderPlugin;
|
||||
use resources::OxrInstance;
|
||||
use session::OxrSession;
|
||||
|
||||
use self::{
|
||||
features::{handtracking::HandTrackingPlugin, passthrough::OxrPassthroughPlugin},
|
||||
reference_space::OxrReferenceSpacePlugin,
|
||||
};
|
||||
use self::{features::handtracking::HandTrackingPlugin, reference_space::OxrReferenceSpacePlugin};
|
||||
|
||||
pub mod action_binding;
|
||||
pub mod action_set_attaching;
|
||||
pub mod action_set_syncing;
|
||||
pub mod environment_blend_mode;
|
||||
pub mod error;
|
||||
pub mod exts;
|
||||
pub mod features;
|
||||
@@ -59,13 +57,11 @@ pub fn add_xr_plugins<G: PluginGroup>(plugins: G) -> PluginGroupBuilder {
|
||||
plugins
|
||||
.build()
|
||||
.disable::<RenderPlugin>()
|
||||
// .disable::<PipelinedRenderingPlugin>()
|
||||
.add_before::<RenderPlugin>(XrSessionPlugin { auto_handle: true })
|
||||
.add_before::<RenderPlugin>(OxrInitPlugin::default())
|
||||
.add(OxrEventsPlugin)
|
||||
.add(OxrReferenceSpacePlugin::default())
|
||||
.add(OxrRenderPlugin::default())
|
||||
.add(OxrPassthroughPlugin)
|
||||
.add(HandTrackingPlugin::default())
|
||||
.add(XrCameraPlugin)
|
||||
.add(action_set_attaching::OxrActionAttachingPlugin)
|
||||
@@ -74,20 +70,14 @@ pub fn add_xr_plugins<G: PluginGroup>(plugins: G) -> PluginGroupBuilder {
|
||||
.add(features::overlay::OxrOverlayPlugin)
|
||||
.add(spaces::OxrSpatialPlugin)
|
||||
.add(spaces::OxrSpacePatchingPlugin)
|
||||
// .add(XrActionPlugin)
|
||||
// we should probably handle the exiting ourselfs so that we can correctly end the
|
||||
// session and instance
|
||||
.set(WindowPlugin {
|
||||
primary_window: Some(Window {
|
||||
transparent: true,
|
||||
present_mode: PresentMode::AutoNoVsync,
|
||||
// title: self.app_info.name.clone(),
|
||||
..default()
|
||||
}),
|
||||
// #[cfg(target_os = "android")]
|
||||
// exit_condition: bevy::window::ExitCondition::DontExit,
|
||||
#[cfg(target_os = "android")]
|
||||
close_when_requested: true,
|
||||
..default()
|
||||
})
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@ use openxr::ViewStateFlags;
|
||||
use crate::{init::should_run_frame_loop, resources::*};
|
||||
use crate::{layer_builder::ProjectionLayer, session::OxrSession};
|
||||
|
||||
use super::environment_blend_mode::OxrEnvironmentBlendModes;
|
||||
|
||||
#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy, SystemSet)]
|
||||
pub struct OxrRenderBegin;
|
||||
|
||||
@@ -393,7 +395,7 @@ pub fn end_frame(world: &mut World) {
|
||||
let _span = debug_span!("xr_end_frame").entered();
|
||||
if let Err(e) = frame_stream.end(
|
||||
frame_state.predicted_display_time,
|
||||
world.resource::<OxrCurrentSessionConfig>().blend_mode,
|
||||
world.resource::<OxrEnvironmentBlendModes>().blend_mode(),
|
||||
&layers,
|
||||
) {
|
||||
error!("Failed to end frame stream: {e}");
|
||||
|
||||
@@ -332,7 +332,6 @@ pub struct OxrRenderLayers(pub Vec<Box<dyn LayerProvider + Send + Sync>>);
|
||||
/// Resource storing graphics info for the currently running session.
|
||||
#[derive(Clone, Copy, Resource, ExtractResource)]
|
||||
pub struct OxrCurrentSessionConfig {
|
||||
pub blend_mode: EnvironmentBlendMode,
|
||||
pub resolution: UVec2,
|
||||
pub format: wgpu::TextureFormat,
|
||||
}
|
||||
@@ -341,7 +340,7 @@ pub struct OxrCurrentSessionConfig {
|
||||
/// This is used to store information from startup that is needed to create the session after the instance has been created.
|
||||
pub struct OxrSessionConfig {
|
||||
/// 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_mode_preference: Vec<EnvironmentBlendMode>,
|
||||
/// 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.
|
||||
@@ -350,7 +349,7 @@ pub struct OxrSessionConfig {
|
||||
impl Default for OxrSessionConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
blend_modes: Some(vec![openxr::EnvironmentBlendMode::OPAQUE]),
|
||||
blend_mode_preference: vec![openxr::EnvironmentBlendMode::OPAQUE],
|
||||
formats: Some(vec![wgpu::TextureFormat::Rgba8UnormSrgb]),
|
||||
resolutions: default(),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user