gfx-rs / wgpu

A cross-platform, safe, pure-Rust graphics API.
https://wgpu.rs
Apache License 2.0
12.77k stars 937 forks source link

surface.get_current_texture blocks for the duration of fullscreen animation on macOS #5613

Open ItsSunnyMonster opened 7 months ago

ItsSunnyMonster commented 7 months ago

Description On macOS, the surface.get_current_texture function blocks after the user clicks the fullscreen button. It does not finish until the fullscreen animation is finished. This causes the entire app to hang while the fullscreen animation is happening, which means during the fullscreen animation the background moves but the window itself does not move. (see video below) On my laptop display (which is a 120hz retina display) after changing to fullscreen, it blocks for around 1.5 seconds again after the fullscreen animation is finished. The same does not happen when restoring from fullscreen. It also doesn't happen on my second monitor which is 60hz 1920x1080.

Repro steps https://github.com/ItsSunnyMonster/wgpu_blocking_repro_example This project will log an error to the console if surface.get_current_texture takes longer than 0.5 seconds.

Expected vs observed behavior surface.get_current_texture should not block when changing to fullscreen.

Extra materials

https://github.com/gfx-rs/wgpu/assets/100400733/11994bab-8721-4b5d-bd06-a44e05a5658a

Platform OS: macOS 14.4.1 CPU: Apple M1 Pro CPU 8 cores RAM: 16GB GPU: Apple M1 Pro GPU 14 cores wgpu: 0.19.4 backend: Metal

ItsSunnyMonster commented 6 months ago

Interestingly, I tried the same thing with the Vulkan backend on macOS, and instead of get_current_texture blocking, the queue.submit function blocks instead.

ItsSunnyMonster commented 4 months ago

As a bit of an update on this issue, here are some more information along with some things that needs to be done:

I don't know a lot about Metal, but I can take a guess that the reason why this is happening is when wgpu requests for a texture to render to during the fullscreen animation, macOS does not give it a texture until the animation is finished. But other details throw this theory off: as per my comment above, when using the Vulkan backend on macOS, queue.submit blocks instead of get_current_texture. Also, it also sometimes blocks for a second time right after the fullscreen animation finishes, as detailed on my first comment.