fix(host): stop force-disabling zero-copy on Mutter+NVIDIA by default

apply_session_env unconditionally forced PUNKTFUNK_FORCE_SHM=1 for every
GNOME/Mutter session, added 2026-06-14 after a same-day stale-frame bug hunt
found Mutter has no implicit dmabuf fence on NVIDIA. That override silently
contradicted the documented "zero-copy is on by default for all Linux GPU
backends" behavior and left Mutter+NVIDIA hosts on the slower CPU/SHM path
unconditionally, with no way to opt back in.

Live retesting (192.168.1.21, RTX 5070 Ti, real client with cursor
movement/window drag/typing — the historical trigger) shows no visible
staleness with the override removed. Drop the automatic force; PUNKTFUNK_FORCE_SHM
stays as a manual escape hatch for anyone who does hit flashing/stale frames
on a Mutter+NVIDIA host.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-06 16:04:25 +00:00
parent efb49c5afd
commit a041b0aa96
2 changed files with 7 additions and 8 deletions
@@ -1278,9 +1278,13 @@ mod pipewire {
} else { } else {
None None
}; };
// PUNKTFUNK_FORCE_SHM=1 forces the race-free download path (SHM, no dmabuf) — required on // PUNKTFUNK_FORCE_SHM=1 forces the race-free download path (SHM, no dmabuf) — a manual
// Mutter+NVIDIA where dmabuf capture has no working sync and shows stale frames. KWin/ // escape hatch, mainly for Mutter+NVIDIA: that combo has no implicit dmabuf fence, so
// gamescope don't need it (they blit into the buffer, so no read-before-render race). // zero-copy capture can in principle race the compositor's render and show stale frames.
// Zero-copy is the Mutter+NVIDIA default (no unconditional override) since live retesting
// found no visible staleness; set this if you do see flashing/stale content on such a
// host. KWin/gamescope don't need it (they blit into the buffer, so no read-before-render
// race).
let force_shm = std::env::var("PUNKTFUNK_FORCE_SHM").as_deref() == Ok("1"); let force_shm = std::env::var("PUNKTFUNK_FORCE_SHM").as_deref() == Ok("1");
// VAAPI zero-copy passthrough: zero-copy on, no EGL→CUDA importer (any non-NVIDIA host), and // VAAPI zero-copy passthrough: zero-copy on, no EGL→CUDA importer (any non-NVIDIA host), and
// the encoder backend is VAAPI → hand the raw dmabuf to the encoder (it imports + GPU-CSCs). // the encoder backend is VAAPI → hand the raw dmabuf to the encoder (it imports + GPU-CSCs).
-5
View File
@@ -619,11 +619,6 @@ pub fn apply_session_env(active: &ActiveSession) {
if let Some(d) = &e.xdg_current_desktop { if let Some(d) = &e.xdg_current_desktop {
std::env::set_var("XDG_CURRENT_DESKTOP", d); std::env::set_var("XDG_CURRENT_DESKTOP", d);
} }
// Mutter on NVIDIA has no working dmabuf capture sync — force SHM there; the KWin/gamescope
// tiled/LINEAR paths keep zero-copy.
if active.kind == ActiveKind::DesktopGnome {
std::env::set_var("PUNKTFUNK_FORCE_SHM", "1");
}
// Topology (Stage 2): the per-compositor backends (KWin/Mutter) now read // Topology (Stage 2): the per-compositor backends (KWin/Mutter) now read
// [`effective_topology`] directly at create time — the console policy, else the legacy // [`effective_topology`] directly at create time — the console policy, else the legacy
// `PUNKTFUNK_{KWIN,MUTTER}_VIRTUAL_PRIMARY` env, else the Auto default (exclusive on the // `PUNKTFUNK_{KWIN,MUTTER}_VIRTUAL_PRIMARY` env, else the Auto default (exclusive on the