wgpu icon indicating copy to clipboard operation
wgpu copied to clipboard

Resizing on macOS is cursed again

Open LoganDark opened this issue 4 years ago • 10 comments

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 wgpu stretch 2

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

LoganDark avatar Jan 24 '21 21:01 LoganDark

Some idle thoughts,

I'm fairly sure that this happens because of combination of

  1. winit is deferring the resize event to slightly later moment, outside of the event handler
  2. 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,

  1. 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.
  2. 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.
  3. Investigate if winit could handle windowWillResize to 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?

scoopr avatar Jan 24 '21 22:01 scoopr

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).

LoganDark avatar Jan 24 '21 22:01 LoganDark

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.

LoganDark avatar Apr 12 '21 21:04 LoganDark

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.

LoganDark avatar Apr 12 '21 21:04 LoganDark

I prototyped a potential fix for this in https://github.com/gfx-rs/gfx/pull/3627, but it didn't work at all 😓

kvark avatar Apr 13 '21 03:04 kvark

You could check out https://github.com/gfx-rs/gfx/pull/3627, enable the override to use it, and see if it helps.

kvark avatar Apr 13 '21 04:04 kvark

Looks like this is still an issue with https://github.com/lapce/lapce/ on Windows

LoganDark avatar Mar 31 '22 04:03 LoganDark

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.

LoganDark avatar Jun 18 '22 06:06 LoganDark

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.

cwfitzgerald avatar Jun 18 '22 08:06 cwfitzgerald

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::poll to wait for the GPU to finish before exiting winit::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.

LoganDark avatar Jul 01 '22 20:07 LoganDark