wgpu
wgpu copied to clipboard
Resizing on macOS is cursed again
Description When resizing the window, the previous frame is stretched before any new frames are displayed. Or... maybe a new frame is drawn using an outdated uniform buffer and I can't update it in time. Who knows...
Repro steps https://github.com/LoganDark/wgpu-stretch
Expected vs observed behavior The square in the top left should not stretch
Extra materials

The previous incarnation of this bug can be found at #249
Platform macOS 10.14.6 Mojave Tech stack is as described in the wgpu-stretch repository
Some idle thoughts,
I'm fairly sure that this happens because of combination of
- winit is deferring the resize event to slightly later moment, outside of the event handler
- the view/layer is set to fill the window, so the system helpfully rescales it to match (or winit scales it in-situ, but emits event deferred)
Avenues to look at,
- Check who is setting the view to be the size of the window (winit? gfx?), and check if it could be not automatically adjusted, but would only be updated to current size when presenting. This would introduce the "cropped" view artifacts, which would be less annoying, but feel perhaps unprofessional still.
- Investigate if winit could be coerced (optionally?) to handle resize events "synchronously". There might be good reasons why they aren't, but I'm not sure. This should produce "perfect" resizing behaviour, though with heavy rendering it might end up queueing a lots of slow redraws.
- Investigate if winit could handle
windowWillResizeto record what size it should be, but return the original resolution, and then at present resize the window to the suggested size anyway. This would produce "perfect windows", but possibly with ever so slight lag for when the resize occurs.
I wonder if that happens also with other winit using projects?
I wonder if that happens also with other winit using projects?
It does. Glutin has the same issue, and they also use winit: https://github.com/rust-windowing/glutin/issues/1340
I'll open an issue in winit's repository to see if they can implement number 2 (handling resize events synchronously).
This issue is not solved yet. Redrawing immediately inside of the Resized event still results in this stretching, even on the latest winit... so this may be a wgpu issue, assuming winit is doing its job correctly now.
Actually it seems now to be the reverse of what it was before. In my newest commit https://github.com/LoganDark/wgpu-stretch/commit/517a37b0c72cd4433f6d187ff2a623abad825570 I updated to the latest (git) version of winit and tried to make resizing smooth by redrawing synchronously inside the handler for WindowEvent::Resized.
Now it seems that the frame is being presented before the window's new size is applied, which I initially thought could be solved by using the Fifo/Mailbox PresentMode, but alas, nothing helped.
I prototyped a potential fix for this in https://github.com/gfx-rs/gfx/pull/3627, but it didn't work at all 😓
You could check out https://github.com/gfx-rs/gfx/pull/3627, enable the override to use it, and see if it helps.
Looks like this is still an issue with https://github.com/lapce/lapce/ on Windows
softbuffer does not have this issue which means it is not (anymore) a winit problem. It probably has to do with latency getting results from the GPU after a resize operation, or uniforms not being uploaded in time, or something like that.
Yeah this seems like a latency based race - we currently have no way of canceling presentation yet, which is potentially what you'd need to do with pending presents which hit the surface after the resize happened.
So
-
This is solvable on Windows by using PresentMode::Mailbox (but not Immediate or Fifo), but the window becomes extremely laggy, like 10fps.
https://user-images.githubusercontent.com/4723091/176966076-6b0ae819-7a2e-43ed-b38b-adceb265caae.mp4
Other details are:
- I am using WGSL instead of SPIR-V
- I am using Push Constants instead of uniforms (fun fact, the upcoming switch to DX12 as a default will ruin this, as DX12 does not support push constants)
- I am using
Device::pollto wait for the GPU to finish before exitingwinit::event::Event::RedrawRequested
-
wgpu 0.13 is the first version to point out the fact that Mailbox is actually not supported on my macOS machine which is probably why it didn't work as a troubleshooting step.
