renamed types and fixed errors

This commit is contained in:
awtterpip
2024-04-18 17:26:36 -05:00
parent f585c9e2dc
commit e2f7f840a9
13 changed files with 187 additions and 263 deletions

View File

@@ -6,90 +6,10 @@ description = "Community crate for OpenXR in Bevy"
repository = "https://github.com/awtterpip/bevy_oxr" repository = "https://github.com/awtterpip/bevy_oxr"
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"
[features]
default = ["linked", "vulkan"]
linked = ["openxr/linked"]
vulkan = ["dep:ash"]
[dependencies] [dependencies]
bevy_openxr.path = "./crates/bevy_openxr" bevy_openxr.path = "./crates/bevy_openxr"
bevy_xr.path = "./crates/bevy_xr" bevy_xr.path = "./crates/bevy_xr"
anyhow = "1.0.79"
async-std = "1.12.0"
bevy = "0.13.0" bevy = "0.13.0"
paste = "1.0.14"
thiserror = "1.0.57"
wgpu = "0.19.3"
wgpu-hal = "0.19.3"
winit = "0.28.7"
[target.'cfg(target_family = "unix")'.dependencies]
openxr = { version = "0.17.1", features = ["mint"] }
[target.'cfg(target_family = "windows")'.dependencies]
openxr = { version = "0.17.1", features = ["mint", "static"] }
[target.'cfg(not(target_family = "wasm"))'.dependencies]
ash = { version = "0.37.3", optional = true }
[target.'cfg(target_family = "wasm")'.dependencies]
js-sys = "0.3"
wasm-bindgen = "0.2.91"
glow = "0.12.1"
web-sys = { version = "0.3.67", features = [
# STANDARD
'console',
'Document',
'Element',
'Headers',
'Navigator',
'Window',
# IO
# 'Url',
# WEBGL
'Gpu',
'HtmlCanvasElement',
'WebGl2RenderingContext',
'WebGlFramebuffer',
'GamepadHapticActuator',
## XR
'DomPointReadOnly',
'XrWebGlLayer',
'XrBoundedReferenceSpace',
'XrEye',
'XrFrame',
'XrHandedness',
'XrInputSource',
'XrInputSourceArray',
'XrInputSourceEvent',
'XrInputSourceEventInit',
'XrInputSourcesChangeEvent',
'XrJointPose',
'XrJointSpace',
'XrPose',
'XrReferenceSpace',
'XrReferenceSpaceEvent',
'XrReferenceSpaceEventInit',
'XrReferenceSpaceType',
'XrRenderState',
'XrRenderStateInit',
'XrRigidTransform',
'XrSession',
'XrSessionEvent',
'XrSessionEventInit',
'XrSessionInit',
'XrSessionMode',
'XrSpace',
'XrTargetRayMode',
'XrView',
'XrViewerPose',
'XrViewport',
'XrVisibilityState',
'XrWebGlLayer',
'XrWebGlLayerInit',
'XrSystem',
] }
wasm-bindgen-futures = "0.4"
[workspace] [workspace]
members = ["crates/*"] members = ["crates/*"]

View File

@@ -7,14 +7,16 @@ edition = "2021"
default = ["vulkan"] default = ["vulkan"]
vulkan = ["dep:ash"] vulkan = ["dep:ash"]
# all dependencies are placed under this since on wasm, this crate is completely empty # bevy can't be placed behind target or proc macros won't work properly
[dependencies]
bevy.workspace = true
# all other dependencies are placed under this since on wasm, this crate is completely empty
[target.'cfg(not(target_family = "wasm"))'.dependencies] [target.'cfg(not(target_family = "wasm"))'.dependencies]
thiserror = "1.0.57" thiserror = "1.0.57"
wgpu = "0.19.3" wgpu = "0.19.3"
wgpu-hal = "0.19.3" wgpu-hal = "0.19.3"
bevy_xr.path = "../bevy_xr" bevy_xr.path = "../bevy_xr"
bevy.workspace = true
ash = { version = "0.37.3", optional = true } ash = { version = "0.37.3", optional = true }

View File

