# Objective
Opening and closing windows quickly on Linux could crash the renderer
with a `GPU resources not available` panic.
The `gpui_wgpu` renderer keeps its GPU resources in an `Option` that is
cleared when a window is torn down, and also while device-loss recovery
is pending. On Wayland the window's `Drop` releases those resources
synchronously but defers unregistering the surface to a later task, so a
compositor resize or transparency event can still reach the renderer in
that short gap. `update_drawable_size` and `update_transparency` assumed
the resources were always present and called an accessor that panics
when they are not.
I am not certain if there is a good case to reproduce this in zed, but I
had encountered it in my own GPUI app.
## Solution
Make `update_drawable_size` and `update_transparency` tolerate missing
GPU resources by skipping the surface reconfiguration instead of
panicking, matching how the rest of the renderer already guards this
state. The requested size and alpha mode are still recorded before the
guard, so they take effect if the renderer's resources are recreated,
for example after device-loss recovery.
## Testing
Tested on Linux with Wayland.
- Reproduced by opening and closing windows quickly, which previously
panicked with `GPU resources not available`. With this change the panic
no longer occurs. This was reproducible on a debug build or a weak/slow
device.
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [ ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
---
Release Notes (not sure if worth mentioning):
- Fixed a crash that could occur when opening and closing windows
quickly on Linux
Co-authored-by: Mikayla Maki <mikayla@zed.dev>
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [ ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Closes#32792Closes#38266Closes#54133
Release Notes:
- Fixed graphical corruption that could occur when using Wayland
----
**What**: Fixes flickering on Wayland (Sway/wlroots) under CPU load
(e.g. rust-analyzer running). The bug only reproduces in release builds
- debug builds are too slow to hit the race window.
Environment where this was reproduced: Intel GPU (both Xe KMD and i915),
Mesa 26.0.4, Sway 1.11.
**Why**: When wgpu presents a frame on Wayland+Vulkan, it calls
`vkQueuePresentKHR,` which - as required by the Vulkan spec -
synchronously issues `wl_surface.attach`, `wl_surface.damage`, and
`wl_surface.commit` to the compositor before returning. The commit also
picks up any pending frame callbacks.
Zed's `completed_frame()` independently calls `state.surface.commit()`.
This is a redundant second commit on the same surface. Under load, the
Wayland socket dispatch can be delayed enough that both commits are in
flight in close succession, and the ordering becomes timing-dependent.
When Zed's commit reaches the compositor before Mesa's attach+commit
sequence has been fully flushed, the compositor sees a commit with no
buffer attached, fires `wl_callback::Done` immediately, and Zed starts
the next frame too early - Mesa's real buffer arrives late, causing the
visible flicker.
Under no load, Mesa's synchronous commit consistently reaches the
compositor first, so the bug doesn't appear.
**Fix**: Track whether `renderer.draw()` actually called
`frame.present()`. When it did, Mesa owns the `wl_surface.commit()` for
that frame - skip Zed's commit in `completed_frame()`. Only commit
ourselves when wgpu didn't present (surface not configured, lost,
occluded, etc.) - in those cases Mesa won't commit, and we need to keep
the frame callback alive.
---------
Co-authored-by: Benjamin Laib <b5l@users.noreply.github.com>
Co-authored-by: John Tur <john-tur@outlook.com>
Updates #54349
There were two problems:
* The crash never happened, instead we'd always retry.
* When re-trying it seemed like we were picking llvmpipe. Claude's
suggestion was that immediately after wake, the real GPU isn't yet
awake, and so we pick llvm. Avoid this by disallowing llvmpipe on retry
Release Notes:
- linux: Reduced crash rate when recovering GPUs
We were assuming that `Bgra8Unorm` always works, which was causing the
panic on configurations that don't support it ("wgpu-hal invariant was
violated: Requested feature is not available on this device")
This change makes a proper fallback to `Rgba8Unorm`. In the worst case,
if a device doesn't support that as well (highly unlikely), we return a
proper error instead of a panic.
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Closes ZED-69S
Release Notes:
- Fixed panic on devices that don't support BGRA8
This should prevent the "wgpu-hal invariant was violated (usage error):
Requested feature is not available on this device" panic, although I'm
not 100% sure (there's a possibility that a device reports the feature
but fails to use it). At the very least, we get more logging
I've tested this fix by patching code to emulate a situation where
device features change after the creation, but that may be not
representative of the real world failure.
Addresses ZED-5G1
Release Notes:
- N/A
## Summary
- Add `unconfigure_surface()` and `replace_surface()` methods to
`WgpuRenderer` for mobile platform window lifecycle management
- Prefer `PresentMode::Mailbox` (triple-buffering) over `Fifo` to avoid
blocking during lifecycle transitions
- Early return in `draw()` when surface is unconfigured to prevent
driver hangs
## Motivation
On Android, the native window (`ANativeWindow`) is destroyed when the
app goes to the background and recreated when it returns to the
foreground. The same happens during orientation changes. Without surface
lifecycle methods, the only option is to destroy the entire
`WgpuRenderer` and create a new one on resume.
The problem: GPUI's scene cache holds `AtlasTextureId` references from
the old renderer's atlas. A new renderer has an empty atlas, so those
cached IDs cause index-out-of-bounds panics.
The fix: Keep the renderer (device, queue, atlas, pipelines) alive
across surface destruction. Only the wgpu `Surface` needs to be
replaced.
### `unconfigure_surface()`
Marks the surface as unconfigured so `draw()` skips rendering via the
existing `surface_configured` guard. Drops intermediate textures that
reference the old surface dimensions. The renderer stays fully alive.
### `replace_surface()`
Creates a new `wgpu::Surface` from fresh window handles using the
**same** `wgpu::Instance` that created the original adapter/device.
Reconfigures the surface and marks it as configured so rendering
resumes. All cached atlas textures remain valid.
### PresentMode::Mailbox
`Fifo` (VSync) blocks in `get_current_texture()` and can deadlock if the
compositor is frozen during a lifecycle transition (e.g.
`TerminateWindow` → `InitWindow` on Android). Mailbox (triple-buffering)
avoids this. Falls back to `AutoNoVsync` → `Fifo` if unsupported.
### draw() early return
Some drivers (notably Adreno) block indefinitely when acquiring a
texture from an unconfigured surface. The early return prevents this.
## Context
This is needed by
[gpui-mobile](https://github.com/itsbalamurali/gpui-mobile), a project
bringing GPUI to Android and iOS. The Android implementation needs these
methods to handle:
1. **Background/foreground transitions** — `TerminateWindow` destroys
the native window, `InitWindow` recreates it
2. **Orientation changes** — Surface is destroyed and recreated with new
dimensions
3. **Split-screen transitions** — Similar surface recreation
Without this change, we maintain a local fork of `gpui_wgpu` with just
these additions. Upstreaming them would let mobile platform
implementations use the official crate directly.
## Test plan
- [x] Tested on Android (Motorola, Adreno 720 GPU) — 3 consecutive
background/foreground cycles, zero panics, atlas textures preserved
- [x] Tested orientation changes (portrait→landscape→portrait) — surface
replacement completed in <40ms per rotation
- [x] Verified `draw()` correctly skips rendering when surface is
unconfigured
- [x] Verified no regression on desktop — methods are additive, existing
code paths unchanged
- [x] PresentMode fallback chain works on devices that don't support
Mailbox
## Release Notes
- N/A
## Summary
Implements the fix proposed by @israelrios in
https://github.com/zed-industries/zed/issues/50269#issuecomment-4049006746.
The issue comment narrowed the hang down to X11 window teardown:
- when the Settings window is closed on X11, the UI thread can stall
while `WgpuRenderer` is dropped during final `X11WindowState` teardown
- at that point, the X11 window has already been destroyed
- the proposed fix is to make `WgpuRenderer::destroy()` release
surface-bound GPU resources eagerly so the native window is destroyed
only after the `wgpu::Surface` and related resources are gone
This PR applies that change in `crates/gpui_wgpu/src/wgpu_renderer.rs`
by calling `self.resources.take()` inside `destroy()`.
## Validation
I confirmed this fix locally on Linux Mint 21.3 Cinnamon by applying it
to the `v0.227.1` build:
- opening and closing Settings no longer causes the main window to hang
## References
- Refs #50269
- Original analysis and fix proposal by @israelrios:
https://github.com/zed-industries/zed/issues/50269#issuecomment-4049006746
Release Notes:
- Fixed a Linux/X11 issue where closing the Settings window could cause
Zed to hang.
This uses the compositor hints if available to pick the best GPU. If
none is
available, it tries each GPU in turn, and the first that actually works
is chosen
Release Notes:
- Linux: Select a more appropriate GPU
---------
Co-authored-by: John Tur <john-tur@outlook.com>
Fixes Zed-5AW
Fixes Zed-5AP
Claude believes this is the right fix, but would love someone who knows
more about graphics than me to take a look: @reflectronic / @zortax?
The panic is:
```
wgpu error: Validation Error
Caused by:
In Texture::create_view
Texture with 'path_intermediate' label is invalid
gpui::platform::wgpu::wgpu_renderer::WgpuRenderer::create_path_intermediate (wgpu_renderer.rs:742)
gpui::platform::wgpu::wgpu_renderer::WgpuRenderer::update_drawable_size (wgpu_renderer.rs:784)
gpui::platform::linux::x11::window::X11WindowStatePtr::set_bounds (window.rs:1169)
gpui::platform::linux::x11::client::X11Client::handle_event (client.rs:902)
```
or:
```
wgpu error: Validation Error
Caused by:
In Texture::create_view
Texture with 'path_intermediate' label is invalid
gpui::platform::wgpu::wgpu_renderer::WgpuRenderer::create_path_intermediate (wgpu_renderer.rs:742)
gpui::platform::wgpu::wgpu_renderer::WgpuRenderer::new (wgpu_renderer.rs:274)
gpui::platform::linux::x11::window::X11WindowState::new::{{closure}} (window.rs:698)
gpui::platform::linux::x11::window::X11WindowState::new (window.rs:488)
gpui::platform::linux::x11::window::X11Window::new (window.rs:814)
gpui::platform::linux::x11::client::X11Client::open_window (client.rs:1514)
gpui::platform::linux::platform::<T>::open_window (platform.rs:289)
gpui::window::Window::new (window.rs:1119)
gpui::app::App::open_window::{{closure}} (app.rs:1025)
gpui::app::App::update (app.rs:835)
gpui::app::App::open_window (app.rs:1022)
```
I haven't seen a Wayland equivalent (not sure if that's because it
doesn't happen on Wayalnd or because I havent' seen it yet)
Release Notes:
- Linux: Fixed a panic in the new WPGU renderer during resize
Closes#49435
Before you mark this PR as ready for review, make sure that you have:
- [ ] Added a solid test coverage and/or screenshots from doing manual
testing
- [ ] Done a self-review taking into account security and performance
aspects
- [ ] Aligned any UI changes with the [UI
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
Release Notes:
- Linux: Reduced GPU memory usage during resize
Implements a basic web platform for the wasm32-unknown-unknown target
for gpui
Release Notes:
- N/A *or* Added/Fixed/Improved ...
---------
Co-authored-by: John Tur <john-tur@outlook.com>
Fixes ZED-54X
Release Notes:
- Linux: wait to request a graphics context until we have a window so we
can (ideally) pick a better context or (less ideally) fail more
gracefully.
---------
Co-authored-by: Zed Zippy <234243425+zed-zippy[bot]@users.noreply.github.com>
#2874 on steroids
Before you mark this PR as ready for review, make sure that you have:
- [ ] Added a solid test coverage and/or screenshots from doing manual
testing
- [ ] Done a self-review taking into account security and performance
aspects
- [ ] Aligned any UI changes with the [UI
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
Release Notes:
- N/A
---------
Co-authored-by: Eric Holk <eric@zed.dev>