Measure render attempts that produce no damage
This commit is contained in:
1 parent
473ce8b332
commit
da5397940b
3 files changed
+47
No files matched your search
@@ -675,6 +675,9 @@ fn render_output(state: &mut Ferese, node: DrmNode, crtc: crtc::Handle) {
|
|||||||
.finish()?;
|
.finish()?;
|
||||||
}
|
}
|
||||||
let Some(damage) = result.damage.cloned() else {
|
let Some(damage) = result.damage.cloned() else {
|
||||||
|
output
|
||||||
|
.render_metrics
|
||||||
|
.record_no_damage(render_started.elapsed(), missed_deadlines);
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ pub(crate) struct RenderMetrics {
|
|||||||
output: String,
|
output: String,
|
||||||
interval_started: Instant,
|
interval_started: Instant,
|
||||||
rendered_frames: u64,
|
rendered_frames: u64,
|
||||||
|
no_damage_frames: u64,
|
||||||
|
no_damage_render_time: Duration,
|
||||||
damaged_pixels: u64,
|
damaged_pixels: u64,
|
||||||
total_render_time: Duration,
|
total_render_time: Duration,
|
||||||
longest_render_time: Duration,
|
longest_render_time: Duration,
|
||||||
@@ -37,6 +39,8 @@ impl RenderMetrics {
|
|||||||
output: output.into(),
|
output: output.into(),
|
||||||
interval_started: now,
|
interval_started: now,
|
||||||
rendered_frames: 0,
|
rendered_frames: 0,
|
||||||
|
no_damage_frames: 0,
|
||||||
|
no_damage_render_time: Duration::ZERO,
|
||||||
damaged_pixels: 0,
|
damaged_pixels: 0,
|
||||||
total_render_time: Duration::ZERO,
|
total_render_time: Duration::ZERO,
|
||||||
longest_render_time: Duration::ZERO,
|
longest_render_time: Duration::ZERO,
|
||||||
@@ -64,6 +68,19 @@ impl RenderMetrics {
|
|||||||
}
|
}
|
||||||
self.frame_times.push_back(render_time);
|
self.frame_times.push_back(render_time);
|
||||||
|
|
||||||
|
self.report_if_due(missed_deadlines);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn record_no_damage(&mut self, render_time: Duration, missed_deadlines: u64) {
|
||||||
|
if !self.enabled {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self.no_damage_frames += 1;
|
||||||
|
self.no_damage_render_time += render_time;
|
||||||
|
self.report_if_due(missed_deadlines);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn report_if_due(&mut self, missed_deadlines: u64) {
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
let elapsed = now.saturating_duration_since(self.interval_started);
|
let elapsed = now.saturating_duration_since(self.interval_started);
|
||||||
if elapsed < REPORT_INTERVAL {
|
if elapsed < REPORT_INTERVAL {
|
||||||
@@ -91,6 +108,8 @@ impl RenderMetrics {
|
|||||||
output = %self.output,
|
output = %self.output,
|
||||||
interval_ms = elapsed.as_millis(),
|
interval_ms = elapsed.as_millis(),
|
||||||
frames = self.rendered_frames,
|
frames = self.rendered_frames,
|
||||||
|
no_damage_frames = self.no_damage_frames,
|
||||||
|
no_damage_render_us = self.no_damage_render_time.as_micros(),
|
||||||
damaged_pixels = self.damaged_pixels,
|
damaged_pixels = self.damaged_pixels,
|
||||||
average_render_us,
|
average_render_us,
|
||||||
longest_render_us = self.longest_render_time.as_micros(),
|
longest_render_us = self.longest_render_time.as_micros(),
|
||||||
@@ -102,6 +121,8 @@ impl RenderMetrics {
|
|||||||
|
|
||||||
self.interval_started = now;
|
self.interval_started = now;
|
||||||
self.rendered_frames = 0;
|
self.rendered_frames = 0;
|
||||||
|
self.no_damage_frames = 0;
|
||||||
|
self.no_damage_render_time = Duration::ZERO;
|
||||||
self.damaged_pixels = 0;
|
self.damaged_pixels = 0;
|
||||||
self.total_render_time = Duration::ZERO;
|
self.total_render_time = Duration::ZERO;
|
||||||
self.longest_render_time = Duration::ZERO;
|
self.longest_render_time = Duration::ZERO;
|
||||||
@@ -121,6 +142,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn disabled_metrics_do_not_accumulate() {
|
fn disabled_metrics_do_not_accumulate() {
|
||||||
let mut metrics = RenderMetrics::new("test", false, Instant::now());
|
let mut metrics = RenderMetrics::new("test", false, Instant::now());
|
||||||
|
metrics.record_no_damage(Duration::from_millis(1), 0);
|
||||||
|
|
||||||
metrics.record_frame(
|
metrics.record_frame(
|
||||||
Duration::from_millis(2),
|
Duration::from_millis(2),
|
||||||
@@ -131,6 +153,26 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(metrics.rendered_frames, 0);
|
assert_eq!(metrics.rendered_frames, 0);
|
||||||
assert_eq!(metrics.damaged_pixels, 0);
|
assert_eq!(metrics.damaged_pixels, 0);
|
||||||
|
assert_eq!(metrics.no_damage_frames, 0);
|
||||||
|
assert_eq!(metrics.no_damage_render_time, Duration::ZERO);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn no_damage_attempts_are_separate_from_presented_frame_statistics() {
|
||||||
|
let mut metrics = RenderMetrics::new("test", true, Instant::now());
|
||||||
|
metrics.record_no_damage(Duration::from_millis(2), 0);
|
||||||
|
metrics.record_no_damage(Duration::from_millis(3), 0);
|
||||||
|
assert_eq!(metrics.no_damage_frames, 2);
|
||||||
|
assert_eq!(metrics.no_damage_render_time, Duration::from_millis(5));
|
||||||
|
assert_eq!(metrics.rendered_frames, 0);
|
||||||
|
assert!(metrics.frame_times.is_empty());
|
||||||
|
|
||||||
|
// An entirely idle interval must report and reset without waiting for
|
||||||
|
// a damaged frame or dividing by a zero presented-frame count.
|
||||||
|
metrics.interval_started = Instant::now() - REPORT_INTERVAL;
|
||||||
|
metrics.record_no_damage(Duration::from_millis(1), 0);
|
||||||
|
assert_eq!(metrics.no_damage_frames, 0);
|
||||||
|
assert_eq!(metrics.no_damage_render_time, Duration::ZERO);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -901,6 +901,8 @@ pub fn init(event_loop: &mut EventLoop<Ferese>, state: &mut Ferese) -> Result<()
|
|||||||
let (damage, effects) = match rendered {
|
let (damage, effects) = match rendered {
|
||||||
Ok((Some(damage), effects)) => (damage, effects),
|
Ok((Some(damage), effects)) => (damage, effects),
|
||||||
Ok((None, _)) => {
|
Ok((None, _)) => {
|
||||||
|
render_metrics
|
||||||
|
.record_no_damage(render_started.elapsed(), missed_deadlines);
|
||||||
// A callback means permission to draw the next client
|
// A callback means permission to draw the next client
|
||||||
// frame, not proof of a new compositor presentation.
|
// frame, not proof of a new compositor presentation.
|
||||||
// No-damage frames must still unblock layer clients.
|
// No-damage frames must still unblock layer clients.
|
||||||
|
|||||||
Reference in new issue
Block a user