~eliasnaur/gio#429: 
Multiple windows cannot render concurrently on macOS

This demo program launches two windows both continuously invalidating and displaying a material.Loader.

After 1 second, the event loop of one window is deliberately hung during the processing of a frame event. Each call to system.FrameEvent.Frame is preceded by logging statements indicating that the frame processing is starting/ending for that window.

On Windows/Linux, the logging demonstrates windows rendering concurrently to one another (interleaved start/end logging for frame processing). Additionally, only one window hangs after a second.

On macOS, the logging indicates that frame processing is never interleaved and both application windows hang after 1 second.

I believe this indicates that Gio is not able to render multiple windows concurrently on macOS right now, probably (and this is conjecture) because each window locks the main thread to perform its render.

Is it possible to lift this restriction? For instance, can we render from a different thread and then perform the final buffer-swap from the main thread? That would allow the bulk of the GPU work to happen in parallel for multiple windows.

Naturally, I don't really know what I'm talking about here in GPU-land, so my interpretation of what's happening may be totally wrong.

Status
REPORTED
Submitter
~whereswaldon
Assigned to
No-one
Submitted
5 months ago
Updated
5 months ago
Labels
No labels applied.

~eliasnaur 5 months ago

I believe this indicates that Gio is not able to render multiple windows concurrently on macOS right now, probably (and this is conjecture) because each window locks the main thread to perform its render.

That's correct. Any platform that forces UI toolkit calls on the main thread (iOS/macOS,Android,WASM) can only have one outstanding window rendering at a time.

Gio had rendering in a separate thread at some point, perhaps it's worth bringing that feature back and pay the complexity cost. Separate rendering may also be needed for frame pacing.

~whereswaldon 5 months ago

I suspect that most users of the multi-window functionality on macOS will expect that the windows can render concurrently. Implementing video players or games with multiple windows seems somewhat impossible without concurrent rendering, so I definitely think it's worth exploring how to achieve it.

If it ties in with the frame quality-of-service/pacing stuff that we've discussed before, so much the better.

~eliasnaur 5 months ago

I looked into this some more, and I'm no longer sure this is worth spending resources on. Some reasons not to do it:

  • This is only a problem on macOS. Linux and Windows support a thread per window, the mobile platforms don't use multiple windows, WASM can't use multiple threads.
  • It is possible to render asynchronously on macOS, but at the cost of complexity and resize glitching because a resize event will no longer block pending its redraw. Maybe a hybrid approach would work where pure animation (not triggered by user input or resizing) can render asynchronously, synchronous rendering otherwise. But that's very complex to get right, and I worry about maintenance cost.

Given the above, the backpressure question is: what's to gain? If two or more windows are rendering simultaneously, they have to share the CPU/GPU resources anyway, so is there really so much to gain by making the sharing more fine-grained?

~eliasnaur 5 months ago

For the obligatory Raph Levien rant about the trouble with asynchronous rendering: https://raphlinus.github.io/rust/gui/2019/06/21/smooth-resize-test.html

~eliasnaur 5 months ago

Elias Naur referenced this ticket in commit dfd6834.

~eliasnaur 5 months ago

Elias Naur referenced this ticket in commit 971740f.

~eliasnaur 5 months ago

Elias Naur referenced this ticket in commit 96dccb2.

Register here or Log in to comment, or comment via email.