From 10825557c6645834cef198161e0364d59e362fd2 Mon Sep 17 00:00:00 2001 From: awtterpip Date: Mon, 29 Jan 2024 21:23:29 -0600 Subject: [PATCH] small changes --- src/lib.rs | 103 ++++++++++++++++++++++ src/main.rs | 58 ++++++++++++ xr_api/Cargo.toml | 6 +- xr_api/src/api_traits.rs | 11 ++- xr_api/src/backend/oxr.rs | 68 +++++++++++--- xr_api/src/backend/oxr/graphics.rs | 60 +++++++------ xr_api/src/backend/oxr/graphics/vulkan.rs | 7 +- xr_api/src/error.rs | 2 +- 8 files changed, 268 insertions(+), 47 deletions(-) create mode 100644 src/main.rs diff --git a/src/lib.rs b/src/lib.rs index e69de29..92bcb85 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -0,0 +1,103 @@ +use std::sync::Arc; + +use bevy::{ + app::PluginGroupBuilder, + prelude::*, + render::{ + camera::{ManualTextureView, ManualTextureViewHandle, ManualTextureViews}, + pipelined_rendering::PipelinedRenderingPlugin, + renderer::{render_system, RenderAdapter, RenderAdapterInfo, RenderInstance, RenderQueue}, + Render, RenderApp, RenderPlugin, + }, + window::PresentMode, +}; +use xr_api::prelude::*; + +pub const LEFT_XR_TEXTURE_HANDLE: ManualTextureViewHandle = ManualTextureViewHandle(1208214591); +pub const RIGHT_XR_TEXTURE_HANDLE: ManualTextureViewHandle = ManualTextureViewHandle(3383858418); + +pub struct XrPlugin; + +impl Plugin for XrPlugin { + fn build(&self, app: &mut App) { + let instance = Entry::new() + .create_instance(ExtensionSet { vulkan: true }) + .unwrap(); + let session = instance + .create_session(SessionCreateInfo { + texture_format: wgpu::TextureFormat::Rgba8UnormSrgb, + }) + .unwrap(); + + let (device, queue, adapter_info, adapter, instance) = + session.get_render_resources().unwrap(); + + app.insert_non_send_resource(session.clone()); + app.add_plugins(RenderPlugin { + render_creation: bevy::render::settings::RenderCreation::Manual( + device.into(), + RenderQueue(Arc::new(queue)), + RenderAdapterInfo(adapter_info), + RenderAdapter(Arc::new(adapter)), + RenderInstance(Arc::new(instance)), + ), + }); + + app.add_systems(Last, begin_frame); + let render_app = app.sub_app_mut(RenderApp); + render_app.insert_non_send_resource(session); + render_app.add_systems(Render, end_frame.after(render_system)); + } +} + +pub fn begin_frame( + session: NonSend, + mut manual_texture_views: ResMut, +) { + let (left, right) = session.begin_frame().unwrap(); + + let left = ManualTextureView { + texture_view: left.texture_view().unwrap().into(), + size: left.resolution(), + format: left.format(), + }; + let right = ManualTextureView { + texture_view: right.texture_view().unwrap().into(), + size: right.resolution(), + format: right.format(), + }; + + manual_texture_views.insert(LEFT_XR_TEXTURE_HANDLE, left); + manual_texture_views.insert(RIGHT_XR_TEXTURE_HANDLE, right); +} + +pub fn end_frame(session: NonSend) { + session.end_frame().unwrap(); +} + +pub struct DefaultXrPlugins; + +impl PluginGroup for DefaultXrPlugins { + fn build(self) -> PluginGroupBuilder { + DefaultPlugins + .build() + .disable::() + .disable::() + .add_before::(XrPlugin) + .set(WindowPlugin { + #[cfg(not(target_os = "android"))] + primary_window: Some(Window { + transparent: true, + present_mode: PresentMode::AutoNoVsync, + ..default() + }), + #[cfg(target_os = "android")] + primary_window: None, + #[cfg(target_os = "android")] + exit_condition: bevy::window::ExitCondition::DontExit, + #[cfg(target_os = "android")] + close_when_requested: true, + ..default() + }) + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..26c892e --- /dev/null +++ b/src/main.rs @@ -0,0 +1,58 @@ +//! A simple 3D scene with light shining over a cube sitting on a plane. + +use bevy::{ + core_pipeline::clear_color::ClearColorConfig, prelude::*, render::camera::RenderTarget, +}; +use bevy_oxr::{DefaultXrPlugins, LEFT_XR_TEXTURE_HANDLE}; + +fn main() { + App::new() + .add_plugins(DefaultXrPlugins) + .add_systems(Startup, setup) + .run(); +} + +/// set up a simple 3D scene +fn setup( + mut commands: Commands, + mut meshes: ResMut>, + mut materials: ResMut>, +) { + // circular base + commands.spawn(PbrBundle { + mesh: meshes.add(shape::Circle::new(4.0).into()), + material: materials.add(Color::WHITE.into()), + transform: Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)), + ..default() + }); + // cube + commands.spawn(PbrBundle { + mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })), + material: materials.add(Color::rgb_u8(124, 144, 255).into()), + transform: Transform::from_xyz(0.0, 0.5, 0.0), + ..default() + }); + // light + commands.spawn(PointLightBundle { + point_light: PointLight { + intensity: 1500.0, + shadows_enabled: true, + ..default() + }, + transform: Transform::from_xyz(4.0, 8.0, 4.0), + ..default() + }); + // camera + commands.spawn(Camera3dBundle { + transform: Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y), + camera: Camera { + target: RenderTarget::TextureView(LEFT_XR_TEXTURE_HANDLE), + ..default() + }, + camera_3d: Camera3d { + clear_color: ClearColorConfig::Custom(Color::RED), + ..default() + }, + ..default() + }); +} diff --git a/xr_api/Cargo.toml b/xr_api/Cargo.toml index 89df672..d5ca4e8 100644 --- a/xr_api/Cargo.toml +++ b/xr_api/Cargo.toml @@ -10,11 +10,11 @@ linked = ["openxr/linked"] [dependencies] ash = "0.37.3" futures = "0.3.29" -glam = "0.25.0" +glam = "0.24.1" thiserror = "1.0.51" tracing = "0.1.40" -wgpu = "0.18" -wgpu-hal = "0.18" +wgpu = "0.17.1" +wgpu-hal = "0.17.1" [target.'cfg(not(target_family = "wasm"))'.dependencies] openxr = "0.17.1" diff --git a/xr_api/src/api_traits.rs b/xr_api/src/api_traits.rs index 63ef9e8..ee4d3ff 100644 --- a/xr_api/src/api_traits.rs +++ b/xr_api/src/api_traits.rs @@ -1,3 +1,4 @@ +use glam::UVec2; use wgpu::{Adapter, AdapterInfo, Device, Queue, TextureView}; use crate::prelude::*; @@ -30,15 +31,23 @@ pub trait SessionTrait { fn begin_frame(&self) -> Result<(View, View)>; /// Submits rendering work for this frame. fn end_frame(&self) -> Result<()>; + /// Gets the resolution of a single eye. + fn resolution(&self) -> UVec2; + /// Gets the texture format for the session. + fn format(&self) -> wgpu::TextureFormat; } pub trait ViewTrait { /// Returns the [TextureView] used to render this view. - fn texture_view(&self) -> TextureView; + fn texture_view(&self) -> Option; /// Returns the [Pose] representing the current position of this view. fn pose(&self) -> Pose; /// Returns the projection matrix for the current view. fn projection_matrix(&self) -> glam::Mat4; + /// Gets the resolution for this view. + fn resolution(&self) -> UVec2; + /// Gets the texture format for the view. + fn format(&self) -> wgpu::TextureFormat; } pub trait InputTrait { diff --git a/xr_api/src/backend/oxr.rs b/xr_api/src/backend/oxr.rs index e253414..058aa61 100644 --- a/xr_api/src/backend/oxr.rs +++ b/xr_api/src/backend/oxr.rs @@ -92,6 +92,7 @@ pub struct OXrSession { pub(crate) head: openxr::Space, pub(crate) resolution: UVec2, pub(crate) blend_mode: EnvironmentBlendMode, + pub(crate) format: wgpu::TextureFormat, } impl SessionTrait for OXrSession { @@ -164,6 +165,15 @@ impl SessionTrait for OXrSession { let _span = info_span!("xr_begin_frame").entered(); self.swapchain.begin().unwrap() } + + { + let _span = info_span!("xr_acquire_image").entered(); + self.swapchain.acquire_image().unwrap() + } + { + let _span = info_span!("xr_wait_image").entered(); + self.swapchain.wait_image().unwrap(); + } let views = { let _span = info_span!("xr_locate_views").entered(); self.session @@ -175,27 +185,21 @@ impl SessionTrait for OXrSession { .unwrap() .1 }; - *self.views.lock().unwrap() = [views[0].clone(), views[1].clone()]; - - { - let _span = info_span!("xr_acquire_image").entered(); - self.swapchain.acquire_image().unwrap() - } - { - let _span = info_span!("xr_wait_image").entered(); - self.swapchain.wait_image().unwrap(); - } { let _span = info_span!("xr_update_manual_texture_views").entered(); let (left, right) = self.swapchain.get_render_views(); let left = OXrView { texture: Mutex::new(Some(left)), view: views[0], + resolution: self.resolution, + format: self.format, }; let right = OXrView { texture: Mutex::new(Some(right)), view: views[1], + resolution: self.resolution, + format: self.format, }; Ok((left.into(), right.into())) } @@ -208,12 +212,14 @@ impl SessionTrait for OXrSession { } { let _span = info_span!("xr_end_frame").entered(); + let frame_state = self.frame_state.lock().unwrap().clone(); let result = self.swapchain.end( - self.frame_state.lock().unwrap().predicted_display_time, + frame_state.predicted_display_time, &*self.views.lock().unwrap(), &self.stage, self.resolution, self.blend_mode, + frame_state.should_render, // passthrough_layer.map(|p| p.into_inner()), ); match result { @@ -223,16 +229,26 @@ impl SessionTrait for OXrSession { } Ok(()) } + + fn resolution(&self) -> UVec2 { + self.resolution + } + + fn format(&self) -> wgpu::TextureFormat { + self.format + } } pub struct OXrView { texture: Mutex>, view: openxr::View, + resolution: UVec2, + format: wgpu::TextureFormat, } impl ViewTrait for OXrView { - fn texture_view(&self) -> wgpu::TextureView { - std::mem::take(&mut *self.texture.lock().unwrap()).unwrap() + fn texture_view(&self) -> Option { + std::mem::take(&mut *self.texture.lock().unwrap()) } fn pose(&self) -> Pose { @@ -336,8 +352,34 @@ impl ViewTrait for OXrView { Mat4::from_cols_array(&cols) } + + fn resolution(&self) -> UVec2 { + self.resolution + } + + fn format(&self) -> wgpu::TextureFormat { + self.format + } } pub struct OXrInput { action_set: openxr::ActionSet, } + +impl InputTrait for OXrInput { + fn get_haptics(&self, path: ActionPath) -> Result> { + todo!() + } + + fn get_pose(&self, path: ActionPath) -> Result> { + todo!() + } + + fn get_float(&self, path: ActionPath) -> Result> { + todo!() + } + + fn get_bool(&self, path: ActionPath) -> Result> { + todo!() + } +} diff --git a/xr_api/src/backend/oxr/graphics.rs b/xr_api/src/backend/oxr/graphics.rs index 2d82c1d..47f3cdf 100644 --- a/xr_api/src/backend/oxr/graphics.rs +++ b/xr_api/src/backend/oxr/graphics.rs @@ -65,6 +65,7 @@ impl Swapchain { stage: &openxr::Space, resolution: UVec2, environment_blend_mode: openxr::EnvironmentBlendMode, + should_render: bool, ) -> Result<()> { Ok(match self { Swapchain::Vulkan(swapchain) => swapchain.end( @@ -73,6 +74,7 @@ impl Swapchain { stage, resolution, environment_blend_mode, + should_render, )?, }) } @@ -132,6 +134,7 @@ impl SwapchainInner { stage: &openxr::Space, resolution: UVec2, environment_blend_mode: openxr::EnvironmentBlendMode, + should_render: bool, ) -> openxr::Result<()> { let rect = openxr::Rect2Di { offset: openxr::Offset2Di { x: 0, y: 0 }, @@ -145,31 +148,36 @@ impl SwapchainInner { warn!("views are len of 0"); return Ok(()); } - self.stream.lock().unwrap().end( - predicted_display_time, - environment_blend_mode, - &[&openxr::CompositionLayerProjection::new() - .space(stage) - .views(&[ - openxr::CompositionLayerProjectionView::new() - .pose(views[0].pose) - .fov(views[0].fov) - .sub_image( - openxr::SwapchainSubImage::new() - .swapchain(&swapchain) - .image_array_index(0) - .image_rect(rect), - ), - openxr::CompositionLayerProjectionView::new() - .pose(views[1].pose) - .fov(views[1].fov) - .sub_image( - openxr::SwapchainSubImage::new() - .swapchain(&swapchain) - .image_array_index(1) - .image_rect(rect), - ), - ])], - ) + let mut stream = self.stream.lock().unwrap(); + if true { + stream.end( + predicted_display_time, + environment_blend_mode, + &[&openxr::CompositionLayerProjection::new() + .space(stage) + .views(&[ + openxr::CompositionLayerProjectionView::new() + .pose(views[0].pose) + .fov(views[0].fov) + .sub_image( + openxr::SwapchainSubImage::new() + .swapchain(&swapchain) + .image_array_index(0) + .image_rect(rect), + ), + openxr::CompositionLayerProjectionView::new() + .pose(views[1].pose) + .fov(views[1].fov) + .sub_image( + openxr::SwapchainSubImage::new() + .swapchain(&swapchain) + .image_array_index(1) + .image_rect(rect), + ), + ])], + ) + } else { + stream.end(predicted_display_time, environment_blend_mode, &[]) + } } } diff --git a/xr_api/src/backend/oxr/graphics/vulkan.rs b/xr_api/src/backend/oxr/graphics/vulkan.rs index 149df16..6dd786c 100644 --- a/xr_api/src/backend/oxr/graphics/vulkan.rs +++ b/xr_api/src/backend/oxr/graphics/vulkan.rs @@ -36,8 +36,8 @@ pub fn init_oxr_graphics( } let vk_entry = unsafe { ash::Entry::load() }.map_err(|_| XrError::Placeholder)?; - let flags = wgpu::InstanceFlags::empty(); - let extensions = ::Instance::desired_extensions(&vk_entry, vk_target_version, flags) + let flags = wgpu_hal::InstanceFlags::empty(); + let extensions = ::Instance::required_extensions(&vk_entry, vk_target_version, flags) .map_err(|_| XrError::Placeholder)?; let device_extensions = vec![ ash::extensions::khr::Swapchain::name(), @@ -317,6 +317,7 @@ pub fn init_oxr_graphics( .create_reference_space(openxr::ReferenceSpaceType::STAGE, openxr::Posef::IDENTITY)?, head: session .create_reference_space(openxr::ReferenceSpaceType::VIEW, openxr::Posef::IDENTITY)?, + format: swapchain_format, }) } @@ -356,7 +357,7 @@ fn wgpu_to_vulkan(format: wgpu::TextureFormat) -> Option { Tf::Bgra8Unorm => F::B8G8R8A8_UNORM, Tf::Rgba8Uint => F::R8G8B8A8_UINT, Tf::Rgba8Sint => F::R8G8B8A8_SINT, - Tf::Rgb10a2Uint => F::A2B10G10R10_UINT_PACK32, + // Tf::Rgb10a2Uint => F::A2B10G10R10_UINT_PACK32, Tf::Rgb10a2Unorm => F::A2B10G10R10_UNORM_PACK32, Tf::Rg11b10Float => F::B10G11R11_UFLOAT_PACK32, Tf::Rg32Uint => F::R32G32_UINT, diff --git a/xr_api/src/error.rs b/xr_api/src/error.rs index dc87e98..696194e 100644 --- a/xr_api/src/error.rs +++ b/xr_api/src/error.rs @@ -11,6 +11,6 @@ pub enum XrError { impl Display for XrError { fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - todo!() + Ok(()) } }