Wayland: Mutter's frame rate is either limited by or lower than that of "heavy" clients
Mutter draws its own frames from the committed frames of its clients, even if those frames haven't finished rendering. Due to the implicit synchronization done by the graphics driver, this means that the rendering of Mutter's own frames is delayed by the rendering of its clients' frames.
Because of this, when a client commits a frame that would take more than a full refresh cycle to render, Mutter will always miss the next vblank, sometimes even multiple times in each frame. In practice, Mutter's frame rate can be even lower than the frame rate of its "heaviest" client because it has additional rendering to do, causing it to increase the number of jobs in the graphics pipeline for the frame and miss additional vblank periods. The user experience is stuttering of every application, be it "heavy" or "light", as well as the shell itself.
This issue is the same as weston/issues/85, but for Mutter.
A workaround for this issue is to throttle the client's rendering in some way. This can often be achieved by enabling VSync on the client or limiting its frame rate through configuration.
Otherwise, reverting !281 (merged) would make Mutter perform the throttling on behalf of its clients.
A solution for this issue would be to use fences on buffers sent by clients and only ever compose finished client frames. The Wayland extension
zwp_linux_explicit_synchronization_unstable_v1 allows clients to explicitly request this kind of synchronization.
How to Reproduce
- Run Mutter with CLUTTER_SHOW_FPS=1
- Run a Wayland or an Xwayland client which does heavy rendering, such as games. In my case,
plot3dcan also be used to reproduce this: (adjust
plot3d_vertex_densityto get its frame rate below your monitor's configured refresh rate)
$ GALLIUM_HUD=fps ./GpuTest /test=plot3d /width=1920 /height=1080 /plot3d_vertex_density=2550
- Observe Mutter's FPS. It will be less than the client's. In my case, almost half.