gpui_windows: Force scene rebuild after GPU device recovery

Same issue as on Linux: after device recovery clears the atlas, a
WM_PAINT arriving during the 200ms recovery sleep could call
draw_window with force_render=false, which unconditionally called
mark_drawable() (clearing skip_draws) and then presented a stale
scene against the empty atlas.

Fix this by adding a force_render_after_recovery flag to the window
state, set during handle_device_lost. The first draw_window call
after recovery reads this flag and forces a full scene rebuild,
matching the Linux approach.
This commit is contained in:
Lukas Wirth 2026-03-25 09:00:28 +01:00
parent 9bbdff43cc
commit 2e5d890e37
2 changed files with 9 additions and 4 deletions

View file

@ -1136,6 +1136,7 @@ impl WindowsWindowInner {
{
panic!("Device lost: {err}");
}
self.state.force_render_after_recovery.set(true);
Some(0)
}
@ -1143,10 +1144,12 @@ impl WindowsWindowInner {
fn draw_window(&self, handle: HWND, force_render: bool) -> Option<isize> {
let mut request_frame = self.state.callbacks.request_frame.take()?;
// we are instructing gpui to force render a frame, this will
// re-populate all the gpu textures for us so we can resume drawing in
// case we disabled drawing earlier due to a device loss
self.state.renderer.borrow_mut().mark_drawable();
let force_render = force_render || self.state.force_render_after_recovery.take();
if force_render {
// Re-enable drawing after a device loss recovery. The forced render
// will rebuild the scene with fresh atlas textures.
self.state.renderer.borrow_mut().mark_drawable();
}
request_frame(RequestFrameOptions {
require_presentation: false,
force_render,

View file

@ -59,6 +59,7 @@ pub struct WindowsWindowState {
pub hovered: Cell<bool>,
pub renderer: RefCell<DirectXRenderer>,
pub force_render_after_recovery: Cell<bool>,
pub click_state: ClickState,
pub current_cursor: Cell<Option<HCURSOR>>,
@ -149,6 +150,7 @@ impl WindowsWindowState {
last_reported_capslock: Cell::new(last_reported_capslock),
hovered: Cell::new(hovered),
renderer: RefCell::new(renderer),
force_render_after_recovery: Cell::new(false),
click_state,
current_cursor: Cell::new(current_cursor),
nc_button_pressed: Cell::new(nc_button_pressed),