-
Notifications
You must be signed in to change notification settings - Fork 342
wlr_output's design doesn't work well with repaint scheduling #1925
Comments
I wonder if it's worth going with the Although one foreseeable issue is restarting the rendering loop on VT-switching, but that has always been awkward. |
One issue is that it's not possible for DRM to implement a We could work-around this by making the DRM backend wait on
|
Yeah, that's a path full of a bunch of heuristics, but would allow us to emulate the mailbox model. When I heard the XDC talk mentioning this, I've been thinking that maybe it's not the worst idea. But Keith Packard has also mentioned that he wants to try and push for some kernel API changes regarding this too, which would make doing that unnecessary. We'll have to see if anything ends up happening. |
Note: swaywm/sway#4772 now sets |
This function allowed backends to provide a custom function for frame scheduling. Before resuming the rendering loop, the DRM and Wayland backends would wait for vsync. There isn't a clear benefit of doing this. The only upside is that we get more stable timings: the delay between two repaints doesn't change too much and is close to a mutliple of the refresh rate. However this introduces latency, especially when a client misses a frame. For instance a fullscreen game missing vblank will need to wait more than a whole frame before being able to display new content. This worst case scenario happens as follows: - Client is still rendering its frame and cannot submit it in time - Deadline is reached - Compositor decides to stop the rendering loop since nothing changed on screen - Client finally manages to render its frame, submits it - Compositor calls wlr_output_schedule_frame - DRM backend waits for next vblank - The wlr_output frame event is fired, compositor draws new content on screen - On the second next vblank, the new content reaches the screen With this patch, the wlr_output frame event is fired immediately when the client submits its late frame. This change also makes it easier to support variable refresh rate, since VRR is all about being able to present too-late frames earlier. References: swaywm#1925
This function allowed backends to provide a custom function for frame scheduling. Before resuming the rendering loop, the DRM and Wayland backends would wait for vsync. There isn't a clear benefit of doing this. The only upside is that we get more stable timings: the delay between two repaints doesn't change too much and is close to a mutliple of the refresh rate. However this introduces latency, especially when a client misses a frame. For instance a fullscreen game missing vblank will need to wait more than a whole frame before being able to display new content. This worst case scenario happens as follows: - Client is still rendering its frame and cannot submit it in time - Deadline is reached - Compositor decides to stop the rendering loop since nothing changed on screen - Client finally manages to render its frame, submits it - Compositor calls wlr_output_schedule_frame - DRM backend waits for next vblank - The wlr_output frame event is fired, compositor draws new content on screen - On the second next vblank, the new content reaches the screen With this patch, the wlr_output frame event is fired immediately when the client submits its late frame. This change also makes it easier to support variable refresh rate, since VRR is all about being able to present too-late frames earlier. References: #1925
Update: with #2046 |
This function allowed backends to provide a custom function for frame scheduling. Before resuming the rendering loop, the DRM and Wayland backends would wait for vsync. There isn't a clear benefit of doing this. The only upside is that we get more stable timings: the delay between two repaints doesn't change too much and is close to a mutliple of the refresh rate. However this introduces latency, especially when a client misses a frame. For instance a fullscreen game missing vblank will need to wait more than a whole frame before being able to display new content. This worst case scenario happens as follows: - Client is still rendering its frame and cannot submit it in time - Deadline is reached - Compositor decides to stop the rendering loop since nothing changed on screen - Client finally manages to render its frame, submits it - Compositor calls wlr_output_schedule_frame - DRM backend waits for next vblank - The wlr_output frame event is fired, compositor draws new content on screen - On the second next vblank, the new content reaches the screen With this patch, the wlr_output frame event is fired immediately when the client submits its late frame. This change also makes it easier to support variable refresh rate, since VRR is all about being able to present too-late frames earlier. References: swaywm#1925
Could wlroots provide an object (say a The algorithm would be configurable:
I am aware such an algorithm would be opinionated, and therefore that it wouldn't work for every compositor, but the big advantage is that it would provide a default algorithm that all compositors can easily use with very few lines of code and that would help decrease the input latency on all of the Linux desktop that uses wlroots, instead of just Sway for now, especially if a mode is added later that keeps track of the maximum render times automatically and doesn't need any configuration from the end user (I don't know if this actually works). Additionally, if this was put in wlroots, it could mean that a Wayland protocol extension that works on all wlroots compositors could be created where clients tell the compositor how much time they need to render their content, like the If the compositor wants its own implementation of frame scheduling, it could listen itself for the |
Sorry, I'm a bit out of the loop so I can't comment on the main part of the comment, but:
I don't think this is a good idea since it has a lag of at least 1 frame; I think a better idea would be to signal the clients the commit deadline together with frame callbacks without delaying the frame callbacks, so then the client itself can decide whether it wants to take all the available time or wait on its own to start rendering closer to the commit deadline. |
I think an optional helper would be a good idea, but I'd prefer to have it working in a compositor before deciding whether it should be part of wlroots or not. The helper should listen to presentation events instead of frame events. The backend doesn't send frame events when a page-flip happens, the backend sends a frame event to signal it's a good time to render (and it's wired up to |
I'm still new to this, but I'm kinda skeptical of the idea to let the client decide when they start rendering. Here are the reasons:
By the way, an application that is known to do work during the idle period between frames is Chrome (https://v8.dev/blog/free-garbage-collection), but it calculates the amount of free time after a frame (which can be calculated by subtracting frame time from the monitor refresh period), in contrast to the time before a frame (which is hard to determine as described in point 1 above). So for that case it will work without the knowledge of render deadline. |
It's hard, but an application surely knows more about what it's about to render than a compositor. I don't expect many applications bother though, so it's probably the best idea to have that option (as in, not block that option from developing later on) and try to adjust it automatically in the compositor for the rest of applications.
I don't see how either of these points depends on all clients starting rendering at the same time? I mean, if you set |
The idea is to have a consistent snapshot view of things like cursor positions among all clients as well as the compositor. So I want to avoid cases like app A thinks your cursor position is that of -10ms from now, app B thinks it's that of -5ms from now, and the compositor has something like -1ms from now. That said, it rarely matters since it's only the focused window that receives events. The examples I mentioned in previous comment is primarily about syncing compositor with the client (so it's not actually client-client sync). We do want to avoid cases where the cursor is running ahead or behind the edge position of the app that is currently resized. |
wlr_output
has a baked-in assumption that the compositor will render right away when theframe
event is triggered.If the compositor doesn't do this, then
wlr_output
assumes the compositor stopped its rendering loop. Some wlroots utilities (wlr_output_damage
,wlr_screencopy_v1
) need to resume the rendering loop, and will callwlr_output_schedule_frame
to do so. This function will re-submit the previous frame (perform a page-flip on DRM) to request a newframe
event. We don't resume the rendering loop immediately to make sure we're correctly aligned with vsync.All of this will prevent the compositor from submitting a new frame some time after the
frame
event.To implement repaint scheduling in Sway,
wlr_output.block_idle_frame
has been introduced. It's basically a way for the compositor to say "i'll submit a frame soon, so please ignore anywlr_output_schedule_frame
call".I'm not a fan of the current situation because the
wlr_output
interface has become too complicated and opinionated. Removingwlr_output.block_idle_frame
is not trivial, see swaywm/sway#4588 (comment).I'll try to think of a better solution, with repaint scheduling + variable refresh rate in mind.
wlroots has migrated to gitlab.freedesktop.org. This issue has been moved to:
https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/1925
The text was updated successfully, but these errors were encountered: