From 086c964e82ed33b10d5ac0724396c95dcbd0bc45 Mon Sep 17 00:00:00 2001 From: awtterpip Date: Sat, 9 Sep 2023 23:27:12 -0500 Subject: [PATCH] improved performance --- examples/xr.rs | 8 +- src/graphics/mod.rs | 4 +- src/graphics/vulkan.rs | 24 +++-- src/lib.rs | 225 +++++++++++++++++++++++------------------ src/resources.rs | 105 ++++++++++--------- 5 files changed, 210 insertions(+), 156 deletions(-) diff --git a/examples/xr.rs b/examples/xr.rs index e00b36c..230103b 100644 --- a/examples/xr.rs +++ b/examples/xr.rs @@ -81,16 +81,17 @@ fn hands( frame_state: Res, xr_input: Res, ) { - frame_state.lock().unwrap().map(|a| { + let frame_state = *frame_state.lock().unwrap(); + let right_controller = oculus_controller .grip_space .right - .relate(&**&xr_input.stage, a.predicted_display_time) + .relate(&**&xr_input.stage, frame_state.predicted_display_time) .unwrap(); let left_controller = oculus_controller .grip_space .left - .relate(&**&xr_input.stage, a.predicted_display_time) + .relate(&**&xr_input.stage, frame_state.predicted_display_time) .unwrap(); gizmos.rect( right_controller.0.pose.position.to_vec3(), @@ -104,5 +105,4 @@ fn hands( Vec2::new(0.05, 0.2), Color::YELLOW_GREEN, ); - }); } diff --git a/src/graphics/mod.rs b/src/graphics/mod.rs index cc9cedd..23c5b3e 100644 --- a/src/graphics/mod.rs +++ b/src/graphics/mod.rs @@ -7,7 +7,7 @@ use wgpu::Instance; use crate::input::XrInput; use crate::resources::{ XrEnvironmentBlendMode, XrFrameState, XrFrameWaiter, XrInstance, XrSession, XrSessionRunning, - XrSwapchain, XrViews, + XrSwapchain, XrViews, XrResolution, XrFormat, }; pub fn initialize_xr_graphics( @@ -21,6 +21,8 @@ pub fn initialize_xr_graphics( XrInstance, XrSession, XrEnvironmentBlendMode, + XrResolution, + XrFormat, XrSessionRunning, XrFrameWaiter, XrSwapchain, diff --git a/src/graphics/vulkan.rs b/src/graphics/vulkan.rs index bfd1cf4..f247e84 100644 --- a/src/graphics/vulkan.rs +++ b/src/graphics/vulkan.rs @@ -14,7 +14,7 @@ use wgpu::{Instance, Texture}; use crate::input::XrInput; use crate::resources::{ Swapchain, SwapchainInner, XrEnvironmentBlendMode, XrFrameState, XrFrameWaiter, XrInstance, - XrSession, XrSessionRunning, XrSwapchain, XrViews, + XrSession, XrSessionRunning, XrSwapchain, XrViews, XrResolution, XrFormat, }; use crate::VIEW_TYPE; @@ -29,6 +29,8 @@ pub fn initialize_xr_graphics( XrInstance, XrSession, XrEnvironmentBlendMode, + XrResolution, + XrFormat, XrSessionRunning, XrFrameWaiter, XrSwapchain, @@ -367,20 +369,24 @@ pub fn initialize_xr_graphics( xr_instance.clone().into(), session.clone().into_any_graphics().into(), blend_mode.into(), + resolution.into(), + swapchain_format.into(), AtomicBool::new(false).into(), Mutex::new(frame_wait).into(), - Mutex::new(Swapchain::Vulkan(SwapchainInner { - stream: frame_stream, - handle, - resolution, - format: swapchain_format, + Swapchain::Vulkan(SwapchainInner { + stream: Mutex::new(frame_stream), + handle: Mutex::new(handle), buffers, - image_index: 0, - })) + image_index: Mutex::new(0), + }) .into(), XrInput::new(xr_instance, session.into_any_graphics())?, Mutex::default().into(), - Mutex::default().into(), + Mutex::new(xr::FrameState { + predicted_display_time: xr::Time::from_nanos(1), + predicted_display_period: xr::Duration::from_nanos(1), + should_render: true, + }).into(), )) } diff --git a/src/lib.rs b/src/lib.rs index 424fb85..38b0495 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,7 +11,10 @@ use bevy::app::PluginGroupBuilder; use bevy::ecs::system::SystemState; use bevy::prelude::*; use bevy::render::camera::{ManualTextureView, ManualTextureViewHandle, ManualTextureViews}; -use bevy::render::renderer::{RenderAdapter, RenderAdapterInfo, RenderDevice, RenderQueue}; +use bevy::render::pipelined_rendering::RenderExtractApp; +use bevy::render::renderer::{ + render_system, RenderAdapter, RenderAdapterInfo, RenderDevice, RenderQueue, +}; use bevy::render::settings::RenderSettings; use bevy::render::{Render, RenderApp, RenderPlugin, RenderSet}; use bevy::window::{PrimaryWindow, RawHandleWrapper}; @@ -37,6 +40,8 @@ pub struct FutureXrResources( XrInstance, XrSession, XrEnvironmentBlendMode, + XrResolution, + XrFormat, XrSessionRunning, XrFrameWaiter, XrSwapchain, @@ -66,6 +71,8 @@ impl Plugin for OpenXrPlugin { xr_instance, session, blend_mode, + resolution, + format, session_running, frame_waiter, swapchain, @@ -80,6 +87,8 @@ impl Plugin for OpenXrPlugin { xr_instance, session, blend_mode, + resolution, + format, session_running, frame_waiter, swapchain, @@ -112,6 +121,8 @@ impl Plugin for OpenXrPlugin { xr_instance, session, blend_mode, + resolution, + format, session_running, frame_waiter, swapchain, @@ -125,6 +136,8 @@ impl Plugin for OpenXrPlugin { app.insert_resource(xr_instance.clone()) .insert_resource(session.clone()) .insert_resource(blend_mode.clone()) + .insert_resource(resolution.clone()) + .insert_resource(format.clone()) .insert_resource(session_running.clone()) .insert_resource(frame_waiter.clone()) .insert_resource(swapchain.clone()) @@ -133,30 +146,44 @@ impl Plugin for OpenXrPlugin { .insert_resource(frame_state.clone()) .insert_resource(action_sets.clone()); - let swapchain_mut = swapchain.lock().unwrap(); - let (left, right) = swapchain_mut.get_render_views(); - let format = swapchain_mut.format(); + let (left, right) = swapchain.get_render_views(); let left = ManualTextureView { texture_view: left.into(), - size: swapchain_mut.resolution(), - format, + size: *resolution, + format: *format, }; let right = ManualTextureView { texture_view: right.into(), - size: swapchain_mut.resolution(), - format, + size: *resolution, + format: *format, }; let mut manual_texture_views = app.world.resource_mut::(); manual_texture_views.insert(LEFT_XR_TEXTURE_HANDLE, left); manual_texture_views.insert(RIGHT_XR_TEXTURE_HANDLE, right); drop(manual_texture_views); - drop(swapchain_mut); + let pipeline_app = app.sub_app_mut(RenderExtractApp); + pipeline_app + .insert_resource(xr_instance.clone()) + .insert_resource(session.clone()) + .insert_resource(blend_mode.clone()) + .insert_resource(resolution.clone()) + .insert_resource(format.clone()) + .insert_resource(session_running.clone()) + .insert_resource(frame_waiter.clone()) + .insert_resource(swapchain.clone()) + .insert_resource(input.clone()) + .insert_resource(views.clone()) + .insert_resource(frame_state.clone()) + .insert_resource(action_sets.clone()); + drop(pipeline_app); let render_app = app.sub_app_mut(RenderApp); render_app .insert_resource(xr_instance) .insert_resource(session) .insert_resource(blend_mode) + .insert_resource(resolution) + .insert_resource(format) .insert_resource(session_running) .insert_resource(frame_waiter) .insert_resource(swapchain) @@ -168,9 +195,9 @@ impl Plugin for OpenXrPlugin { render_app.add_systems( Render, ( - pre_frame.in_set(RenderSet::Prepare).before(post_frame), - post_frame.in_set(RenderSet::Prepare), - post_queue_submit.in_set(RenderSet::Cleanup), + begin_frame.before(render_system).after(RenderSet::ExtractCommands), + locate_views.before(render_system), + end_frame.after(render_system), ), ); } @@ -187,116 +214,120 @@ impl PluginGroup for DefaultXrPlugins { } } -pub fn pre_frame( +pub fn begin_frame( instance: Res, session: Res, session_running: Res, - frame_state: Res, - frame_waiter: Res, + resolution: Res, + format: Res, swapchain: Res, - xr_input: Res, - action_sets: Res, + frame_waiter: Res, + frame_state: Res, mut manual_texture_views: ResMut, ) { - while let Some(event) = instance.poll_event(&mut Default::default()).unwrap() { - use xr::Event::*; - match event { - SessionStateChanged(e) => { - // Session state change is where we can begin and end sessions, as well as - // find quit messages! - info!("entered XR state {:?}", e.state()); - match e.state() { - xr::SessionState::READY => { - session.begin(VIEW_TYPE).unwrap(); - session_running.store(true, std::sync::atomic::Ordering::Relaxed); + { + let _span = info_span!("xr_poll_events"); + while let Some(event) = instance.poll_event(&mut Default::default()).unwrap() { + use xr::Event::*; + match event { + SessionStateChanged(e) => { + // Session state change is where we can begin and end sessions, as well as + // find quit messages! + info!("entered XR state {:?}", e.state()); + match e.state() { + xr::SessionState::READY => { + session.begin(VIEW_TYPE).unwrap(); + session_running.store(true, std::sync::atomic::Ordering::Relaxed); + } + xr::SessionState::STOPPING => { + session.end().unwrap(); + session_running.store(false, std::sync::atomic::Ordering::Relaxed); + } + xr::SessionState::EXITING | xr::SessionState::LOSS_PENDING => return, + _ => {} } - xr::SessionState::STOPPING => { - session.end().unwrap(); - session_running.store(false, std::sync::atomic::Ordering::Relaxed); - } - xr::SessionState::EXITING | xr::SessionState::LOSS_PENDING => return, - _ => {} } + InstanceLossPending(_) => return, + EventsLost(e) => { + warn!("lost {} XR events", e.lost_event_count()); + } + _ => {} } - InstanceLossPending(_) => return, - EventsLost(e) => { - warn!("lost {} XR events", e.lost_event_count()); - } - _ => {} } } - if !session_running.load(std::sync::atomic::Ordering::Relaxed) { - // Don't grind up the CPU - //std::thread::sleep(std::time::Duration::from_millis(10)); - return; + { + let _span = info_span!("xr_wait_frame").entered(); + *frame_state.lock().unwrap() = frame_waiter.lock().unwrap().wait().unwrap(); } - - *frame_state.lock().unwrap() = Some(frame_waiter.lock().unwrap().wait().unwrap()); - - let mut swapchain = swapchain.lock().unwrap(); - - swapchain.begin().unwrap(); - swapchain.update_render_views(); - let (left, right) = swapchain.get_render_views(); - /*let mut active_action_sets = vec![]; - for i in &action_sets.0 { - active_action_sets.push(xr::ActiveActionSet::new(i)); + { + let _span = info_span!("xr_begin_frame").entered(); + swapchain.begin().unwrap() + } + { + let _span = info_span!("xr_acquire_image").entered(); + swapchain.acquire_image().unwrap() + } + { + let _span = info_span!("xr_wait_image").entered(); + swapchain.wait_image().unwrap(); + } + { + let _span = info_span!("xr_update_manual_texture_views").entered(); + let (left, right) = swapchain.get_render_views(); + let left = ManualTextureView { + texture_view: left.into(), + size: **resolution, + format: **format, + }; + let right = ManualTextureView { + texture_view: right.into(), + size: **resolution, + format: **format, + }; + manual_texture_views.insert(LEFT_XR_TEXTURE_HANDLE, left); + manual_texture_views.insert(RIGHT_XR_TEXTURE_HANDLE, right); } - info!("action sets: {:#?}", action_sets.0.len()); - match session.sync_actions(&active_action_sets) { - Err(err) => { - warn!("{}", err); - } - _ => {} - }*/ - let format = swapchain.format(); - let left = ManualTextureView { - texture_view: left.into(), - size: swapchain.resolution(), - format, - }; - let right = ManualTextureView { - texture_view: right.into(), - size: swapchain.resolution(), - format, - }; - manual_texture_views.insert(LEFT_XR_TEXTURE_HANDLE, left); - manual_texture_views.insert(RIGHT_XR_TEXTURE_HANDLE, right); } -pub fn post_frame( +pub fn end_frame( + xr_frame_state: Res, + views: Res, + input: Res, + swapchain: Res, + resolution: Res, + environment_blend_mode: Res, +) { + { + let _span = info_span!("xr_release_image").entered(); + swapchain.release_image().unwrap(); + } + { + let _span = info_span!("xr_end_frame").entered(); + swapchain + .end( + xr_frame_state.lock().unwrap().predicted_display_time, + &*views.lock().unwrap(), + &input.stage, + **resolution, + **environment_blend_mode, + ) + .unwrap(); + } +} + +pub fn locate_views( views: Res, input: Res, session: Res, xr_frame_state: Res, ) { + let _span = info_span!("xr_locate_views").entered(); *views.lock().unwrap() = session .locate_views( VIEW_TYPE, - xr_frame_state - .lock() - .unwrap() - .unwrap() - .predicted_display_time, + xr_frame_state.lock().unwrap().predicted_display_time, &input.stage, ) .unwrap() .1; } - -pub fn post_queue_submit( - xr_frame_state: Res, - views: Res, - input: Res, - swapchain: Res, - environment_blend_mode: Res, -) { - let xr_frame_state = xr_frame_state.lock().unwrap().unwrap(); - let views = &*views.lock().unwrap(); - let stage = &input.stage; - swapchain - .lock() - .unwrap() - .post_queue_submit(xr_frame_state, views, stage, **environment_blend_mode) - .unwrap(); -} diff --git a/src/resources.rs b/src/resources.rs index 371ff45..e7913b6 100644 --- a/src/resources.rs +++ b/src/resources.rs @@ -8,11 +8,12 @@ use openxr as xr; xr_resource_wrapper!(XrInstance, xr::Instance); xr_resource_wrapper!(XrSession, xr::Session); xr_resource_wrapper!(XrEnvironmentBlendMode, xr::EnvironmentBlendMode); -xr_resource_wrapper!(XrViewConfigurationViews, Vec); +xr_resource_wrapper!(XrResolution, UVec2); +xr_resource_wrapper!(XrFormat, wgpu::TextureFormat); xr_arc_resource_wrapper!(XrSessionRunning, AtomicBool); xr_arc_resource_wrapper!(XrFrameWaiter, Mutex); -xr_arc_resource_wrapper!(XrSwapchain, Mutex); -xr_arc_resource_wrapper!(XrFrameState, Mutex>); +xr_arc_resource_wrapper!(XrSwapchain, Swapchain); +xr_arc_resource_wrapper!(XrFrameState, Mutex); xr_arc_resource_wrapper!(XrViews, Mutex>); pub enum Swapchain { @@ -20,67 +21,70 @@ pub enum Swapchain { } impl Swapchain { - pub(crate) fn begin(&mut self) -> xr::Result<()> { + pub(crate) fn begin(&self) -> xr::Result<()> { match self { - Swapchain::Vulkan(swap) => swap.begin(), - } - } - - pub(crate) fn update_render_views(&mut self) { - match self { - Swapchain::Vulkan(swap) => swap.update_render_views(), + Swapchain::Vulkan(swapchain) => swapchain.begin(), } } pub(crate) fn get_render_views(&self) -> (wgpu::TextureView, wgpu::TextureView) { match self { - Swapchain::Vulkan(swap) => swap.get_render_views(), + Swapchain::Vulkan(swapchain) => swapchain.get_render_views(), } } - pub(crate) fn format(&self) -> wgpu::TextureFormat { + pub(crate) fn acquire_image(&self) -> xr::Result<()> { match self { - Swapchain::Vulkan(swap) => swap.format, + Swapchain::Vulkan(swapchain) => swapchain.acquire_image(), } } - pub(crate) fn resolution(&self) -> UVec2 { + pub(crate) fn wait_image(&self) -> xr::Result<()> { match self { - Swapchain::Vulkan(swap) => swap.resolution, + Swapchain::Vulkan(swapchain) => swapchain.wait_image(), } } - pub(crate) fn post_queue_submit( - &mut self, - xr_frame_state: xr::FrameState, + pub(crate) fn release_image(&self) -> xr::Result<()> { + match self { + Swapchain::Vulkan(swapchain) => swapchain.release_image(), + } + } + + pub(crate) fn end( + &self, + predicted_display_time: xr::Time, views: &[openxr::View], stage: &xr::Space, + resolution: UVec2, environment_blend_mode: xr::EnvironmentBlendMode, ) -> xr::Result<()> { match self { - Swapchain::Vulkan(swap) => { - swap.post_queue_submit(xr_frame_state, views, stage, environment_blend_mode) - } + Swapchain::Vulkan(swapchain) => swapchain.end( + predicted_display_time, + views, + stage, + resolution, + environment_blend_mode, + ), } } } pub struct SwapchainInner { - pub(crate) stream: xr::FrameStream, - pub(crate) handle: xr::Swapchain, - pub(crate) resolution: UVec2, - pub(crate) format: wgpu::TextureFormat, + pub(crate) stream: Mutex>, + pub(crate) handle: Mutex>, pub(crate) buffers: Vec, - pub(crate) image_index: usize, + pub(crate) image_index: Mutex, } impl SwapchainInner { - fn begin(&mut self) -> xr::Result<()> { - self.stream.begin() + fn begin(&self) -> xr::Result<()> { + self.stream.lock().unwrap().begin() } fn get_render_views(&self) -> (wgpu::TextureView, wgpu::TextureView) { - let texture = &self.buffers[self.image_index]; + let texture = &self.buffers[*self.image_index.lock().unwrap()]; ( texture.create_view(&wgpu::TextureViewDescriptor { @@ -97,30 +101,41 @@ impl SwapchainInner { ) } - fn update_render_views(&mut self) { - let image_index = self.handle.acquire_image().unwrap(); - self.handle.wait_image(xr::Duration::INFINITE).unwrap(); - - self.image_index = image_index as _; + fn acquire_image(&self) -> xr::Result<()> { + let image_index = self.handle.lock().unwrap().acquire_image()?; + *self.image_index.lock().unwrap() = image_index as _; + Ok(()) } - fn post_queue_submit( - &mut self, - xr_frame_state: xr::FrameState, + fn wait_image(&self) -> xr::Result<()> { + self.handle + .lock() + .unwrap() + .wait_image(xr::Duration::INFINITE) + } + + fn release_image(&self) -> xr::Result<()> { + self.handle.lock().unwrap().release_image() + } + + fn end( + &self, + predicted_display_time: xr::Time, views: &[openxr::View], stage: &xr::Space, + resolution: UVec2, environment_blend_mode: xr::EnvironmentBlendMode, ) -> xr::Result<()> { - self.handle.release_image().unwrap(); let rect = xr::Rect2Di { offset: xr::Offset2Di { x: 0, y: 0 }, extent: xr::Extent2Di { - width: self.resolution.x as _, - height: self.resolution.y as _, + width: resolution.x as _, + height: resolution.y as _, }, }; - self.stream.end( - xr_frame_state.predicted_display_time, + let swapchain = self.handle.lock().unwrap(); + self.stream.lock().unwrap().end( + predicted_display_time, environment_blend_mode, &[&xr::CompositionLayerProjection::new().space(stage).views(&[ xr::CompositionLayerProjectionView::new() @@ -128,7 +143,7 @@ impl SwapchainInner { .fov(views[0].fov) .sub_image( xr::SwapchainSubImage::new() - .swapchain(&self.handle) + .swapchain(&swapchain) .image_array_index(0) .image_rect(rect), ), @@ -137,7 +152,7 @@ impl SwapchainInner { .fov(views[1].fov) .sub_image( xr::SwapchainSubImage::new() - .swapchain(&self.handle) + .swapchain(&swapchain) .image_array_index(1) .image_rect(rect), ),