[wayland] vsync with frame callbacks causes high CPU load and works badly with VRR
Categories
(Core :: Widget: Gtk, defect, P3)
Tracking
()
People
(Reporter: rmader, Unassigned)
References
(Blocks 2 open bugs)
Details
(Whiteboard: gtk-severity-sweep-2026-10)
The frame callback based vsync unfortunately causes pretty high CPU load both in firefox and the Wayland compositor. This is easily visible when comparing the CPU load when watching a hw-decoded video with widget.wayland.vsync.enabled either enabled or not. On top of that VRR implementations in common Wayland compositors like Mutter are hard to get right for unusual implementations like the one we have.
Proposed solution:
Given that we don't need vsync to avoid tear, but only to get the right refresh rate, good refresh timings and "running in background" detection, we might be able to simplify the implementation and do something closer to what other platforms like Android do.
The later - IIUC - just uses a software timer with the maximum refresh rate of the display. We could do the same on a per-window basis, using the maximum refresh rate of all outputs the window is visible on, falling back to 60Hz otherwise. As we nowadays have explicit suspend events from the compositor, we'd still suspend in the background if compositors tell us so (Mutter 49 does so after a short timeout when the window is fully obscured).
This should bring down CPU usage to the level of widget.wayland.vsync.enabled=false, while keeping correct maximum refresh rates - and working well with VRR. It would also simplify things for gfx.wayland.hdr.
The main disadvantage would be missing phase synchronization to the actual output. However, the current architecture doesn't do a particular good job in that regard as the vsync runs in the main thread. Also, with screens becoming ever faster and 60Hz not necessarily the norm any more, the impact will decrease more and more. Finally it seems to work well enough on Android.
Comment 2•9 months ago
|
||
Is https://wayland.app/protocols/presentation-time related here?
Updated•9 months ago
|
| Reporter | ||
Comment 3•9 months ago
|
||
What about switching to Vulkan and using explicit sync?
I'm afraid I don't see how either of that would help here.
Is https://wayland.app/protocols/presentation-time related here?
This could help here as it would allow us to get better information about the actual presentation time. Given the rather abstract vsync architecture - passing the info on over process barriers so websites can use it for requestAnimationFrame() - I'm not sure about the complexity/impact trade-off, though.
(In reply to Robert Mader [:rmader] from comment #3)
I'm afraid I don't see how either of that would help here.
I thought may be with Vulkan, something like this can be used?
| Reporter | ||
Comment 5•9 months ago
|
||
(In reply to Shmerl from comment #4)
I thought may be with Vulkan, something like this can be used?
Explicit vs implicit sync is only vaguely related here I'd say - that's just about GPU work not being finished before a buffer is submitted to the Wayland compositor. Compositors like Mutter already implement mechanisms to explicitly wait for implicit sync before submitting page flips to KMS, which essentially do the same as when the client creates the sync objects.
Comment 6•9 months ago
|
||
There are two main issues with SW vsync:
- how to get actual monitor refresh rate? (we know where the window is located so we can use SW vsync accordingly per monitor).
- how to detect hidden/obscured window - that's the most important issue.
We can implement the two fixes to recent SW vsync and then compare the results.
Updated•9 months ago
|
Comment 7•9 months ago
|
||
Just want to comment that widget.wayland.vsync.enabled=false works terribly bad, at least for wlroots based compositors. It is not making the CPU usage less, but in fact it causes CPU usage of 13-15% on compositor process when firefox is compleletely idle. I had a bug for this, but as Martin commented the widget.wayland.vsync.enabled=false is a debugging setting not supposed to be used, so the bug is closed. But if the same behaviour is going to be implemented for widget.wayland.vsync.enabled=true it will be a really terrible thing for laptop battery life. 10-13% may not sound so bad, but as this happen on idle when no video is playing or nothing heavy happening on graphics side it will be the only process that drains the battery.
| Reporter | ||
Comment 8•9 months ago
|
||
(In reply to Martin Stránský [:stransky] (ni? me) from comment #6)
There are two main issues with SW vsync:
- how to get actual monitor refresh rate? (we know where the window is located so we can use SW vsync accordingly per monitor).
- how to detect hidden/obscured window - that's the most important issue.
We can implement the two fixes to recent SW vsync and then compare the results.
- Right, the idea would be to get it from the
wl_output. That's basically what we do on X11-EGL since bug 1640779, just on a per-window base, allowing different refresh rates for different windows. - That should already be handled via the visibility/xdg-suspend signal, if Wayland compositors use it (Mutter does and got some improvements in 49). We fixed that in bug 1693513 / https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/6630 - and it seems to work well here. I.e. if I move a youtube FF window to the background via alt-tab, CPU usage goes way down after ~3 seconds.
(In reply to s.zharkoff from comment #7)
[...] but in fact it causes CPU usage of 13-15% on compositor process when firefox is compleletely idle. [...]
Uh, that's bad indeed. Actually Firefox should disable the vsync whenever not needed - and checking it on my device it's sitting at 0.6% CPU while being visible and idle. We'll keep that in mind!
Comment 9•9 months ago
|
||
For me it is sitting at something like 1% also when vsync is enabled. But if I do set widget.wayland.vsync.enabled=false it goes mad at idle (not firefox, ff keeps low but wayfire (or sway - whatever is used) goes mad. But - only on idle, if I start playing video compositor's CPU usage stays almost same as idle. And in fact when youtube is playing the cpu use does not change much depending on widget.wayland.vsync.enabled true or false, only firefox at idle triggers this. And I need to restart - if I just set up "about:config" setting without firefox restart does not change anything.
Updated•19 days ago
|
Description
•