feat: impl Pipelined Rendering

Signed-off-by: Schmarni <marnistromer@gmail.com>
This commit is contained in:
Schmarni
2025-10-21 00:09:17 +02:00
parent 08cec3c700
commit 05d4670609
8 changed files with 50 additions and 27 deletions

17
Cargo.lock generated
View File

@@ -1242,8 +1242,7 @@ dependencies = [
[[package]] [[package]]
name = "bevy_render" name = "bevy_render"
version = "0.16.1" version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "git+https://github.com/Schmarni-Dev/bevy?branch=render_thread_init_callback#2ac1d069738b047d172195c1be990ee29c64a0b2"
checksum = "ef91fed1f09405769214b99ebe4390d69c1af5cdd27967deae9135c550eb1667"
dependencies = [ dependencies = [
"async-channel", "async-channel",
"bevy_app", "bevy_app",
@@ -2962,7 +2961,7 @@ dependencies = [
"log", "log",
"presser", "presser",
"thiserror 1.0.69", "thiserror 1.0.69",
"windows 0.58.0", "windows 0.54.0",
] ]
[[package]] [[package]]
@@ -3501,7 +3500,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"windows-targets 0.48.5", "windows-targets 0.53.2",
] ]
[[package]] [[package]]
@@ -4042,7 +4041,7 @@ version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d" checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d"
dependencies = [ dependencies = [
"proc-macro-crate 3.3.0", "proc-macro-crate 1.3.1",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.104", "syn 2.0.104",
@@ -5114,7 +5113,7 @@ dependencies = [
"errno", "errno",
"libc", "libc",
"linux-raw-sys 0.4.15", "linux-raw-sys 0.4.15",
"windows-sys 0.59.0", "windows-sys 0.52.0",
] ]
[[package]] [[package]]
@@ -5743,7 +5742,7 @@ dependencies = [
"getrandom 0.3.3", "getrandom 0.3.3",
"once_cell", "once_cell",
"rustix 1.1.2", "rustix 1.1.2",
"windows-sys 0.59.0", "windows-sys 0.52.0",
] ]
[[package]] [[package]]
@@ -6190,7 +6189,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69fff37da548239c3bf9e64a12193d261e8b22b660991c6fd2df057c168f435f" checksum = "69fff37da548239c3bf9e64a12193d261e8b22b660991c6fd2df057c168f435f"
dependencies = [ dependencies = [
"cc", "cc",
"windows-targets 0.48.5", "windows-targets 0.52.6",
] ]
[[package]] [[package]]
@@ -6791,7 +6790,7 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
dependencies = [ dependencies = [
"windows-sys 0.59.0", "windows-sys 0.52.0",
] ]
[[package]] [[package]]

View File

@@ -71,6 +71,7 @@ naga = { git = "https://github.com/Schmarni-Dev/wgpu", branch = "bad_dmabuf_work
wgpu-hal = { git = "https://github.com/Schmarni-Dev/wgpu", branch = "bad_dmabuf_workaround" } wgpu-hal = { git = "https://github.com/Schmarni-Dev/wgpu", branch = "bad_dmabuf_workaround" }
bevy_pbr = { git = "https://github.com/Schmarni-Dev/bevy", branch = "premul_oit_016" } bevy_pbr = { git = "https://github.com/Schmarni-Dev/bevy", branch = "premul_oit_016" }
bevy_core_pipeline = { git = "https://github.com/Schmarni-Dev/bevy", branch = "premul_oit_016" } bevy_core_pipeline = { git = "https://github.com/Schmarni-Dev/bevy", branch = "premul_oit_016" }
bevy_render = { git = "https://github.com/Schmarni-Dev/bevy", branch = "render_thread_init_callback" }
[dependencies] [dependencies]
# small utility thingys # small utility thingys

View File

@@ -29,6 +29,9 @@ use bevy::gizmos::GizmoPlugin;
use bevy::gltf::GltfPlugin; use bevy::gltf::GltfPlugin;
use bevy::input::InputPlugin; use bevy::input::InputPlugin;
use bevy::pbr::PbrPlugin; use bevy::pbr::PbrPlugin;
use bevy::render::pipelined_rendering::{
PipelinedRenderThreadOnCreateCallback, PipelinedRenderingPlugin,
};
use bevy::render::settings::{Backends, RenderCreation, WgpuSettings}; use bevy::render::settings::{Backends, RenderCreation, WgpuSettings};
use bevy::render::{RenderDebugFlags, RenderPlugin}; use bevy::render::{RenderDebugFlags, RenderPlugin};
use bevy::scene::ScenePlugin; use bevy::scene::ScenePlugin;
@@ -335,6 +338,9 @@ fn bevy_loop(
false => plugins.add(FlatscreenInputPlugin), false => plugins.add(FlatscreenInputPlugin),
}; };
} }
app.insert_resource(PipelinedRenderThreadOnCreateCallback(
enter_runtime_context.clone(),
));
app.add_plugins( app.add_plugins(
if !args.force_flatscreen { if !args.force_flatscreen {
add_xr_plugins(plugins) add_xr_plugins(plugins)
@@ -386,6 +392,7 @@ fn bevy_loop(
..default() ..default()
}), }),
); );
app.add_plugins(PipelinedRenderingPlugin);
app.add_plugins(bevy_sk::hand::HandPlugin); app.add_plugins(bevy_sk::hand::HandPlugin);
app.add_plugins(bevy_equirect::EquirectangularPlugin); app.add_plugins(bevy_equirect::EquirectangularPlugin);
@@ -506,3 +513,13 @@ fn xr_step(world: &mut World) {
tick_internal_client(); tick_internal_client();
} }
pub fn get_time(pipelined: bool, state: &OxrFrameState) -> openxr::Time {
if pipelined {
openxr::Time::from_nanos(
state.predicted_display_time.as_nanos() + state.predicted_display_period.as_nanos(),
)
} else {
state.predicted_display_time
}
}

