From 33f2a7a425ea9d52fbc606327c98a30ef98667a6 Mon Sep 17 00:00:00 2001 From: Daniel McNab <36049421+DJMcNab@users.noreply.github.com> Date: Thu, 26 Sep 2024 09:29:52 +0100 Subject: [PATCH 1/3] Start experimenting with choreographer --- Cargo.lock | 14 +++++++++++--- Cargo.toml | 4 ++++ examples/with_winit/Cargo.toml | 1 + examples/with_winit/src/lib.rs | 9 +++++++++ 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d3e514ca3..1fe6dd395 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1329,13 +1329,12 @@ dependencies = [ [[package]] name = "ndk" version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" +source = "git+https://github.com/rust-mobile/ndk/?rev=01425d88813a4bdf02fd58abd34a6bbfb6383def#01425d88813a4bdf02fd58abd34a6bbfb6383def" dependencies = [ "bitflags 2.6.0", "jni-sys", "log", - "ndk-sys 0.6.0+11769913", + "ndk-sys 0.6.0+12185904", "num_enum", "raw-window-handle", "thiserror", @@ -1365,6 +1364,14 @@ dependencies = [ "jni-sys", ] +[[package]] +name = "ndk-sys" +version = "0.6.0+12185904" +source = "git+https://github.com/rust-mobile/ndk/?rev=01425d88813a4bdf02fd58abd34a6bbfb6383def#01425d88813a4bdf02fd58abd34a6bbfb6383def" +dependencies = [ + "jni-sys", +] + [[package]] name = "notify" version = "6.1.1" @@ -3360,6 +3367,7 @@ dependencies = [ "env_logger", "getrandom", "log", + "ndk", "notify-debouncer-mini", "pollster", "profiling", diff --git a/Cargo.toml b/Cargo.toml index 398914da0..2b9d33513 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,3 +62,7 @@ pollster = "0.3.0" web-time = "1.1.0" wgpu-profiler = "0.18.0" scenes = { path = "examples/scenes" } + +[patch.crates-io] +# "Choreographer" branch: https://github.com/rust-mobile/ndk/tree/choreographer +ndk = { git = "https://github.com/rust-mobile/ndk/", rev = "01425d88813a4bdf02fd58abd34a6bbfb6383def" } diff --git a/examples/with_winit/Cargo.toml b/examples/with_winit/Cargo.toml index 7cdd3181a..470d07524 100644 --- a/examples/with_winit/Cargo.toml +++ b/examples/with_winit/Cargo.toml @@ -62,6 +62,7 @@ tracing-subscriber = { version = "0.3.18", default-features = false, features = "registry", ] } profiling = { version = "1.0.15", features = ["profile-with-tracing"] } +ndk = { version = "0.9", features = ["api-level-33"] } [target.'cfg(target_arch = "wasm32")'.dependencies] console_error_panic_hook = "0.1.7" diff --git a/examples/with_winit/src/lib.rs b/examples/with_winit/src/lib.rs index 576452d27..b773ac912 100644 --- a/examples/with_winit/src/lib.rs +++ b/examples/with_winit/src/lib.rs @@ -8,6 +8,7 @@ use std::collections::HashSet; use std::num::NonZeroUsize; use std::sync::Arc; +use ndk::choreographer; #[cfg(not(target_arch = "wasm32"))] use std::time::Instant; #[cfg(target_arch = "wasm32")] @@ -163,6 +164,7 @@ struct VelloApp<'s> { modifiers: ModifiersState, debug: vello::DebugLayers, + choreographer: Option, } impl<'s> ApplicationHandler for VelloApp<'s> { @@ -461,6 +463,11 @@ impl<'s> ApplicationHandler for VelloApp<'s> { self.prev_scene_ix = self.scene_ix; window.set_title(&format!("Vello demo - {}", example_scene.config.name)); } + if example_scene.config.animated { + if let Some(choreographer) = self.choreographer { + choreographer.post_frame_callback(Box::new(|time| eprintln!("{time}"))); + } + } self.fragment.reset(); let mut scene_params = SceneParams { time: self.start.elapsed().as_secs_f64(), @@ -744,6 +751,8 @@ fn run( prev_scene_ix: 0, modifiers: ModifiersState::default(), debug, + // We know looper is active since we have the `EventLoop` + choreographer: ndk::choreographer::Choreographer::instance(), }; event_loop.run_app(&mut app).expect("run to completion"); From ee980ef648dcbef42a433134caa00b63653a120d Mon Sep 17 00:00:00 2001 From: Daniel McNab <36049421+DJMcNab@users.noreply.github.com> Date: Thu, 26 Sep 2024 13:10:28 +0100 Subject: [PATCH 2/3] Keep exploring with choreographer --- Cargo.lock | 15 +++------------ Cargo.toml | 4 +++- examples/with_winit/src/lib.rs | 33 ++++++++++++++++++++++++--------- 3 files changed, 30 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1fe6dd395..11464e949 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1329,12 +1329,12 @@ dependencies = [ [[package]] name = "ndk" version = "0.9.0" -source = "git+https://github.com/rust-mobile/ndk/?rev=01425d88813a4bdf02fd58abd34a6bbfb6383def#01425d88813a4bdf02fd58abd34a6bbfb6383def" +source = "git+https://github.com/djmcnab/ndk/?rev=81627a7564982a04027a49d538cac1686d870dbd#81627a7564982a04027a49d538cac1686d870dbd" dependencies = [ "bitflags 2.6.0", "jni-sys", "log", - "ndk-sys 0.6.0+12185904", + "ndk-sys 0.6.0+11769913", "num_enum", "raw-window-handle", "thiserror", @@ -1358,16 +1358,7 @@ dependencies = [ [[package]] name = "ndk-sys" version = "0.6.0+11769913" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" -dependencies = [ - "jni-sys", -] - -[[package]] -name = "ndk-sys" -version = "0.6.0+12185904" -source = "git+https://github.com/rust-mobile/ndk/?rev=01425d88813a4bdf02fd58abd34a6bbfb6383def#01425d88813a4bdf02fd58abd34a6bbfb6383def" +source = "git+https://github.com/djmcnab/ndk/?rev=81627a7564982a04027a49d538cac1686d870dbd#81627a7564982a04027a49d538cac1686d870dbd" dependencies = [ "jni-sys", ] diff --git a/Cargo.toml b/Cargo.toml index 2b9d33513..86e7ba954 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -65,4 +65,6 @@ scenes = { path = "examples/scenes" } [patch.crates-io] # "Choreographer" branch: https://github.com/rust-mobile/ndk/tree/choreographer -ndk = { git = "https://github.com/rust-mobile/ndk/", rev = "01425d88813a4bdf02fd58abd34a6bbfb6383def" } +# With a patch to make version numbers work https://github.com/djmcnab/ndk/tree/choreographer +ndk = { git = "https://github.com/djmcnab/ndk/", rev = "81627a7564982a04027a49d538cac1686d870dbd" } +ndk-sys = { git = "https://github.com/djmcnab/ndk/", rev = "81627a7564982a04027a49d538cac1686d870dbd" } diff --git a/examples/with_winit/src/lib.rs b/examples/with_winit/src/lib.rs index b773ac912..d1220edc2 100644 --- a/examples/with_winit/src/lib.rs +++ b/examples/with_winit/src/lib.rs @@ -8,7 +8,6 @@ use std::collections::HashSet; use std::num::NonZeroUsize; use std::sync::Arc; -use ndk::choreographer; #[cfg(not(target_arch = "wasm32"))] use std::time::Instant; #[cfg(target_arch = "wasm32")] @@ -16,6 +15,7 @@ use web_time::Instant; use winit::application::ApplicationHandler; use winit::event::*; use winit::keyboard::*; +use winit::window::WindowId; #[cfg(all(feature = "wgpu-profiler", not(target_arch = "wasm32")))] use std::time::Duration; @@ -165,6 +165,8 @@ struct VelloApp<'s> { debug: vello::DebugLayers, choreographer: Option, + animation_in_flight: bool, + proxy: winit::event_loop::EventLoopProxy, } impl<'s> ApplicationHandler for VelloApp<'s> { @@ -443,8 +445,6 @@ impl<'s> ApplicationHandler for VelloApp<'s> { let _rendering_span = tracing::trace_span!("Actioning Requested Redraw").entered(); let encoding_span = tracing::trace_span!("Encoding scene").entered(); - render_state.window.request_redraw(); - let Some(RenderState { surface, window }) = &self.state else { return; }; @@ -463,11 +463,6 @@ impl<'s> ApplicationHandler for VelloApp<'s> { self.prev_scene_ix = self.scene_ix; window.set_title(&format!("Vello demo - {}", example_scene.config.name)); } - if example_scene.config.animated { - if let Some(choreographer) = self.choreographer { - choreographer.post_frame_callback(Box::new(|time| eprintln!("{time}"))); - } - } self.fragment.reset(); let mut scene_params = SceneParams { time: self.start.elapsed().as_secs_f64(), @@ -594,6 +589,20 @@ impl<'s> ApplicationHandler for VelloApp<'s> { frame_time_us: (new_time - self.frame_start_time).as_micros() as u64, }); self.frame_start_time = new_time; + if example_scene.config.animated { + if let Some(choreographer) = self.choreographer.as_ref() { + let proxy = self.proxy.clone(); + choreographer.post_vsync_callback(Box::new(move |frame| { + eprintln!("{frame:?}"); + proxy + .send_event(UserEvent::ChoreographerFrame(window_id)) + .unwrap(); + })); + self.animation_in_flight = true; + } else { + window.request_redraw(); + } + } } _ => {} } @@ -617,7 +626,7 @@ impl<'s> ApplicationHandler for VelloApp<'s> { } } - fn user_event(&mut self, _event_loop: &winit::event_loop::ActiveEventLoop, event: UserEvent) { + fn user_event(&mut self, event_loop: &winit::event_loop::ActiveEventLoop, event: UserEvent) { match event { #[cfg(not(any(target_arch = "wasm32", target_os = "android")))] UserEvent::HotReload => { @@ -637,6 +646,9 @@ impl<'s> ApplicationHandler for VelloApp<'s> { Err(e) => log::error!("Failed to reload shaders: {e}"), } } + UserEvent::ChoreographerFrame(window_id) => { + self.window_event(event_loop, window_id, WindowEvent::RedrawRequested); + } } } @@ -753,6 +765,8 @@ fn run( debug, // We know looper is active since we have the `EventLoop` choreographer: ndk::choreographer::Choreographer::instance(), + proxy: event_loop.create_proxy(), + animation_in_flight: false, }; event_loop.run_app(&mut app).expect("run to completion"); @@ -791,6 +805,7 @@ fn window_attributes() -> WindowAttributes { enum UserEvent { #[cfg(not(any(target_arch = "wasm32", target_os = "android")))] HotReload, + ChoreographerFrame(WindowId), } #[cfg(target_arch = "wasm32")] From 432d66d3acf3546d8263bfc55be5918f898f6a76 Mon Sep 17 00:00:00 2001 From: Daniel McNab <36049421+DJMcNab@users.noreply.github.com> Date: Thu, 26 Sep 2024 13:58:34 +0100 Subject: [PATCH 3/3] Connect up Achoreographer --- examples/with_winit/Cargo.toml | 3 ++ examples/with_winit/src/lib.rs | 51 +++++++++++++++++++++++----------- 2 files changed, 38 insertions(+), 16 deletions(-) diff --git a/examples/with_winit/Cargo.toml b/examples/with_winit/Cargo.toml index 470d07524..708f3ac03 100644 --- a/examples/with_winit/Cargo.toml +++ b/examples/with_winit/Cargo.toml @@ -71,3 +71,6 @@ wasm-bindgen-futures = "0.4.43" web-sys = { version = "0.3.70", features = ["HtmlCollection", "Text"] } web-time = { workspace = true } getrandom = { version = "0.2.15", features = ["js"] } + +[package.metadata.android.application] +debuggable = true diff --git a/examples/with_winit/src/lib.rs b/examples/with_winit/src/lib.rs index d1220edc2..906bc441b 100644 --- a/examples/with_winit/src/lib.rs +++ b/examples/with_winit/src/lib.rs @@ -442,6 +442,9 @@ impl<'s> ApplicationHandler for VelloApp<'s> { self.prior_position = Some(position); } WindowEvent::RedrawRequested => { + if self.animation_in_flight { + return; + } let _rendering_span = tracing::trace_span!("Actioning Requested Redraw").entered(); let encoding_span = tracing::trace_span!("Encoding scene").entered(); @@ -589,19 +592,32 @@ impl<'s> ApplicationHandler for VelloApp<'s> { frame_time_us: (new_time - self.frame_start_time).as_micros() as u64, }); self.frame_start_time = new_time; - if example_scene.config.animated { - if let Some(choreographer) = self.choreographer.as_ref() { - let proxy = self.proxy.clone(); - choreographer.post_vsync_callback(Box::new(move |frame| { - eprintln!("{frame:?}"); - proxy - .send_event(UserEvent::ChoreographerFrame(window_id)) - .unwrap(); - })); - self.animation_in_flight = true; - } else { - window.request_redraw(); - } + + if let Some(choreographer) = self.choreographer.as_ref() { + let proxy = self.proxy.clone(); + choreographer.post_vsync_callback(Box::new(move |frame| { + // eprintln!("New frame"); + // let frame_time = frame.frame_time(); + // let preferred_index = frame.preferred_frame_timeline_index(); + // for timeline in 0..frame.frame_timelines_length() { + // eprintln!( + // "{:?} {}", + // frame.frame_timeline_deadline(timeline) - frame_time, + // if timeline == preferred_index { + // "(Preferred)" + // } else { + // "" + // } + // ); + // } + // eprintln!("{frame:?}"); + proxy + .send_event(UserEvent::ChoreographerFrame(window_id)) + .unwrap(); + })); + self.animation_in_flight = true; + } else { + window.request_redraw(); } } _ => {} @@ -621,9 +637,11 @@ impl<'s> ApplicationHandler for VelloApp<'s> { * self.transform; } - if let Some(render_state) = &mut self.state { - render_state.window.request_redraw(); - } + // if let Some(render_state) = &mut self.state { + // if !self.animation_in_flight { + // render_state.window.request_redraw(); + // } + // } } fn user_event(&mut self, event_loop: &winit::event_loop::ActiveEventLoop, event: UserEvent) { @@ -647,6 +665,7 @@ impl<'s> ApplicationHandler for VelloApp<'s> { } } UserEvent::ChoreographerFrame(window_id) => { + self.animation_in_flight = false; self.window_event(event_loop, window_id, WindowEvent::RedrawRequested); } }