@@ -6,7 +6,7 @@ use super::graphics::GraphicsBackend;
use thiserror::Error; use thiserror::Error;
#[derive(Error, Debug)] #[derive(Error, Debug)]
pub enum OXrError { pub enum OxrError {
#[error("OpenXR error: {0}")] #[error("OpenXR error: {0}")]
OpenXrError(#[from] openxr::sys::Result), OpenXrError(#[from] openxr::sys::Result),
#[error("OpenXR loading error: {0}")] #[error("OpenXR loading error: {0}")]
@@ -52,7 +52,7 @@ pub use init_error::InitError;
/// This module is needed because thiserror does not allow conditional compilation within enums for some reason, /// This module is needed because thiserror does not allow conditional compilation within enums for some reason,
/// so graphics api specific errors are implemented here. /// so graphics api specific errors are implemented here.
mod init_error { mod init_error {
use super::OXrError; use super::OxrError;
use std::fmt; use std::fmt;
#[derive(Debug)] #[derive(Debug)]
@@ -77,21 +77,21 @@ mod init_error {
} }
#[cfg(feature = "vulkan")] #[cfg(feature = "vulkan")]
impl From<ash::vk::Result> for OXrError { impl From<ash::vk::Result> for OxrError {
fn from(value: ash::vk::Result) -> Self { fn from(value: ash::vk::Result) -> Self {
Self::InitError(InitError::VulkanError(value)) Self::InitError(InitError::VulkanError(value))
} }
} }
#[cfg(feature = "vulkan")] #[cfg(feature = "vulkan")]
impl From<ash::LoadingError> for OXrError { impl From<ash::LoadingError> for OxrError {
fn from(value: ash::LoadingError) -> Self { fn from(value: ash::LoadingError) -> Self {
Self::InitError(InitError::VulkanLoadingError(value)) Self::InitError(InitError::VulkanLoadingError(value))
} }
} }
} }
impl From<Vec<Cow<'static, str>>> for OXrError { impl From<Vec<Cow<'static, str>>> for OxrError {
fn from(value: Vec<Cow<'static, str>>) -> Self { fn from(value: Vec<Cow<'static, str>>) -> Self {
Self::UnavailableExtensions(UnavailableExts(value)) Self::UnavailableExtensions(UnavailableExts(value))
} }

View File

@@ -2,8 +2,8 @@ use bevy::prelude::{Deref, DerefMut};
use openxr::ExtensionSet; use openxr::ExtensionSet;
#[derive(Clone, Debug, Eq, PartialEq, Deref, DerefMut)] #[derive(Clone, Debug, Eq, PartialEq, Deref, DerefMut)]
pub struct OXrExtensions(ExtensionSet); pub struct OxrExtensions(ExtensionSet);
impl OXrExtensions { impl OxrExtensions {
pub fn raw_mut(&mut self) -> &mut ExtensionSet { pub fn raw_mut(&mut self) -> &mut ExtensionSet {
&mut self.0 &mut self.0
} }
@@ -27,21 +27,21 @@ impl OXrExtensions {
self self
} }
/// returns true if all of the extensions enabled are also available in `available_exts` /// returns true if all of the extensions enabled are also available in `available_exts`
pub fn is_available(&self, available_exts: &OXrExtensions) -> bool { pub fn is_available(&self, available_exts: &OxrExtensions) -> bool {
self.clone() & available_exts.clone() == *self self.clone() & available_exts.clone() == *self
} }
} }
impl From<ExtensionSet> for OXrExtensions { impl From<ExtensionSet> for OxrExtensions {
fn from(value: ExtensionSet) -> Self { fn from(value: ExtensionSet) -> Self {
Self(value) Self(value)
} }
} }
impl From<OXrExtensions> for ExtensionSet { impl From<OxrExtensions> for ExtensionSet {
fn from(val: OXrExtensions) -> Self { fn from(val: OxrExtensions) -> Self {
val.0 val.0
} }
} }
impl Default for OXrExtensions { impl Default for OxrExtensions {
fn default() -> Self { fn default() -> Self {
let exts = ExtensionSet::default(); let exts = ExtensionSet::default();
//exts.ext_hand_tracking = true; //exts.ext_hand_tracking = true;
@@ -165,7 +165,7 @@ macro_rules! impl_ext {
) => { ) => {
$( $(
$macro! { $macro! {
OXrExtensions; OxrExtensions;
almalence_digital_lens_control, almalence_digital_lens_control,
bd_controller_interaction, bd_controller_interaction,
epic_view_configuration_fov, epic_view_configuration_fov,

View File

@@ -5,14 +5,14 @@ use std::any::TypeId;
use bevy::math::UVec2; use bevy::math::UVec2;
use crate::types::{AppInfo, OXrExtensions, Result, WgpuGraphics}; use crate::types::{AppInfo, OxrExtensions, Result, WgpuGraphics};
/// This is an extension trait to the [`Graphics`](openxr::Graphics) trait and is how the graphics API should be interacted with. /// This is an extension trait to the [`Graphics`](openxr::Graphics) trait and is how the graphics API should be interacted with.
pub unsafe trait GraphicsExt: openxr::Graphics { pub unsafe trait GraphicsExt: openxr::Graphics {
/// Wrap the graphics specific type into the [GraphicsWrap] enum /// Wrap the graphics specific type into the [GraphicsWrap] enum
fn wrap<T: GraphicsType>(item: T::Inner<Self>) -> GraphicsWrap<T>; fn wrap<T: GraphicsType>(item: T::Inner<Self>) -> GraphicsWrap<T>;
/// Returns all of the required openxr extensions to use this graphics API. /// Returns all of the required openxr extensions to use this graphics API.
fn required_exts() -> OXrExtensions; fn required_exts() -> OxrExtensions;
/// Convert from wgpu format to the graphics format /// Convert from wgpu format to the graphics format
fn from_wgpu_format(format: wgpu::TextureFormat) -> Option<Self::Format>; fn from_wgpu_format(format: wgpu::TextureFormat) -> Option<Self::Format>;
/// Convert from the graphics format to wgpu format /// Convert from the graphics format to wgpu format
@@ -64,7 +64,7 @@ pub type GraphicsBackend = GraphicsWrap<()>;
impl GraphicsBackend { impl GraphicsBackend {
const ALL: &'static [Self] = &[Self::Vulkan(())]; const ALL: &'static [Self] = &[Self::Vulkan(())];
pub fn available_backends(exts: &OXrExtensions) -> Vec<Self> { pub fn available_backends(exts: &OxrExtensions) -> Vec<Self> {
Self::ALL Self::ALL
.iter() .iter()
.copied() .copied()
@@ -72,11 +72,11 @@ impl GraphicsBackend {
.collect() .collect()
} }
pub fn is_available(&self, exts: &OXrExtensions) -> bool { pub fn is_available(&self, exts: &OxrExtensions) -> bool {
self.required_exts().is_available(exts) self.required_exts().is_available(exts)
} }
pub fn required_exts(&self) -> OXrExtensions { pub fn required_exts(&self) -> OxrExtensions {
graphics_match!( graphics_match!(
self; self;
_ => Api::required_exts() _ => Api::required_exts()
@@ -125,14 +125,14 @@ impl<T: GraphicsType> GraphicsWrap<T> {
/// # Example /// # Example
/// ///
/// ``` /// ```
/// pub struct OXrFrameStream(GraphicsWrap<XrFrameStream>); /// pub struct OxrFrameStream(GraphicsWrap<XrFrameStream>);
/// ///
/// impl GraphicsType for OXrFrameStream { /// impl GraphicsType for OxrFrameStream {
/// // Here is the inner type /// // Here is the inner type
/// type Inner<G: GraphicsExt> = openxr::FrameStream<G>; /// type Inner<G: GraphicsExt> = openxr::FrameStream<G>;
/// } /// }
/// ///
/// fn begin(frame_stream: &mut XrFrameStream) { /// fn begin(frame_stream: &mut OxrFrameStream) {
/// graphics_match! { /// graphics_match! {
/// // get the inner 'GraphicsWrap' struct /// // get the inner 'GraphicsWrap' struct
/// &mut frame_stream.0; /// &mut frame_stream.0;

View File

@@ -8,8 +8,8 @@ use wgpu_hal::api::Vulkan;
use wgpu_hal::Api; use wgpu_hal::Api;
use super::{GraphicsExt, GraphicsType, GraphicsWrap}; use super::{GraphicsExt, GraphicsType, GraphicsWrap};
use crate::error::OXrError; use crate::error::OxrError;
use crate::types::{AppInfo, OXrExtensions, Result, WgpuGraphics}; use crate::types::{AppInfo, OxrExtensions, Result, WgpuGraphics};
#[cfg(not(target_os = "android"))] #[cfg(not(target_os = "android"))]
const VK_TARGET_VERSION: Version = Version::new(1, 2, 0); const VK_TARGET_VERSION: Version = Version::new(1, 2, 0);
@@ -28,7 +28,7 @@ unsafe impl GraphicsExt for openxr::Vulkan {
GraphicsWrap::Vulkan(item) GraphicsWrap::Vulkan(item)
} }
fn required_exts() -> OXrExtensions { fn required_exts() -> OxrExtensions {
let mut extensions = openxr::ExtensionSet::default(); let mut extensions = openxr::ExtensionSet::default();
extensions.khr_vulkan_enable2 = true; extensions.khr_vulkan_enable2 = true;
extensions.into() extensions.into()
@@ -106,7 +106,7 @@ unsafe impl GraphicsExt for openxr::Vulkan {
reqs.min_api_version_supported, reqs.min_api_version_supported,
reqs.max_api_version_supported.major() + 1 reqs.max_api_version_supported.major() + 1
); );
return Err(OXrError::FailedGraphicsRequirements); return Err(OxrError::FailedGraphicsRequirements);
}; };
let vk_entry = unsafe { ash::Entry::load() }?; let vk_entry = unsafe { ash::Entry::load() }?;
let flags = wgpu::InstanceFlags::empty(); let flags = wgpu::InstanceFlags::empty();
@@ -165,7 +165,7 @@ unsafe impl GraphicsExt for openxr::Vulkan {
VK_TARGET_VERSION.minor(), VK_TARGET_VERSION.minor(),
VK_TARGET_VERSION.patch() VK_TARGET_VERSION.patch()
); );
return Err(OXrError::FailedGraphicsRequirements); return Err(OxrError::FailedGraphicsRequirements);
} }
let wgpu_vk_instance = unsafe { let wgpu_vk_instance = unsafe {
@@ -189,7 +189,7 @@ unsafe impl GraphicsExt for openxr::Vulkan {
let Some(wgpu_exposed_adapter) = wgpu_vk_instance.expose_adapter(vk_physical_device) else { let Some(wgpu_exposed_adapter) = wgpu_vk_instance.expose_adapter(vk_physical_device) else {
error!("WGPU failed to provide an adapter"); error!("WGPU failed to provide an adapter");
return Err(OXrError::FailedGraphicsRequirements); return Err(OxrError::FailedGraphicsRequirements);
}; };
let enabled_extensions = wgpu_exposed_adapter let enabled_extensions = wgpu_exposed_adapter

View File

@@ -25,27 +25,27 @@ use bevy_xr::session::EndXrSession;
use bevy_xr::session::XrSharedStatus; use bevy_xr::session::XrSharedStatus;
use bevy_xr::session::XrStatus; use bevy_xr::session::XrStatus;
use crate::error::OXrError; use crate::error::OxrError;
use crate::graphics::*; use crate::graphics::*;
use crate::resources::*; use crate::resources::*;
use crate::types::*; use crate::types::*;
pub fn session_started(started: Option<Res<OXrSessionStarted>>) -> bool { pub fn session_started(started: Option<Res<OxrSessionStarted>>) -> bool {
started.is_some_and(|started| started.get()) started.is_some_and(|started| started.get())
} }
#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy, SystemSet)] #[derive(Debug, Hash, PartialEq, Eq, Clone, Copy, SystemSet)]
pub enum OXrPreUpdateSet { pub enum OxrPreUpdateSet {
PollEvents, PollEvents,
HandleEvents, HandleEvents,
} }
pub struct OXrInitPlugin { pub struct OxrInitPlugin {
/// Information about the app this is being used to build. /// Information about the app this is being used to build.
pub app_info: AppInfo, pub app_info: AppInfo,
/// 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. /// 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 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.
@@ -59,9 +59,9 @@ pub struct OXrInitPlugin {
} }
#[derive(Component)] #[derive(Component)]
pub struct OXrTrackingRoot; pub struct OxrTrackingRoot;
impl Plugin for OXrInitPlugin { impl Plugin for OxrInitPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
match self.init_xr() { match self.init_xr() {
Ok(( Ok((
@@ -83,9 +83,9 @@ impl Plugin for OXrInitPlugin {
), ),
synchronous_pipeline_compilation: self.synchronous_pipeline_compilation, synchronous_pipeline_compilation: self.synchronous_pipeline_compilation,
}, },
ExtractResourcePlugin::<OXrCleanupSession>::default(), ExtractResourcePlugin::<OxrCleanupSession>::default(),
ExtractResourcePlugin::<OXrTime>::default(), ExtractResourcePlugin::<OxrTime>::default(),
ExtractResourcePlugin::<OXrRootTransform>::default(), ExtractResourcePlugin::<OxrRootTransform>::default(),
)) ))
.add_systems(First, reset_per_frame_resources) .add_systems(First, reset_per_frame_resources)
.add_systems( .add_systems(
@@ -93,7 +93,7 @@ impl Plugin for OXrInitPlugin {
( (
poll_events poll_events
.run_if(session_available) .run_if(session_available)
.in_set(OXrPreUpdateSet::PollEvents), .in_set(OxrPreUpdateSet::PollEvents),
( (
(create_xr_session, apply_deferred) (create_xr_session, apply_deferred)
.chain() .chain()
@@ -109,7 +109,7 @@ impl Plugin for OXrInitPlugin {
.run_if(on_event::<DestroyXrSession>()) .run_if(on_event::<DestroyXrSession>())
.run_if(status_equals(XrStatus::Exiting)), .run_if(status_equals(XrStatus::Exiting)),
) )
.in_set(OXrPreUpdateSet::HandleEvents), .in_set(OxrPreUpdateSet::HandleEvents),
), ),
) )
.add_systems( .add_systems(
@@ -123,24 +123,24 @@ impl Plugin for OXrInitPlugin {
focused_mode: UpdateMode::Continuous, focused_mode: UpdateMode::Continuous,
unfocused_mode: UpdateMode::Continuous, unfocused_mode: UpdateMode::Continuous,
}) })
.init_resource::<OXrCleanupSession>() .init_resource::<OxrCleanupSession>()
.init_resource::<OXrRootTransform>() .init_resource::<OxrRootTransform>()
.insert_non_send_resource(session_create_info); .insert_non_send_resource(session_create_info);
app.world app.world
.spawn((TransformBundle::default(), OXrTrackingRoot)); .spawn((TransformBundle::default(), OxrTrackingRoot));
let render_app = app.sub_app_mut(RenderApp); let render_app = app.sub_app_mut(RenderApp);
render_app render_app
.insert_resource(instance) .insert_resource(instance)
.insert_resource(system_id) .insert_resource(system_id)
.insert_resource(status) .insert_resource(status)
.init_resource::<OXrRootTransform>() .init_resource::<OxrRootTransform>()
.init_resource::<OXrCleanupSession>() .init_resource::<OxrCleanupSession>()
.add_systems( .add_systems(
Render, Render,
destroy_xr_session_render destroy_xr_session_render
.run_if(resource_equals(OXrCleanupSession(true))) .run_if(resource_equals(OxrCleanupSession(true)))
.after(RenderSet::ExtractCommands), .after(RenderSet::ExtractCommands),
) )
.add_systems( .add_systems(
@@ -164,12 +164,12 @@ impl Plugin for OXrInitPlugin {
app.configure_sets( app.configure_sets(
PreUpdate, PreUpdate,
( (
OXrPreUpdateSet::PollEvents.before(handle_session), OxrPreUpdateSet::PollEvents.before(handle_session),
OXrPreUpdateSet::HandleEvents.after(handle_session), OxrPreUpdateSet::HandleEvents.after(handle_session),
), ),
); );
let session_started = OXrSessionStarted::default(); let session_started = OxrSessionStarted::default();
app.insert_resource(session_started.clone()); app.insert_resource(session_started.clone());
@@ -180,24 +180,24 @@ impl Plugin for OXrInitPlugin {
} }
pub fn update_root_transform( pub fn update_root_transform(
mut root_transform: ResMut<OXrRootTransform>, mut root_transform: ResMut<OxrRootTransform>,
root: Query<&GlobalTransform, With<OXrTrackingRoot>>, root: Query<&GlobalTransform, With<OxrTrackingRoot>>,
) { ) {
let transform = root.single(); let transform = root.single();
root_transform.0 = *transform; root_transform.0 = *transform;
} }
fn xr_entry() -> Result<OXrEntry> { fn xr_entry() -> Result<OxrEntry> {
#[cfg(windows)] #[cfg(windows)]
let entry = openxr::Entry::linked(); let entry = openxr::Entry::linked();
#[cfg(not(windows))] #[cfg(not(windows))]
let entry = unsafe { openxr::Entry::load()? }; let entry = unsafe { openxr::Entry::load()? };
Ok(OXrEntry(entry)) Ok(OxrEntry(entry))
} }
impl OXrInitPlugin { impl OxrInitPlugin {
fn init_xr(&self) -> Result<(OXrInstance, OXrSystemId, WgpuGraphics, SessionConfigInfo)> { fn init_xr(&self) -> Result<(OxrInstance, OxrSystemId, WgpuGraphics, SessionConfigInfo)> {
let entry = xr_entry()?; let entry = xr_entry()?;
let available_exts = entry.enumerate_extensions()?; let available_exts = entry.enumerate_extensions()?;
@@ -224,7 +224,7 @@ impl OXrInitPlugin {
} else { } else {
available_backends.first().copied() available_backends.first().copied()
} }
.ok_or(OXrError::NoAvailableBackend)?; .ok_or(OxrError::NoAvailableBackend)?;
let exts = self.exts.clone() & available_exts; let exts = self.exts.clone() & available_exts;
@@ -265,7 +265,7 @@ impl OXrInitPlugin {
Ok(( Ok((
instance, instance,
OXrSystemId(system_id), OxrSystemId(system_id),
graphics, graphics,
session_create_info, session_create_info,
)) ))
@@ -274,7 +274,7 @@ impl OXrInitPlugin {
fn init_xr_session( fn init_xr_session(
device: &wgpu::Device, device: &wgpu::Device,
instance: &OXrInstance, instance: &OxrInstance,
system_id: openxr::SystemId, system_id: openxr::SystemId,
SessionConfigInfo { SessionConfigInfo {
blend_modes, blend_modes,
@@ -283,13 +283,13 @@ fn init_xr_session(
graphics_info, graphics_info,
}: SessionConfigInfo, }: SessionConfigInfo,
) -> Result<( ) -> Result<(
OXrSession, OxrSession,
OXrFrameWaiter, OxrFrameWaiter,
OXrFrameStream, OxrFrameStream,
OXrSwapchain, OxrSwapchain,
OXrSwapchainImages, OxrSwapchainImages,
OXrGraphicsInfo, OxrGraphicsInfo,
OXrStage, OxrStage,
)> { )> {
let (session, frame_waiter, frame_stream) = let (session, frame_waiter, frame_stream) =
unsafe { instance.create_session(system_id, graphics_info)? }; unsafe { instance.create_session(system_id, graphics_info)? };
@@ -297,7 +297,7 @@ fn init_xr_session(
// TODO!() support other view configurations // TODO!() support other view configurations
let available_view_configurations = instance.enumerate_view_configurations(system_id)?; let available_view_configurations = instance.enumerate_view_configurations(system_id)?;
if !available_view_configurations.contains(&openxr::ViewConfigurationType::PRIMARY_STEREO) { if !available_view_configurations.contains(&openxr::ViewConfigurationType::PRIMARY_STEREO) {
return Err(OXrError::NoAvailableViewConfiguration); return Err(OxrError::NoAvailableViewConfiguration);
} }
let view_configuration_type = openxr::ViewConfigurationType::PRIMARY_STEREO; let view_configuration_type = openxr::ViewConfigurationType::PRIMARY_STEREO;
@@ -343,7 +343,7 @@ fn init_xr_session(
None None
} }
} }
.ok_or(OXrError::NoAvailableViewConfiguration)?; .ok_or(OxrError::NoAvailableViewConfiguration)?;
let available_formats = session.enumerate_swapchain_formats()?; let available_formats = session.enumerate_swapchain_formats()?;
@@ -358,7 +358,7 @@ fn init_xr_session(
} else { } else {
available_formats.first().copied() available_formats.first().copied()
} }
.ok_or(OXrError::NoAvailableFormat)?; .ok_or(OxrError::NoAvailableFormat)?;
let swapchain = session.create_swapchain(SwapchainCreateInfo { let swapchain = session.create_swapchain(SwapchainCreateInfo {
create_flags: SwapchainCreateFlags::EMPTY, create_flags: SwapchainCreateFlags::EMPTY,
@@ -391,15 +391,15 @@ fn init_xr_session(
} else { } else {
available_blend_modes.first().copied() available_blend_modes.first().copied()
} }
.ok_or(OXrError::NoAvailableBackend)?; .ok_or(OxrError::NoAvailableBackend)?;
let stage = OXrStage( let stage = OxrStage(
session session
.create_reference_space(openxr::ReferenceSpaceType::STAGE, openxr::Posef::IDENTITY)? .create_reference_space(openxr::ReferenceSpaceType::STAGE, openxr::Posef::IDENTITY)?
.into(), .into(),
); );
let graphics_info = OXrGraphicsInfo { let graphics_info = OxrGraphicsInfo {
blend_mode, blend_mode,
resolution, resolution,
format, format,
@@ -419,19 +419,19 @@ fn init_xr_session(
/// This is used solely to transport resources from the main world to the render world. /// This is used solely to transport resources from the main world to the render world.
#[derive(Resource)] #[derive(Resource)]
struct XrRenderResources { struct XrRenderResources {
session: OXrSession, session: OxrSession,
frame_stream: OXrFrameStream, frame_stream: OxrFrameStream,
swapchain: OXrSwapchain, swapchain: OxrSwapchain,
images: OXrSwapchainImages, images: OxrSwapchainImages,
graphics_info: OXrGraphicsInfo, graphics_info: OxrGraphicsInfo,
stage: OXrStage, stage: OxrStage,
} }
pub fn create_xr_session( pub fn create_xr_session(
device: Res<RenderDevice>, device: Res<RenderDevice>,
instance: Res<OXrInstance>, instance: Res<OxrInstance>,
create_info: NonSend<SessionConfigInfo>, create_info: NonSend<SessionConfigInfo>,
system_id: Res<OXrSystemId>, system_id: Res<OxrSystemId>,
mut commands: Commands, mut commands: Commands,
) { ) {
match init_xr_session( match init_xr_session(
@@ -459,7 +459,7 @@ pub fn create_xr_session(
} }
} }
pub fn begin_xr_session(session: Res<OXrSession>, session_started: Res<OXrSessionStarted>) { pub fn begin_xr_session(session: Res<OxrSession>, session_started: Res<OxrSessionStarted>) {
let _span = info_span!("xr_begin_session"); let _span = info_span!("xr_begin_session");
session session
.begin(openxr::ViewConfigurationType::PRIMARY_STEREO) .begin(openxr::ViewConfigurationType::PRIMARY_STEREO)
@@ -467,7 +467,7 @@ pub fn begin_xr_session(session: Res<OXrSession>, session_started: Res<OXrSessio
session_started.set(true); session_started.set(true);
} }
pub fn end_xr_session(session: Res<OXrSession>, session_started: Res<OXrSessionStarted>) { pub fn end_xr_session(session: Res<OxrSession>, session_started: Res<OxrSessionStarted>) {
let _span = info_span!("xr_end_session"); let _span = info_span!("xr_end_session");
session.end().expect("Failed to end session"); session.end().expect("Failed to end session");
session_started.set(false); session_started.set(false);
@@ -496,7 +496,7 @@ pub fn transfer_xr_resources(mut commands: Commands, mut world: ResMut<MainWorld
} }
/// Polls any OpenXR events and handles them accordingly /// Polls any OpenXR events and handles them accordingly
pub fn poll_events(instance: Res<OXrInstance>, status: Res<XrSharedStatus>) { pub fn poll_events(instance: Res<OxrInstance>, status: Res<XrSharedStatus>) {
let _span = info_span!("xr_poll_events"); let _span = info_span!("xr_poll_events");
let mut buffer = Default::default(); let mut buffer = Default::default();
while let Some(event) = instance while let Some(event) = instance
@@ -532,24 +532,24 @@ pub fn poll_events(instance: Res<OXrInstance>, status: Res<XrSharedStatus>) {
} }
} }
pub fn reset_per_frame_resources(mut cleanup: ResMut<OXrCleanupSession>) { pub fn reset_per_frame_resources(mut cleanup: ResMut<OxrCleanupSession>) {
**cleanup = false; **cleanup = false;
} }
pub fn destroy_xr_session(mut commands: Commands) { pub fn destroy_xr_session(mut commands: Commands) {
commands.remove_resource::<OXrSession>(); commands.remove_resource::<OxrSession>();
commands.remove_resource::<OXrFrameWaiter>(); commands.remove_resource::<OxrFrameWaiter>();
commands.remove_resource::<OXrSwapchainImages>(); commands.remove_resource::<OxrSwapchainImages>();
commands.remove_resource::<OXrGraphicsInfo>(); commands.remove_resource::<OxrGraphicsInfo>();
commands.remove_resource::<OXrStage>(); commands.remove_resource::<OxrStage>();
commands.insert_resource(OXrCleanupSession(true)); commands.insert_resource(OxrCleanupSession(true));
} }
pub fn destroy_xr_session_render(world: &mut World) { pub fn destroy_xr_session_render(world: &mut World) {
world.remove_resource::<OXrSwapchain>(); world.remove_resource::<OxrSwapchain>();
world.remove_resource::<OXrFrameStream>(); world.remove_resource::<OxrFrameStream>();
world.remove_resource::<OXrStage>(); world.remove_resource::<OxrStage>();
world.remove_resource::<OXrSwapchainImages>(); world.remove_resource::<OxrSwapchainImages>();
world.remove_resource::<OXrGraphicsInfo>(); world.remove_resource::<OxrGraphicsInfo>();
world.remove_resource::<OXrSession>(); world.remove_resource::<OxrSession>();
} }

View File

@@ -3,12 +3,12 @@ use std::mem;
use openxr::{sys, CompositionLayerFlags, Fovf, Posef, Rect2Di, Space}; use openxr::{sys, CompositionLayerFlags, Fovf, Posef, Rect2Di, Space};
use crate::graphics::graphics_match; use crate::graphics::graphics_match;
use crate::resources::OXrSwapchain; use crate::resources::OxrSwapchain;
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct SwapchainSubImage<'a> { pub struct SwapchainSubImage<'a> {
inner: sys::SwapchainSubImage, inner: sys::SwapchainSubImage,
swapchain: Option<&'a OXrSwapchain>, swapchain: Option<&'a OxrSwapchain>,
} }
impl<'a> SwapchainSubImage<'a> { impl<'a> SwapchainSubImage<'a> {
@@ -30,7 +30,7 @@ impl<'a> SwapchainSubImage<'a> {
&self.inner &self.inner
} }
#[inline] #[inline]
pub fn swapchain(mut self, value: &'a OXrSwapchain) -> Self { pub fn swapchain(mut self, value: &'a OxrSwapchain) -> Self {
graphics_match!( graphics_match!(
&value.0; &value.0;
swap => self.inner.swapchain = swap.as_raw() swap => self.inner.swapchain = swap.as_raw()
@@ -59,7 +59,7 @@ impl<'a> Default for SwapchainSubImage<'a> {
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct CompositionLayerProjectionView<'a> { pub struct CompositionLayerProjectionView<'a> {
inner: sys::CompositionLayerProjectionView, inner: sys::CompositionLayerProjectionView,
swapchain: Option<&'a OXrSwapchain>, swapchain: Option<&'a OxrSwapchain>,
} }
impl<'a> CompositionLayerProjectionView<'a> { impl<'a> CompositionLayerProjectionView<'a> {
@@ -104,13 +104,13 @@ impl<'a> Default for CompositionLayerProjectionView<'a> {
} }
} }
pub unsafe trait CompositionLayer<'a> { pub unsafe trait CompositionLayer<'a> {
fn swapchain(&self) -> Option<&'a OXrSwapchain>; fn swapchain(&self) -> Option<&'a OxrSwapchain>;
fn header(&self) -> &'a sys::CompositionLayerBaseHeader; fn header(&self) -> &'a sys::CompositionLayerBaseHeader;
} }
#[derive(Clone)] #[derive(Clone)]
pub struct CompositionLayerProjection<'a> { pub struct CompositionLayerProjection<'a> {
inner: sys::CompositionLayerProjection, inner: sys::CompositionLayerProjection,
swapchain: Option<&'a OXrSwapchain>, swapchain: Option<&'a OxrSwapchain>,
views: Vec<sys::CompositionLayerProjectionView>, views: Vec<sys::CompositionLayerProjectionView>,
} }
impl<'a> CompositionLayerProjection<'a> { impl<'a> CompositionLayerProjection<'a> {
@@ -154,7 +154,7 @@ impl<'a> CompositionLayerProjection<'a> {
} }
} }
unsafe impl<'a> CompositionLayer<'a> for CompositionLayerProjection<'a> { unsafe impl<'a> CompositionLayer<'a> for CompositionLayerProjection<'a> {
fn swapchain(&self) -> Option<&'a OXrSwapchain> { fn swapchain(&self) -> Option<&'a OxrSwapchain> {
self.swapchain self.swapchain
} }

View File

@@ -7,7 +7,7 @@ use bevy::{
}; };
use bevy_xr::camera::XrCameraPlugin; use bevy_xr::camera::XrCameraPlugin;
use bevy_xr::session::XrSessionPlugin; use bevy_xr::session::XrSessionPlugin;
use init::OXrInitPlugin; use init::OxrInitPlugin;
use render::XrRenderPlugin; use render::XrRenderPlugin;
pub mod error; pub mod error;
@@ -25,7 +25,7 @@ pub fn add_xr_plugins<G: PluginGroup>(plugins: G) -> PluginGroupBuilder {
.disable::<RenderPlugin>() .disable::<RenderPlugin>()
.disable::<PipelinedRenderingPlugin>() .disable::<PipelinedRenderingPlugin>()
.add_before::<RenderPlugin, _>(XrSessionPlugin) .add_before::<RenderPlugin, _>(XrSessionPlugin)
.add_before::<RenderPlugin, _>(OXrInitPlugin { .add_before::<RenderPlugin, _>(OxrInitPlugin {
app_info: default(), app_info: default(),
exts: default(), exts: default(),
blend_modes: default(), blend_modes: default(),

View File

@@ -12,7 +12,7 @@ use bevy::{
use bevy_xr::camera::{XrCamera, XrCameraBundle, XrProjection}; use bevy_xr::camera::{XrCamera, XrCameraBundle, XrProjection};
use openxr::{CompositionLayerFlags, ViewStateFlags}; use openxr::{CompositionLayerFlags, ViewStateFlags};
use crate::init::{session_started, OXrPreUpdateSet}; use crate::init::{session_started, OxrPreUpdateSet};
use crate::layer_builder::*; use crate::layer_builder::*;
use crate::resources::*; use crate::resources::*;
@@ -20,17 +20,17 @@ pub struct XrRenderPlugin;
impl Plugin for XrRenderPlugin { impl Plugin for XrRenderPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.add_plugins((ExtractResourcePlugin::<OXrViews>::default(),)) app.add_plugins((ExtractResourcePlugin::<OxrViews>::default(),))
.add_systems( .add_systems(
PreUpdate, PreUpdate,
( (
init_views.run_if(resource_added::<OXrGraphicsInfo>), init_views.run_if(resource_added::<OxrGraphicsInfo>),
wait_frame.run_if(session_started), wait_frame.run_if(session_started),
locate_views.run_if(session_started), locate_views.run_if(session_started),
update_views.run_if(session_started), update_views.run_if(session_started),
) )
.chain() .chain()
.after(OXrPreUpdateSet::HandleEvents), .after(OxrPreUpdateSet::HandleEvents),
) )
.add_systems( .add_systems(
PostUpdate, PostUpdate,
@@ -65,9 +65,9 @@ pub const XR_TEXTURE_INDEX: u32 = 3383858418;
// TODO: have cameras initialized externally and then recieved by this function. // TODO: have cameras initialized externally and then recieved by this function.
/// This is needed to properly initialize the texture views so that bevy will set them to the correct resolution despite them being updated in the render world. /// This is needed to properly initialize the texture views so that bevy will set them to the correct resolution despite them being updated in the render world.
pub fn init_views( pub fn init_views(
graphics_info: Res<OXrGraphicsInfo>, graphics_info: Res<OxrGraphicsInfo>,
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,
) { ) {
let _span = info_span!("xr_init_views"); let _span = info_span!("xr_init_views");
@@ -93,22 +93,22 @@ pub fn init_views(
)); ));
views.push(default()); views.push(default());
} }
commands.insert_resource(OXrViews(views)); commands.insert_resource(OxrViews(views));
} }
pub fn wait_frame(mut frame_waiter: ResMut<OXrFrameWaiter>, mut commands: Commands) { pub fn wait_frame(mut frame_waiter: ResMut<OxrFrameWaiter>, mut commands: Commands) {
let _span = info_span!("xr_wait_frame"); let _span = info_span!("xr_wait_frame");
let state = frame_waiter.wait().expect("Failed to wait frame"); let state = frame_waiter.wait().expect("Failed to wait frame");
// Here we insert the predicted display time for when this frame will be displayed. // Here we insert the predicted display time for when this frame will be displayed.
// TODO: don't add predicted_display_period if pipelined rendering plugin not enabled // TODO: don't add predicted_display_period if pipelined rendering plugin not enabled
commands.insert_resource(OXrTime(state.predicted_display_time)); commands.insert_resource(OxrTime(state.predicted_display_time));
} }
pub fn locate_views( pub fn locate_views(
session: Res<OXrSession>, session: Res<OxrSession>,
stage: Res<OXrStage>, stage: Res<OxrStage>,
time: Res<OXrTime>, time: Res<OxrTime>,
mut openxr_views: ResMut<OXrViews>, mut openxr_views: ResMut<OxrViews>,
) { ) {
let _span = info_span!("xr_locate_views"); let _span = info_span!("xr_locate_views");
let (flags, xr_views) = session let (flags, xr_views) = session
@@ -125,7 +125,7 @@ pub fn locate_views(
flags & ViewStateFlags::ORIENTATION_VALID == ViewStateFlags::ORIENTATION_VALID, flags & ViewStateFlags::ORIENTATION_VALID == ViewStateFlags::ORIENTATION_VALID,
flags & ViewStateFlags::POSITION_VALID == ViewStateFlags::POSITION_VALID, flags & ViewStateFlags::POSITION_VALID == ViewStateFlags::POSITION_VALID,
) { ) {
(true, true) => *openxr_views = OXrViews(xr_views), (true, true) => *openxr_views = OxrViews(xr_views),
(true, false) => { (true, false) => {
for (i, view) in openxr_views.iter_mut().enumerate() { for (i, view) in openxr_views.iter_mut().enumerate() {
view.pose.orientation = xr_views[i].pose.orientation; view.pose.orientation = xr_views[i].pose.orientation;
@@ -142,7 +142,7 @@ pub fn locate_views(
pub fn update_views( pub fn update_views(
mut query: Query<(&mut Transform, &mut XrProjection, &XrCamera)>, mut query: Query<(&mut Transform, &mut XrProjection, &XrCamera)>,
views: ResMut<OXrViews>, views: ResMut<OxrViews>,
) { ) {
for (mut transform, mut projection, camera) in query.iter_mut() { for (mut transform, mut projection, camera) in query.iter_mut() {
let Some(view) = views.get(camera.0 as usize) else { let Some(view) = views.get(camera.0 as usize) else {
@@ -162,8 +162,8 @@ pub fn update_views(
} }
pub fn update_views_render_world( pub fn update_views_render_world(
views: Res<OXrViews>, views: Res<OxrViews>,
root: Res<OXrRootTransform>, root: Res<OxrRootTransform>,
mut query: Query<(&mut ExtractedView, &XrCamera)>, mut query: Query<(&mut ExtractedView, &XrCamera)>,
) { ) {
for (mut extracted_view, camera) in query.iter_mut() { for (mut extracted_view, camera) in query.iter_mut() {
@@ -280,10 +280,10 @@ fn calculate_projection(near_z: f32, fov: openxr::Fovf) -> Mat4 {
/// # Safety /// # Safety
/// Images inserted into texture views here should not be written to until [`wait_image`] is ran /// Images inserted into texture views here should not be written to until [`wait_image`] is ran
pub fn insert_texture_views( 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<OxrGraphicsInfo>,
) { ) {
let _span = info_span!("xr_insert_texture_views"); let _span = info_span!("xr_insert_texture_views");
let index = swapchain.acquire_image().expect("Failed to acquire image"); let index = swapchain.acquire_image().expect("Failed to acquire image");
@@ -294,7 +294,7 @@ pub fn insert_texture_views(
} }
} }
pub fn wait_image(mut swapchain: ResMut<OXrSwapchain>) { pub fn wait_image(mut swapchain: ResMut<OxrSwapchain>) {
swapchain swapchain
.wait_image(openxr::Duration::INFINITE) .wait_image(openxr::Duration::INFINITE)
.expect("Failed to wait image"); .expect("Failed to wait image");
@@ -303,7 +303,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: &OxrGraphicsInfo,
index: u32, index: u32,
) -> ManualTextureViewHandle { ) -> ManualTextureViewHandle {
let view = texture.create_view(&wgpu::TextureViewDescriptor { let view = texture.create_view(&wgpu::TextureViewDescriptor {
@@ -322,17 +322,17 @@ pub fn add_texture_view(
handle handle
} }
pub fn begin_frame(mut frame_stream: ResMut<OXrFrameStream>) { pub fn begin_frame(mut frame_stream: ResMut<OxrFrameStream>) {
frame_stream.begin().expect("Failed to begin frame") frame_stream.begin().expect("Failed to begin frame")
} }
pub fn end_frame( pub fn end_frame(
mut frame_stream: ResMut<OXrFrameStream>, mut frame_stream: ResMut<OxrFrameStream>,
mut swapchain: ResMut<OXrSwapchain>, mut swapchain: ResMut<OxrSwapchain>,
stage: Res<OXrStage>, stage: Res<OxrStage>,
display_time: Res<OXrTime>, display_time: Res<OxrTime>,
graphics_info: Res<OXrGraphicsInfo>, graphics_info: Res<OxrGraphicsInfo>,
openxr_views: Res<OXrViews>, openxr_views: Res<OxrViews>,
) { ) {
let _span = info_span!("xr_end_frame"); let _span = info_span!("xr_end_frame");
swapchain.release_image().unwrap(); swapchain.release_image().unwrap();

View File

@@ -5,32 +5,32 @@ use bevy::prelude::*;
use bevy::render::extract_resource::ExtractResource; use bevy::render::extract_resource::ExtractResource;
use openxr::AnyGraphics; use openxr::AnyGraphics;
use crate::error::OXrError; use crate::error::OxrError;
use crate::graphics::*; use crate::graphics::*;
use crate::layer_builder::CompositionLayer; use crate::layer_builder::CompositionLayer;
use crate::types::*; use crate::types::*;
/// Wrapper around the entry point to the OpenXR API /// Wrapper around the entry point to the OpenXR API
#[derive(Deref, Clone)] #[derive(Deref, Clone)]
pub struct OXrEntry(pub openxr::Entry); pub struct OxrEntry(pub openxr::Entry);
impl OXrEntry { impl OxrEntry {
/// Enumerate available extensions for this OpenXR runtime. /// Enumerate available extensions for this OpenXR runtime.
pub fn enumerate_extensions(&self) -> Result<OXrExtensions> { pub fn enumerate_extensions(&self) -> Result<OxrExtensions> {
Ok(self.0.enumerate_extensions().map(Into::into)?) Ok(self.0.enumerate_extensions().map(Into::into)?)
} }
pub fn create_instance( pub fn create_instance(
&self, &self,
app_info: AppInfo, app_info: AppInfo,
exts: OXrExtensions, exts: OxrExtensions,
layers: &[&str], layers: &[&str],
backend: GraphicsBackend, backend: GraphicsBackend,
) -> Result<OXrInstance> { ) -> Result<OxrInstance> {
let available_exts = self.enumerate_extensions()?; let available_exts = self.enumerate_extensions()?;
if !backend.is_available(&available_exts) { if !backend.is_available(&available_exts) {
return Err(OXrError::UnavailableBackend(backend)); return Err(OxrError::UnavailableBackend(backend));
} }
let required_exts = exts | backend.required_exts(); let required_exts = exts | backend.required_exts();
@@ -46,7 +46,7 @@ impl OXrEntry {
layers, layers,
)?; )?;
Ok(OXrInstance(instance, backend, app_info)) Ok(OxrInstance(instance, backend, app_info))
} }
pub fn available_backends(&self) -> Result<Vec<GraphicsBackend>> { pub fn available_backends(&self) -> Result<Vec<GraphicsBackend>> {
@@ -58,13 +58,13 @@ impl OXrEntry {
/// Wrapper around [openxr::Instance] with additional data for safety. /// Wrapper around [openxr::Instance] with additional data for safety.
#[derive(Resource, Deref, Clone)] #[derive(Resource, Deref, Clone)]
pub struct OXrInstance( pub struct OxrInstance(
#[deref] pub openxr::Instance, #[deref] pub openxr::Instance,
pub(crate) GraphicsBackend, pub(crate) GraphicsBackend,
pub(crate) AppInfo, pub(crate) AppInfo,
); );
impl OXrInstance { impl OxrInstance {
pub fn into_inner(self) -> openxr::Instance { pub fn into_inner(self) -> openxr::Instance {
self.0 self.0
} }
@@ -84,7 +84,7 @@ impl OXrInstance {
) )
} }
/// Creates an [OXrSession] /// Creates an [OxrSession]
/// ///
/// # Safety /// # Safety
/// ///
@@ -93,9 +93,9 @@ impl OXrInstance {
&self, &self,
system_id: openxr::SystemId, system_id: openxr::SystemId,
info: SessionCreateInfo, info: SessionCreateInfo,
) -> Result<(OXrSession, OXrFrameWaiter, OXrFrameStream)> { ) -> Result<(OxrSession, OxrFrameWaiter, OxrFrameStream)> {
if !info.0.using_graphics_of_val(&self.1) { if !info.0.using_graphics_of_val(&self.1) {
return Err(OXrError::GraphicsBackendMismatch { return Err(OxrError::GraphicsBackendMismatch {
item: std::any::type_name::<SessionCreateInfo>(), item: std::any::type_name::<SessionCreateInfo>(),
backend: info.0.graphics_name(), backend: info.0.graphics_name(),
expected_backend: self.1.graphics_name(), expected_backend: self.1.graphics_name(),
@@ -105,7 +105,7 @@ impl OXrInstance {
info.0; info.0;
info => { info => {
let (session, frame_waiter, frame_stream) = self.0.create_session::<Api>(system_id, &info)?; let (session, frame_waiter, frame_stream) = self.0.create_session::<Api>(system_id, &info)?;
Ok((session.into(), OXrFrameWaiter(frame_waiter), OXrFrameStream(Api::wrap(frame_stream)))) Ok((session.into(), OxrFrameWaiter(frame_waiter), OxrFrameStream(Api::wrap(frame_stream))))
} }
) )
} }
@@ -113,22 +113,22 @@ impl OXrInstance {
/// Graphics agnostic wrapper around [openxr::Session] /// Graphics agnostic wrapper around [openxr::Session]
#[derive(Resource, Deref, Clone)] #[derive(Resource, Deref, Clone)]
pub struct OXrSession( pub struct OxrSession(
#[deref] pub openxr::Session<AnyGraphics>, #[deref] pub openxr::Session<AnyGraphics>,
pub GraphicsWrap<Self>, pub GraphicsWrap<Self>,
); );
impl GraphicsType for OXrSession { impl GraphicsType for OxrSession {
type Inner<G: GraphicsExt> = openxr::Session<G>; type Inner<G: GraphicsExt> = openxr::Session<G>;
} }
impl<G: GraphicsExt> From<openxr::Session<G>> for OXrSession { impl<G: GraphicsExt> From<openxr::Session<G>> for OxrSession {
fn from(session: openxr::Session<G>) -> Self { fn from(session: openxr::Session<G>) -> Self {
Self::new(session) Self::new(session)
} }
} }
impl OXrSession { impl OxrSession {
pub fn new<G: GraphicsExt>(session: openxr::Session<G>) -> Self { pub fn new<G: GraphicsExt>(session: openxr::Session<G>) -> Self {
Self(session.clone().into_any_graphics(), G::wrap(session)) Self(session.clone().into_any_graphics(), G::wrap(session))
} }
@@ -141,24 +141,24 @@ impl OXrSession {
) )
} }
/// Creates an [OXrSwapchain]. /// Creates an [OxrSwapchain].
pub fn create_swapchain(&self, info: SwapchainCreateInfo) -> Result<OXrSwapchain> { pub fn create_swapchain(&self, info: SwapchainCreateInfo) -> Result<OxrSwapchain> {
Ok(OXrSwapchain(graphics_match!( Ok(OxrSwapchain(graphics_match!(
&self.1; &self.1;
session => session.create_swapchain(&info.try_into()?)? => OXrSwapchain session => session.create_swapchain(&info.try_into()?)? => OxrSwapchain
))) )))
} }
} }
/// Graphics agnostic wrapper around [openxr::FrameStream] /// Graphics agnostic wrapper around [openxr::FrameStream]
#[derive(Resource)] #[derive(Resource)]
pub struct OXrFrameStream(pub GraphicsWrap<Self>); pub struct OxrFrameStream(pub GraphicsWrap<Self>);
impl GraphicsType for OXrFrameStream { impl GraphicsType for OxrFrameStream {
type Inner<G: GraphicsExt> = openxr::FrameStream<G>; type Inner<G: GraphicsExt> = openxr::FrameStream<G>;
} }
impl OXrFrameStream { impl OxrFrameStream {
/// Indicate that graphics device work is beginning. /// Indicate that graphics device work is beginning.
pub fn begin(&mut self) -> openxr::Result<()> { pub fn begin(&mut self) -> openxr::Result<()> {
graphics_match!( graphics_match!(
@@ -204,17 +204,17 @@ impl OXrFrameStream {
/// Handle for waiting to render a frame. Check [`FrameWaiter`](openxr::FrameWaiter) for available methods. /// Handle for waiting to render a frame. Check [`FrameWaiter`](openxr::FrameWaiter) for available methods.
#[derive(Resource, Deref, DerefMut)] #[derive(Resource, Deref, DerefMut)]
pub struct OXrFrameWaiter(pub openxr::FrameWaiter); pub struct OxrFrameWaiter(pub openxr::FrameWaiter);
/// Graphics agnostic wrapper around [openxr::Swapchain] /// Graphics agnostic wrapper around [openxr::Swapchain]
#[derive(Resource)] #[derive(Resource)]
pub struct OXrSwapchain(pub GraphicsWrap<Self>); pub struct OxrSwapchain(pub GraphicsWrap<Self>);
impl GraphicsType for OXrSwapchain { impl GraphicsType for OxrSwapchain {
type Inner<G: GraphicsExt> = openxr::Swapchain<G>; type Inner<G: GraphicsExt> = openxr::Swapchain<G>;
} }
impl OXrSwapchain { impl OxrSwapchain {
/// Determine the index of the next image to render to in the swapchain image array /// Determine the index of the next image to render to in the swapchain image array
pub fn acquire_image(&mut self) -> Result<u32> { pub fn acquire_image(&mut self) -> Result<u32> {
graphics_match!( graphics_match!(
@@ -245,7 +245,7 @@ impl OXrSwapchain {
device: &wgpu::Device, device: &wgpu::Device,
format: wgpu::TextureFormat, format: wgpu::TextureFormat,
resolution: UVec2, resolution: UVec2,
) -> Result<OXrSwapchainImages> { ) -> Result<OxrSwapchainImages> {
graphics_match!( graphics_match!(
&self.0; &self.0;
swap => { swap => {
@@ -255,7 +255,7 @@ impl OXrSwapchain {
images.push(Api::to_wgpu_img(image, device, format, resolution)?); images.push(Api::to_wgpu_img(image, device, format, resolution)?);
} }
} }
Ok(OXrSwapchainImages(images.into())) Ok(OxrSwapchainImages(images.into()))
} }
) )
} }
@@ -263,23 +263,23 @@ impl OXrSwapchain {
/// Stores the generated swapchain images. /// Stores the generated swapchain images.
#[derive(Debug, Deref, Resource, Clone)] #[derive(Debug, Deref, Resource, Clone)]
pub struct OXrSwapchainImages(pub Arc<Vec<wgpu::Texture>>); pub struct OxrSwapchainImages(pub Arc<Vec<wgpu::Texture>>);
/// Thread safe wrapper around [openxr::Space] representing the stage. /// Thread safe wrapper around [openxr::Space] representing the stage.
#[derive(Deref, Clone, Resource)] #[derive(Deref, Clone, Resource)]
pub struct OXrStage(pub Arc<openxr::Space>); pub struct OxrStage(pub Arc<openxr::Space>);
/// Stores the latest generated [OXrViews] /// Stores the latest generated [OxrViews]
#[derive(Clone, Resource, ExtractResource, Deref, DerefMut)] #[derive(Clone, Resource, ExtractResource, Deref, DerefMut)]
pub struct OXrViews(pub Vec<openxr::View>); pub struct OxrViews(pub Vec<openxr::View>);
/// Wrapper around [openxr::SystemId] to allow it to be stored as a resource. /// Wrapper around [openxr::SystemId] to allow it to be stored as a resource.
#[derive(Debug, Copy, Clone, Deref, Default, Eq, PartialEq, Ord, PartialOrd, Hash, Resource)] #[derive(Debug, Copy, Clone, Deref, Default, Eq, PartialEq, Ord, PartialOrd, Hash, Resource)]
pub struct OXrSystemId(pub openxr::SystemId); pub struct OxrSystemId(pub openxr::SystemId);
/// Resource storing graphics info for the currently running session. /// Resource storing graphics info for the currently running session.
#[derive(Clone, Copy, Resource)] #[derive(Clone, Copy, Resource)]
pub struct OXrGraphicsInfo { pub struct OxrGraphicsInfo {
pub blend_mode: EnvironmentBlendMode, pub blend_mode: EnvironmentBlendMode,
pub resolution: UVec2, pub resolution: UVec2,
pub format: wgpu::TextureFormat, pub format: wgpu::TextureFormat,
@@ -299,9 +299,9 @@ pub struct SessionConfigInfo {
} }
#[derive(Resource, Clone, Default)] #[derive(Resource, Clone, Default)]
pub struct OXrSessionStarted(Arc<AtomicBool>); pub struct OxrSessionStarted(Arc<AtomicBool>);
impl OXrSessionStarted { impl OxrSessionStarted {
pub fn set(&self, val: bool) { pub fn set(&self, val: bool) {
self.0.store(val, Ordering::SeqCst); self.0.store(val, Ordering::SeqCst);
} }
@@ -313,12 +313,12 @@ impl OXrSessionStarted {
/// The calculated display time for the app. Passed through the pipeline. /// The calculated display time for the app. Passed through the pipeline.
#[derive(Copy, Clone, Eq, PartialEq, Deref, DerefMut, Resource, ExtractResource)] #[derive(Copy, Clone, Eq, PartialEq, Deref, DerefMut, Resource, ExtractResource)]
pub struct OXrTime(pub openxr::Time); pub struct OxrTime(pub openxr::Time);
/// The root transform's global position for late latching in the render world. /// The root transform's global position for late latching in the render world.
#[derive(ExtractResource, Resource, Clone, Copy, Default)] #[derive(ExtractResource, Resource, Clone, Copy, Default)]
pub struct OXrRootTransform(pub GlobalTransform); pub struct OxrRootTransform(pub GlobalTransform);
#[derive(ExtractResource, Resource, Clone, Copy, Default, Deref, DerefMut, PartialEq)] #[derive(ExtractResource, Resource, Clone, Copy, Default, Deref, DerefMut, PartialEq)]
/// This is inserted into the world to signify if the session should be cleaned up. /// This is inserted into the world to signify if the session should be cleaned up.
pub struct OXrCleanupSession(pub bool); pub struct OxrCleanupSession(pub bool);

View File

@@ -1,13 +1,13 @@
use std::borrow::Cow; use std::borrow::Cow;
use crate::error::OXrError; use crate::error::OxrError;
use crate::graphics::{GraphicsExt, GraphicsType, GraphicsWrap}; use crate::graphics::{GraphicsExt, GraphicsType, GraphicsWrap};
pub use crate::openxr::exts::OXrExtensions; pub use crate::openxr::exts::OxrExtensions;
pub use openxr::{EnvironmentBlendMode, SwapchainCreateFlags, SwapchainUsageFlags}; pub use openxr::{EnvironmentBlendMode, SwapchainCreateFlags, SwapchainUsageFlags};
pub type Result<T> = std::result::Result<T, OXrError>; pub type Result<T> = std::result::Result<T, OxrError>;
/// A container for all required graphics objects needed for a bevy app. /// A container for all required graphics objects needed for a bevy app.
pub struct WgpuGraphics( pub struct WgpuGraphics(
@@ -70,14 +70,14 @@ pub struct SwapchainCreateInfo {
} }
impl<G: GraphicsExt> TryFrom<SwapchainCreateInfo> for openxr::SwapchainCreateInfo<G> { impl<G: GraphicsExt> TryFrom<SwapchainCreateInfo> for openxr::SwapchainCreateInfo<G> {
type Error = OXrError; type Error = OxrError;
fn try_from(value: SwapchainCreateInfo) -> Result<Self> { fn try_from(value: SwapchainCreateInfo) -> Result<Self> {
Ok(openxr::SwapchainCreateInfo { Ok(openxr::SwapchainCreateInfo {
create_flags: value.create_flags, create_flags: value.create_flags,
usage_flags: value.usage_flags, usage_flags: value.usage_flags,
format: G::from_wgpu_format(value.format) format: G::from_wgpu_format(value.format)
.ok_or(OXrError::UnsupportedTextureFormat(value.format))?, .ok_or(OxrError::UnsupportedTextureFormat(value.format))?,
sample_count: value.sample_count, sample_count: value.sample_count,
width: value.width, width: value.width,
height: value.height, height: value.height,

View File

@@ -3,6 +3,9 @@ name = "bevy_webxr"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
# bevy can't be placed behind target or proc macros won't work properly
[dependencies]
bevy.workspace = true
# all dependencies are placed under this since on anything but wasm, this crate is completely empty # all dependencies are placed under this since on anything but wasm, this crate is completely empty
[target.'cfg(target_family = "wasm")'.dependencies] [target.'cfg(target_family = "wasm")'.dependencies]
@@ -11,4 +14,3 @@ wgpu = "0.19.3"
wgpu-hal = "0.19.3" wgpu-hal = "0.19.3"
bevy_xr.path = "../bevy_xr" bevy_xr.path = "../bevy_xr"
bevy.workspace = true