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 {
let htotal = mode.hsync().2 as u32;
let vtotal = mode.vsync().2 as u32;

View file

@ -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(

View file

@ -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<Duration> {
if self.previous_frames.len() < window || window == 0 {
return None;
}
self.previous_frames
.iter()
.rev()
.take(window)
.map(|f| f.frame_time())
.sum::<Duration>()
/ (window.min(self.previous_frames.len()) as u32)
Some(
self.previous_frames
.iter()
.rev()
.take(window)
.map(|f| f.frame_time())
.sum::<Duration>()
/ (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)
}
}

View file

@ -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(),
);