recover from lost/outdated wgpu surface on Wayland#1074
Conversation
| } | ||
| let frame = match self.surface.get_current_texture() { | ||
| Ok(frame) => frame, | ||
| Err(wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated) => { |
There was a problem hiding this comment.
WebGpu examples also choose to handle wgpu::SurfaceError::Other and wgpu::SurfaceError::OutOfMemory. Not relevant on niri (from my testing), but it might help getting a present instead of a frozen mess in some other specific edge cases
they also choose to attempt a get again but I'm not that thoroughly versed in Vulkan to decide whether this or the other approach is better
There was a problem hiding this comment.
That's interesting. In the wgpu docs, it's described a bit differently:
Lost and Outdated are the two variants where wgpu itself explicitly recommends recreating the surface: https://docs.rs/wgpu/27.0.1/wgpu/enum.SurfaceError.html#variants
It seems in their example they opted for a broad "just reconfigure will fix it" catch-all approach, but it might make sense to only handle what's actually a surface configuration issue.
OOM shouldn't really try to recreate the surface if memory is starved (wouldn't be able to create a new frame anway - the comment in their example even says that), and Other would need to be inspected to decide what to do.
|
This looks good. Thanks! |
On some Wayland compositors like Niri, floem apps freeze on startup.
The first frame renders, then the window is visually frozen.
Inputs still work under the hood but nothing visually changes.
Resizing the window fixes it.
To reproduce, simply run any example on niri (I haven't tried any other WM).
-> Window is frozen, on resize, it works again.
This is same bug Zed had: Freezing on Start in Niri #50574
Their fix on their internal
gpui_wgpurenderer: Fix handling of surface.configure on Linux#50640In floem, for the vello and vger renderers,
finish()doesn't handle any Err Result fromsurface.get_current_texture(). On some Wayland compositors, the surface might be "lost" or "outdated" right after initial configuration, soget_current_texture()returns an error on the very first frame.SurfaceErrorin wgpu doesn't auto-recover, so all future frames also fail silently and the window appears frozen.Resizing unfreezes because the resize calls
surface.configure()and rebuilds.The fix is simply to handle
SurfaceError::Lost and SurfaceError::Outdatedby calling surface.configure() again, basically what Zed did:Note that this is also the cause of an open bug in Lapce: Lapce freezing on niri at startup #3897