render: rewrite the render loop to use a time-based frame index, allowing for future fps scaling based on energy mode
This commit is contained in:
@@ -42,15 +42,20 @@ pub async fn render(rmt: esp_hal::peripherals::RMT<'static>, gpio: AnyPin<'stati
|
||||
info!("Rendering started! {}ms since boot", Instant::now().as_millis());
|
||||
controls.notify_render_is_running(true);
|
||||
|
||||
// TODO: The prediction engine should be able to scale the display FPS down for power saving sometimes
|
||||
const FPS: u64 = 80;
|
||||
const RENDER_BUDGET: Duration = Duration::from_millis(1000 / FPS);
|
||||
|
||||
const ANIMATION_TPS: u64 = 120;
|
||||
const ANIMATION_FRAME_TIME: Duration = Duration::from_millis(1000 / ANIMATION_TPS);
|
||||
|
||||
loop {
|
||||
// FIXME: need to put the rendering loop into a deep sleep when the display is off
|
||||
let start = Instant::now();
|
||||
|
||||
output.blank();
|
||||
|
||||
uniforms.frame = (Instant::now().as_millis() / ANIMATION_FRAME_TIME.as_millis()) as usize;
|
||||
surfaces.render_to(&mut output, &uniforms);
|
||||
// TODO: We should split up the safety layers so they always have full power
|
||||
safety_surfaces.render_to(&mut output, &uniforms);
|
||||
@@ -64,6 +69,7 @@ pub async fn render(rmt: esp_hal::peripherals::RMT<'static>, gpio: AnyPin<'stati
|
||||
warn!("Renderer is sleeping zzzz");
|
||||
controls.notify_render_is_running(false);
|
||||
output.blank();
|
||||
output.commit_async().await.expect("Failed to commit low power frame");
|
||||
wdt.disable();
|
||||
controls.wait_until_display_is_on().await;
|
||||
wdt.feed();
|
||||
@@ -72,17 +78,17 @@ pub async fn render(rmt: esp_hal::peripherals::RMT<'static>, gpio: AnyPin<'stati
|
||||
controls.notify_render_is_running(true);
|
||||
}
|
||||
|
||||
// Apply the FPS cap where we sleep if we are rendering fast enough
|
||||
if render_duration < RENDER_BUDGET {
|
||||
let remaining_budget = RENDER_BUDGET - render_duration;
|
||||
uniforms.frame += 1;
|
||||
Timer::after(remaining_budget).await;
|
||||
} else {
|
||||
let dropped_count = (render_duration.as_ticks() as f32 / RENDER_BUDGET.as_ticks() as f32).ceil() as usize;
|
||||
warn!("Render stall! Frame took {}ms, dropping {dropped_count} frame(s)", render_duration.as_millis());
|
||||
// If we took longer than the budget, we need to drop some frames to catch up
|
||||
uniforms.frame += dropped_count;
|
||||
// Otherwise, we have a problem
|
||||
// TODO: Automatically scale FPS back when this happens
|
||||
warn!("Render stall! Frame took {}ms", render_duration.as_millis());
|
||||
}
|
||||
|
||||
// TODO: Need a way to let the UI layers configure this
|
||||
uniforms.primary_color.hue = uniforms.primary_color.hue.wrapping_add(1);
|
||||
|
||||
wdt.feed();
|
||||
|
||||
Reference in New Issue
Block a user