View File

@@ -3,7 +3,7 @@ use std::sync::Arc;
use bevy::prelude::*; use bevy::prelude::*;
use bevy_mod_openxr::{ use bevy_mod_openxr::{
helper_traits::{ToQuat as _, ToVec3 as _}, helper_traits::{ToQuat as _, ToVec3 as _},
resources::OxrFrameState, resources::{OxrFrameState, Pipelined},
session::OxrSession, session::OxrSession,
}; };
use bevy_mod_xr::{ use bevy_mod_xr::{
@@ -12,7 +12,7 @@ use bevy_mod_xr::{
}; };
use openxr::SpaceLocationFlags; use openxr::SpaceLocationFlags;
use crate::{DbusConnection, PreFrameWait, nodes::spatial::Spatial}; use crate::{DbusConnection, PreFrameWait, get_time, nodes::spatial::Spatial};
use super::{ObjectHandle, SpatialRef, input::mouse_pointer::FlatscreenCam}; use super::{ObjectHandle, SpatialRef, input::mouse_pointer::FlatscreenCam};
@@ -68,6 +68,7 @@ fn update_xr(
ref_space: Option<Res<XrPrimaryReferenceSpace>>, ref_space: Option<Res<XrPrimaryReferenceSpace>>,
hmd: Res<Hmd>, hmd: Res<Hmd>,
state: Option<Res<OxrFrameState>>, state: Option<Res<OxrFrameState>>,
pipelined: Option<Res<Pipelined>>,
) { ) {
let (Some(session), Some(view), Some(ref_space), Some(state)) = let (Some(session), Some(view), Some(ref_space), Some(state)) =
(session, hmd.space, ref_space, state) (session, hmd.space, ref_space, state)
@@ -80,9 +81,9 @@ fn update_xr(
// }); // });
return; return;
}; };
// this won't be correct with pipelined rendering let time = get_time(pipelined.is_some(), &state);
let location = session let location = session
.locate_space(&view, &ref_space, state.predicted_display_time) .locate_space(&view, &ref_space, time)
.inspect_err(|err| error!("Error while Locating OpenXR Stage Space {err}")); .inspect_err(|err| error!("Error while Locating OpenXR Stage Space {err}"));
if let Ok(location) = location { if let Ok(location) = location {
let is_tracked = location let is_tracked = location

View File

@@ -2,6 +2,7 @@ use super::{CaptureManager, get_sorted_handlers};
use crate::{ use crate::{
DbusConnection, PreFrameWait, DbusConnection, PreFrameWait,
core::client::INTERNAL_CLIENT, core::client::INTERNAL_CLIENT,
get_time,
nodes::{ nodes::{
Node, OwnedNode, Node, OwnedNode,
drawable::{ drawable::{
@@ -19,7 +20,7 @@ use bevy::{math::Affine3, prelude::*};
use bevy_mod_openxr::{ use bevy_mod_openxr::{
action_binding::{OxrSendActionBindings, OxrSuggestActionBinding}, action_binding::{OxrSendActionBindings, OxrSuggestActionBinding},
helper_traits::{ToIsometry3d, ToVec2}, helper_traits::{ToIsometry3d, ToVec2},
resources::{OxrFrameState, OxrInstance}, resources::{OxrFrameState, OxrInstance, Pipelined},
session::OxrSession, session::OxrSession,
}; };
use bevy_mod_xr::{ use bevy_mod_xr::{
@@ -147,6 +148,7 @@ fn update(
session: Option<Res<OxrSession>>, session: Option<Res<OxrSession>>,
ref_space: Option<Res<XrPrimaryReferenceSpace>>, ref_space: Option<Res<XrPrimaryReferenceSpace>>,
state: Option<Res<OxrFrameState>>, state: Option<Res<OxrFrameState>>,
pipelined: Option<Res<Pipelined>>,
) { ) {
let (Some(session), Some(state), Some(ref_space)) = (session, state, ref_space) else { let (Some(session), Some(state), Some(ref_space)) = (session, state, ref_space) else {
controllers.left.set_enabled(false); controllers.left.set_enabled(false);
@@ -158,8 +160,7 @@ fn update(
.sync_actions(&[ActiveActionSet::new(&actions.set)]) .sync_actions(&[ActiveActionSet::new(&actions.set)])
.unwrap(); .unwrap();
}); });
let time = state.predicted_display_time; let time = get_time(pipelined.is_some(), &state);
// stupid bevy gltf loading issue (rotated 180 degrees on the y axis)
controllers controllers
.left .left
.update(&session, &actions, time, ref_space.0); .update(&session, &actions, time, ref_space.0);

View File

@@ -8,11 +8,11 @@ use crate::nodes::{
spatial::Spatial, spatial::Spatial,
}; };
use crate::objects::{AsyncTracked, ObjectHandle, SpatialRef, Tracked}; use crate::objects::{AsyncTracked, ObjectHandle, SpatialRef, Tracked};
use crate::{BevyMaterial, DbusConnection, ObjectRegistryRes, PreFrameWait}; use crate::{BevyMaterial, DbusConnection, ObjectRegistryRes, PreFrameWait, get_time};
use bevy::prelude::Transform as BevyTransform; use bevy::prelude::Transform as BevyTransform;
use bevy::prelude::*; use bevy::prelude::*;
use bevy_mod_openxr::helper_traits::{ToQuat, ToVec3}; use bevy_mod_openxr::helper_traits::{ToQuat, ToVec3};
use bevy_mod_openxr::resources::OxrFrameState; use bevy_mod_openxr::resources::{OxrFrameState, Pipelined};
use bevy_mod_openxr::session::OxrSession; use bevy_mod_openxr::session::OxrSession;
use bevy_mod_xr::hands::{HandBone, HandSide, XrHandBoneEntities, XrHandBoneRadius}; use bevy_mod_xr::hands::{HandBone, HandSide, XrHandBoneEntities, XrHandBoneRadius};
use bevy_mod_xr::session::{XrPreDestroySession, XrSessionCreated}; use bevy_mod_xr::session::{XrPreDestroySession, XrSessionCreated};
@@ -50,6 +50,7 @@ fn update_hands(
&mut XrHandBoneRadius, &mut XrHandBoneRadius,
)>, )>,
joints_query: Query<&XrHandBoneEntities>, joints_query: Query<&XrHandBoneEntities>,
pipelined: Option<Res<Pipelined>>,
) { ) {
let (Some(session), Some(state), Some(ref_space)) = (session, state, ref_space) else { let (Some(session), Some(state), Some(ref_space)) = (session, state, ref_space) else {
hands.left.tracked.set_tracked(false); hands.left.tracked.set_tracked(false);
@@ -62,9 +63,9 @@ fn update_hands(
hand.tracked.set_tracked(false); hand.tracked.set_tracked(false);
return None; return None;
}; };
// this won't be correct with pipelined rendering let time = get_time(pipelined.is_some(), &state);
session session
.locate_hand_joints(tracker, &ref_space, state.predicted_display_time) .locate_hand_joints(tracker, &ref_space, time)
.inspect_err(|err| error!("Error while locating hand joints")) .inspect_err(|err| error!("Error while locating hand joints"))
.ok() .ok()
.flatten() .flatten()

View File

@@ -3,7 +3,7 @@ use std::sync::Arc;
use bevy::prelude::*; use bevy::prelude::*;
use bevy_mod_openxr::{ use bevy_mod_openxr::{
helper_traits::{ToQuat, ToVec3}, helper_traits::{ToQuat, ToVec3},
resources::OxrFrameState, resources::{OxrFrameState, Pipelined},
session::OxrSession, session::OxrSession,
}; };
use bevy_mod_xr::{ use bevy_mod_xr::{
@@ -14,7 +14,7 @@ use openxr::SpaceLocationFlags;
use parking_lot::RwLock; use parking_lot::RwLock;
use zbus::{Connection, ObjectServer, interface}; use zbus::{Connection, ObjectServer, interface};
use crate::{DbusConnection, PreFrameWait, nodes::spatial::Spatial}; use crate::{DbusConnection, PreFrameWait, get_time, nodes::spatial::Spatial};
use super::{AsyncTracked, ObjectHandle, SpatialRef, Tracked}; use super::{AsyncTracked, ObjectHandle, SpatialRef, Tracked};
@@ -75,6 +75,7 @@ fn update(
ref_space: Option<Res<XrPrimaryReferenceSpace>>, ref_space: Option<Res<XrPrimaryReferenceSpace>>,
play_space: Res<PlaySpace>, play_space: Res<PlaySpace>,
state: Option<Res<OxrFrameState>>, state: Option<Res<OxrFrameState>>,
pipelined: Option<Res<Pipelined>>,
) { ) {
let (Some(session), Some(stage), Some(ref_space), Some(state)) = let (Some(session), Some(stage), Some(ref_space), Some(state)) =
(session, stage, ref_space, state) (session, stage, ref_space, state)
@@ -87,9 +88,9 @@ fn update(
.set_local_transform(Mat4::from_translation(vec3(0.0, -1.65, 0.0))); .set_local_transform(Mat4::from_translation(vec3(0.0, -1.65, 0.0)));
return; return;
}; };
// this won't be correct with pipelined rendering let time = get_time(pipelined.is_some(), &state);
let location = session let location = session
.locate_space(&stage.0, &ref_space, state.predicted_display_time) .locate_space(&stage.0, &ref_space, time)
.inspect_err(|err| error!("Error while Locating OpenXR Stage Space {err}")); .inspect_err(|err| error!("Error while Locating OpenXR Stage Space {err}"));
if let Ok(location) = location { if let Ok(location) = location {
let is_tracked = location.location_flags.contains( let is_tracked = location.location_flags.contains(

View File

@@ -11,6 +11,7 @@ mod xdg;
use crate::core::error::ServerError; use crate::core::error::ServerError;
use crate::core::registry::OwnedRegistry; use crate::core::registry::OwnedRegistry;
use crate::get_time;
use crate::nodes::drawable::model::ModelNodeSystemSet; use crate::nodes::drawable::model::ModelNodeSystemSet;
use crate::wayland::core::seat::SeatMessage; use crate::wayland::core::seat::SeatMessage;
use crate::wayland::core::surface::Surface; use crate::wayland::core::surface::Surface;
@@ -26,7 +27,7 @@ use bevy::render::{Render, RenderApp};
use bevy::{asset::Assets, ecs::resource::Resource, image::Image}; use bevy::{asset::Assets, ecs::resource::Resource, image::Image};
use bevy_dmabuf::import::ImportedDmatexs; use bevy_dmabuf::import::ImportedDmatexs;
use bevy_mod_openxr::render::end_frame; use bevy_mod_openxr::render::end_frame;
use bevy_mod_openxr::resources::{OxrFrameState, OxrInstance}; use bevy_mod_openxr::resources::{OxrFrameState, OxrInstance, Pipelined};
use bevy_mod_xr::session::XrRenderSet; use bevy_mod_xr::session::XrRenderSet;
use core::buffer::BufferUsage; use core::buffer::BufferUsage;
use core::{buffer::Buffer, callback::Callback, surface::WL_SURFACE_REGISTRY}; use core::{buffer::Buffer, callback::Callback, surface::WL_SURFACE_REGISTRY};
@@ -490,6 +491,7 @@ fn submit_frame_timings(
mut frame_count: Local<u64>, mut frame_count: Local<u64>,
instance: Option<Res<OxrInstance>>, instance: Option<Res<OxrInstance>>,
frame_state: Option<Res<OxrFrameState>>, frame_state: Option<Res<OxrFrameState>>,
pipelined: Option<Res<Pipelined>>,
) { ) {
*frame_count += 1; *frame_count += 1;
let display_timestamp = frame_state let display_timestamp = frame_state
@@ -502,7 +504,7 @@ fn submit_frame_timings(
let mut out = MaybeUninit::uninit(); let mut out = MaybeUninit::uninit();
let result = (v.convert_time_to_timespec_time)( let result = (v.convert_time_to_timespec_time)(
instance.as_raw(), instance.as_raw(),
state.predicted_display_time, get_time(pipelined.is_some(), &state),
out.as_mut_ptr(), out.as_mut_ptr(),
); );
if result != openxr::sys::Result::SUCCESS { if result != openxr::sys::Result::SUCCESS {