From 8da3ac6d75197acce5d3373ddd97548b5eafee37 Mon Sep 17 00:00:00 2001 From: Victoria Brekenfeld Date: Thu, 27 Jun 2024 18:15:18 +0200 Subject: [PATCH] kms: Fix frame scheduling --- src/backend/kms/drm_helpers.rs | 1 + src/backend/kms/surface/mod.rs | 7 ++++--- src/backend/kms/surface/timings.rs | 32 ++++++++++++++++++------------ src/debug.rs | 2 +- 4 files changed, 25 insertions(+), 17 deletions(-) diff --git a/src/backend/kms/drm_helpers.rs b/src/backend/kms/drm_helpers.rs index b908e428..1464ae3f 100644 --- a/src/backend/kms/drm_helpers.rs +++ b/src/backend/kms/drm_helpers.rs @@ -316,6 +316,7 @@ fn get_manufacturer(vendor: &[char; 3]) -> &'static str { } } +// Returns refresh rate in milliherz pub fn calculate_refresh_rate(mode: Mode) -> u32 { let htotal = mode.hsync().2 as u32; let vtotal = mode.vsync().2 as u32; diff --git a/src/backend/kms/surface/mod.rs b/src/backend/kms/surface/mod.rs index 6a2a0af5..5c085465 100644 --- a/src/backend/kms/surface/mod.rs +++ b/src/backend/kms/surface/mod.rs @@ -594,9 +594,10 @@ impl SurfaceThreadState { .unwrap() .dmabuf_formats(); - self.timings.set_refresh_interval(Some(Duration::from_nanos( - drm_helpers::calculate_refresh_rate(surface.pending_mode()) as u64, - ))); + self.timings + .set_refresh_interval(Some(Duration::from_secs_f64( + 1_000.0 / drm_helpers::calculate_refresh_rate(surface.pending_mode()) as f64, + ))); self.timings.set_vrr(vrr); match DrmCompositor::new( diff --git a/src/backend/kms/surface/timings.rs b/src/backend/kms/surface/timings.rs index d372a7e4..cfa237f5 100644 --- a/src/backend/kms/surface/timings.rs +++ b/src/backend/kms/surface/timings.rs @@ -3,7 +3,7 @@ use std::{collections::VecDeque, num::NonZeroU64, time::Duration}; use smithay::utils::{Clock, Monotonic, Time}; use tracing::error; -const MIN_RENDER_TIME: Duration = Duration::from_millis(5); +const FRAME_TIME_BUFFER: Duration = Duration::from_millis(1); const FRAME_TIME_WINDOW: usize = 3; pub struct Timings { @@ -37,7 +37,7 @@ impl Frame { } fn frame_time(&self) -> Duration { - Time::elapsed(&self.render_start, self.presentation_submitted) + Time::elapsed(&self.render_start, self.presentation_presented) } } @@ -179,18 +179,20 @@ impl Timings { / (self.previous_frames.len() as u32) } - pub fn avg_frametime(&self, window: usize) -> Duration { - if self.previous_frames.is_empty() || window == 0 { - return MIN_RENDER_TIME; + pub fn avg_frametime(&self, window: usize) -> Option { + if self.previous_frames.len() < window || window == 0 { + return None; } - self.previous_frames - .iter() - .rev() - .take(window) - .map(|f| f.frame_time()) - .sum::() - / (window.min(self.previous_frames.len()) as u32) + Some( + self.previous_frames + .iter() + .rev() + .take(window) + .map(|f| f.frame_time()) + .sum::() + / (window.min(self.previous_frames.len()) as u32), + ) } pub fn avg_fps(&self) -> f64 { @@ -259,6 +261,10 @@ impl Timings { return Duration::ZERO; } - estimated_presentation_time.saturating_sub(self.avg_frametime(FRAME_TIME_WINDOW)) + let Some(avg_frametime) = self.avg_frametime(FRAME_TIME_WINDOW) else { + return Duration::ZERO; + }; + + estimated_presentation_time.saturating_sub(avg_frametime + FRAME_TIME_BUFFER) } } diff --git a/src/debug.rs b/src/debug.rs index a9b74b73..ecd27669 100644 --- a/src/debug.rs +++ b/src/debug.rs @@ -50,8 +50,8 @@ pub fn fps_ui<'a>( let amount = avg_fps.round() as usize * 2; let (max_disp, min_disp, avg_disp) = ( - timings.min_frametime(amount).as_secs_f64(), timings.max_frametime(amount).as_secs_f64(), + timings.min_frametime(amount).as_secs_f64(), timings.avg_frametime(amount).as_secs_f64(), );