Linux/wlr capture delivers ~2/3 of the requested frame rate (pacing sleeps before requesting the frame)

Aperta
#5,751 4 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
3/5
Tempo stimato
1-2 giorni
Idoneità per principianti
72/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
cpp, linux

Direzione di ricerca

Start in src/platform/linux/wlgrab.cpp at wlr_ram_t::capture and wlr_dmabuf_t::capture, then inspect snapshot() and the existing unpaced PipeWire capture path. Reproduce the reported 60 Hz case and trace when pacing, the screencopy request, and compositor response occur. Done means wlr capture approaches the requested rate when the source and encoder can sustain it, without regressing the idle-screen behavior referenced in #5748.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Is there an existing issue for this?
  • I have searched the existing issues
Describe the Bug

On the wlr capture path, the delivered frame rate is capped at roughly two thirds of the
requested rate, regardless of codec, resolution, encoder load or Sunshine version. With a
60 fps client request on a 60 Hz output I get a steady 41 fps; the same host sustains
59.9 fps when an independent wlr-screencopy consumer captures the same output with the
same VA-API encoder.

I believe the cause is the order of operations in the wlr capture loop
(src/platform/linux/wlgrab.cpp, wlr_ram_t::capture / wlr_dmabuf_t::capture):

while (true) {
  platf::handle_pacing(next_frame, delay, sleep_overshoot_logger);  // sleep a full frame interval
  auto status = snapshot(...);   // only now request a frame, then block until the compositor answers
  push_captured_image_cb(...);
}

snapshot() issues the screencopy request after the pacing sleep, so the compositor
cannot answer until its next frame. The delivered interval is therefore quantised to the
output's vblank and, since the request lands at an arbitrary phase, averages about
1.5 vblanks — 25 ms at 60 Hz, which is the 41 fps I measure.

The PipeWire path already has unpaced capture (#5629); wlr does not.

Evidence

Host: Ubuntu 24.04, AMD RX 7900 (VA-API), sway on its headless backend, virtual output
1920x1080. Capture source is glxgears fullscreen, verified window-by-window at 61.8–62.2 fps
for every measurement below. Client is Moonlight 12.2 on Android TV. Rates are read from
Moonlight's performance overlay.

The ceiling does not move for any of these:

varied values tried delivered
codec AV1 / H.264 41 / 41
Sunshine version 2026.516 / 2026.918 41 / 41
thread priority all 46 threads renice −15 41
resolution 1080p / 720p 41 / 41

Independent consumer on the same output, same host, same encoder:

capture encoder frames / duration fps
wf-recorder libx264 796 / 12.98 s 61.3
wf-recorder h264_vaapi 836 / 13.96 s 59.9
Sunshine vaapi — 41

The ceiling tracks the output's refresh, not the requested rate. Holding the client at
90 fps and forcing the output back to 60 Hz collapses it again, which is what points at the
vblank rather than at delay itself:

client request output delivered host processing avg
60 fps 60 Hz 41 15.5 ms
90 fps 60 Hz 42–44 15.1–16.8 ms
90 fps 90 Hz 54–56 12.3–12.8 ms
120 fps 120 Hz 64–73 10.9–12.4 ms

Host processing latency averages 15.5 ms throughout, so the encoder is not the limit — it
would allow ~64 fps on its own.

Expected Behavior

Delivered frame rate should approach the requested rate when the source and the encoder can
both sustain it, as the same protocol does for other consumers.

Additional Context

#5748 is touching snapshot() and the request timing in the same file for a different reason
(idle-screen compositor CPU); whoever works on that area may want this case in view.

Host Operating System

Linux

Operating System Version

Ubuntu 24.04.3 LTS, kernel 7.0.0-31-generic

Architecture

amd64

Sunshine commit or version

2026.918.174827 (also reproduced on 2026.516.143833)

GPU Type

AMD

GPU Model

Radeon RX 7900

GPU Driver/Mesa Version

amdgpu / Mesa (VA-API)

Capture Method

wlr (wlgrab)

Lingua principale
C++
Stelle
43k
Fork
2.4k
Merge medio
1g 15h
PR unite (30g)
105

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di LizardByte/Sunshine

Tutte le issue di LizardByte/Sunshine

Issue simili

Altre issue su C++

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.