diff --git a/crates/bevy_openxr/examples/android/src/lib.rs b/crates/bevy_openxr/examples/android/src/lib.rs index ad5ac98..9866566 100644 --- a/crates/bevy_openxr/examples/android/src/lib.rs +++ b/crates/bevy_openxr/examples/android/src/lib.rs @@ -37,17 +37,21 @@ fn setup( mut meshes: ResMut>, mut materials: ResMut>, ) { + let mut white: StandardMaterial = Color::WHITE.into(); + white.unlit = true; // circular base commands.spawn(PbrBundle { mesh: meshes.add(Circle::new(4.0)), - material: materials.add(Color::WHITE), + material: materials.add(white), transform: Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)), ..default() }); + let mut cube_mat: StandardMaterial = Color::rgb_u8(124, 144, 255).into(); + cube_mat.unlit = true; // cube commands.spawn(PbrBundle { mesh: meshes.add(Cuboid::new(1.0, 1.0, 1.0)), - material: materials.add(Color::rgb_u8(124, 144, 255)), + material: materials.add(cube_mat), transform: Transform::from_xyz(0.0, 0.5, 0.0), ..default() }); diff --git a/crates/bevy_openxr/src/openxr/render.rs b/crates/bevy_openxr/src/openxr/render.rs index a4daa6e..f4baea6 100644 --- a/crates/bevy_openxr/src/openxr/render.rs +++ b/crates/bevy_openxr/src/openxr/render.rs @@ -1,13 +1,15 @@ use bevy::{ - ecs::query::QuerySingleError, + app::{MainScheduleOrder, SubApp}, + ecs::{query::QuerySingleError, schedule::MainThreadExecutor}, prelude::*, render::{ camera::{ManualTextureView, ManualTextureViewHandle, ManualTextureViews, RenderTarget}, extract_resource::ExtractResourcePlugin, - pipelined_rendering::PipelinedRenderingPlugin, + pipelined_rendering::{PipelinedRenderingPlugin, RenderAppChannels, RenderExtractApp}, view::ExtractedView, Render, RenderApp, RenderSet, }, + tasks::ComputeTaskPool, }; use bevy_xr::camera::{XrCamera, XrCameraBundle, XrProjection}; use openxr::ViewStateFlags; @@ -30,6 +32,20 @@ impl Plugin for OxrRenderPlugin { fn build(&self, app: &mut App) { if app.is_plugin_added::() { app.init_resource::(); + + let mut schedule_order = app.world.resource_mut::(); + + if let Some(pos) = schedule_order + .labels + .iter() + .position(|label| (**label).eq(&OxrLast)) + { + schedule_order.labels.remove(pos); + } + + if let Some(sub_app) = app.remove_sub_app(RenderExtractApp) { + app.insert_sub_app(RenderExtractApp, SubApp::new(sub_app.app, update_rendering)); + } } app.add_plugins(( @@ -138,6 +154,31 @@ impl Plugin for OxrRenderPlugin { } } +// This function waits for the rendering world to be received, +// runs extract, and then sends the rendering world back to the render thread. +// +// modified pipelined rendering extract function +fn update_rendering(app_world: &mut World, _sub_app: &mut App) { + app_world.resource_scope(|world, main_thread_executor: Mut| { + world.resource_scope(|world, mut render_channels: Mut| { + // we use a scope here to run any main thread tasks that the render world still needs to run + // while we wait for the render world to be received. + let mut render_app = ComputeTaskPool::get() + .scope_with_executor(true, Some(&*main_thread_executor.0), |s| { + s.spawn(async { render_channels.recv().await }); + }) + .pop() + .unwrap(); + + world.run_schedule(OxrLast); + + render_app.extract(world); + + render_channels.send_blocking(render_app); + }); + }); +} + pub const XR_TEXTURE_INDEX: u32 = 3383858418; pub fn init_views(