kms: Fix frame scheduling

This commit is contained in:
Victoria Brekenfeld 2024-06-27 18:15:18 +02:00
parent 5617f3228b
commit 8da3ac6d75
4 changed files with 25 additions and 17 deletions

View file

@ -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 { pub fn calculate_refresh_rate(mode: Mode) -> u32 {
let htotal = mode.hsync().2 as u32; let htotal = mode.hsync().2 as u32;
let vtotal = mode.vsync().2 as u32; let vtotal = mode.vsync().2 as u32;

View file

@ -594,9 +594,10 @@ impl SurfaceThreadState {
.unwrap() .unwrap()
.dmabuf_formats(); .dmabuf_formats();
self.timings.set_refresh_interval(Some(Duration::from_nanos( self.timings
drm_helpers::calculate_refresh_rate(surface.pending_mode()) as u64, .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); self.timings.set_vrr(vrr);
match DrmCompositor::new( match DrmCompositor::new(

View file

@ -3,7 +3,7 @@ use std::{collections::VecDeque, num::NonZeroU64, time::Duration};
use smithay::utils::{Clock, Monotonic, Time}; use smithay::utils::{Clock, Monotonic, Time};
use tracing::error; 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; const FRAME_TIME_WINDOW: usize = 3;
pub struct Timings { pub struct Timings {
@ -37,7 +37,7 @@ impl Frame {
} }
fn frame_time(&self) -> Duration { 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) / (self.previous_frames.len() as u32)
} }
pub fn avg_frametime(&self, window: usize) -> Duration { pub fn avg_frametime(&self, window: usize) -> Option<Duration> {
if self.previous_frames.is_empty() || window == 0 { if self.previous_frames.len() < window || window == 0 {
return MIN_RENDER_TIME; return None;
} }
self.previous_frames Some(
.iter() self.previous_frames
.rev() .iter()
.take(window) .rev()
.map(|f| f.frame_time()) .take(window)
.sum::<Duration>() .map(|f| f.frame_time())
/ (window.min(self.previous_frames.len()) as u32) .sum::<Duration>()
/ (window.min(self.previous_frames.len()) as u32),
)
} }
pub fn avg_fps(&self) -> f64 { pub fn avg_fps(&self) -> f64 {
@ -259,6 +261,10 @@ impl Timings {
return Duration::ZERO; 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)
} }
} }

View file

@ -50,8 +50,8 @@ pub fn fps_ui<'a>(
let amount = avg_fps.round() as usize * 2; let amount = avg_fps.round() as usize * 2;
let (max_disp, min_disp, avg_disp) = ( let (max_disp, min_disp, avg_disp) = (
timings.min_frametime(amount).as_secs_f64(),
timings.max_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(), timings.avg_frametime(amount).as_secs_f64(),
); );