Skip to content

Commit eec8bda

Browse files
committed
fix(mmserver): drop application frames if the application is too slow
This produces roughly the same number of frames - meaning if an application is slow, we still wait for it to encode - but prevents the compositor thread from blocking while it does. Instead, we just try again next frame.
1 parent d2f571d commit eec8bda

File tree

2 files changed

+21
-11
lines changed

2 files changed

+21
-11
lines changed

mm-server/src/session/compositor.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::{collections::BTreeMap, sync::Arc};
66

77
use protocols::*;
88
use slotmap::SlotMap;
9-
use tracing::{instrument, trace};
9+
use tracing::{debug, instrument, trace};
1010
use wayland_protocols::{
1111
wp::{
1212
fractional_scale::v1::server::wp_fractional_scale_manager_v1,
@@ -172,8 +172,11 @@ impl Compositor {
172172
&mut self,
173173
video_pipeline: &mut video::EncodePipeline,
174174
) -> anyhow::Result<()> {
175-
let now = EPOCH.elapsed().as_millis() as u32;
176-
unsafe { video_pipeline.begin()? };
175+
let ready = unsafe { video_pipeline.begin()? };
176+
if !ready {
177+
debug!("dropped frame because of backpressure");
178+
return Ok(());
179+
}
177180

178181
// Iterate backwards to find the first fullscreen window.
179182
let first_visible_idx = self
@@ -186,8 +189,9 @@ impl Compositor {
186189
})
187190
.unwrap_or_default();
188191

189-
let mut presentation_feedback =
190-
Vec::with_capacity(self.surface_stack.len() - first_visible_idx);
192+
let num_surfaces = self.surface_stack.len() - first_visible_idx;
193+
let mut presentation_feedback = Vec::with_capacity(num_surfaces);
194+
191195
for id in self.surface_stack[first_visible_idx..].iter() {
192196
let surface = &mut self.surfaces[*id];
193197

mm-server/src/session/video.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -146,10 +146,18 @@ impl EncodePipeline {
146146
// }
147147

148148
#[instrument(level = "trace", skip_all)]
149-
pub unsafe fn begin(&mut self) -> anyhow::Result<()> {
149+
pub unsafe fn begin(&mut self) -> anyhow::Result<bool> {
150150
let device = &self.vk.device;
151151
let frame = &mut self.swap[self.swap_idx];
152152

153+
let ready = frame.tp_clear.poll()?;
154+
155+
// If the previous frame isn't ready, drop this one to let the app
156+
// catch up.
157+
if !ready {
158+
return Ok(false);
159+
}
160+
153161
// Trace on on the GPU side.
154162
if let Some(ref ctx) = self.vk.graphics_queue.tracy_context {
155163
if let Some(span) = frame.staging_span.take() {
@@ -167,10 +175,6 @@ impl EncodePipeline {
167175
}
168176

169177
frame.texture_semas_used = 0;
170-
171-
// Wait for the frame to no longer be in flight, and then establish new timeline
172-
// points.
173-
frame.tp_clear.wait()?;
174178
frame.tp_staging_done += 10;
175179
frame.tp_render_done = &frame.tp_staging_done + 1;
176180
frame.tp_clear = &frame.tp_render_done + 1;
@@ -203,7 +207,7 @@ impl EncodePipeline {
203207
vk::AccessFlags2::COLOR_ATTACHMENT_WRITE,
204208
);
205209

206-
Ok(())
210+
Ok(true)
207211
}
208212

209213
/// Adds a surface to be drawn. Returns the timeline point when the texture
@@ -355,6 +359,8 @@ impl EncodePipeline {
355359
Ok(release)
356360
}
357361

362+
/// End the current frame and submit it to the GPU. Returns the timeline
363+
/// point indicating when rendering and encoding have both completed.
358364
#[instrument(skip_all)]
359365
pub unsafe fn end_and_submit(&mut self) -> anyhow::Result<VkTimelinePoint> {
360366
let device = &self.vk.device;

0 commit comments

Comments
 (0)