mirror of
https://github.com/zed-industries/zed.git
synced 2026-05-25 23:04:27 +00:00
gpui_linux: Force scene rebuild after GPU device recovery (#52389)
After GPU device recovery clears the atlas, the next frame could re-present a stale scene via the needs_present path (which skips scene rebuilding). The stale scene references texture IDs that no longer exist in the cleared atlas, causing an index-out-of-bounds panic. Fix this by setting a force_render_after_recovery flag when device recovery completes. The platform refresh loop reads this flag and passes force_render: true in RequestFrameOptions, ensuring GPUI rebuilds the scene before presenting. Fixes ZED-5QT Release Notes: - N/A or Added/Fixed/Improved ...
This commit is contained in:
parent
9973a349a4
commit
dbd95ea742
4 changed files with 21 additions and 6 deletions
|
|
@ -116,6 +116,7 @@ pub struct WaylandWindowState {
|
||||||
handle: AnyWindowHandle,
|
handle: AnyWindowHandle,
|
||||||
active: bool,
|
active: bool,
|
||||||
hovered: bool,
|
hovered: bool,
|
||||||
|
pub(crate) force_render_after_recovery: bool,
|
||||||
in_progress_configure: Option<InProgressConfigure>,
|
in_progress_configure: Option<InProgressConfigure>,
|
||||||
resize_throttle: bool,
|
resize_throttle: bool,
|
||||||
in_progress_window_controls: Option<WindowControls>,
|
in_progress_window_controls: Option<WindowControls>,
|
||||||
|
|
@ -389,6 +390,7 @@ impl WaylandWindowState {
|
||||||
handle,
|
handle,
|
||||||
active: false,
|
active: false,
|
||||||
hovered: false,
|
hovered: false,
|
||||||
|
force_render_after_recovery: false,
|
||||||
in_progress_window_controls: None,
|
in_progress_window_controls: None,
|
||||||
window_controls: WindowControls::default(),
|
window_controls: WindowControls::default(),
|
||||||
client_inset: None,
|
client_inset: None,
|
||||||
|
|
@ -570,11 +572,16 @@ impl WaylandWindowStatePtr {
|
||||||
let mut state = self.state.borrow_mut();
|
let mut state = self.state.borrow_mut();
|
||||||
state.surface.frame(&state.globals.qh, state.surface.id());
|
state.surface.frame(&state.globals.qh, state.surface.id());
|
||||||
state.resize_throttle = false;
|
state.resize_throttle = false;
|
||||||
|
let force_render = state.force_render_after_recovery;
|
||||||
|
state.force_render_after_recovery = false;
|
||||||
drop(state);
|
drop(state);
|
||||||
|
|
||||||
let mut cb = self.callbacks.borrow_mut();
|
let mut cb = self.callbacks.borrow_mut();
|
||||||
if let Some(fun) = cb.request_frame.as_mut() {
|
if let Some(fun) = cb.request_frame.as_mut() {
|
||||||
fun(Default::default());
|
fun(RequestFrameOptions {
|
||||||
|
force_render,
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1372,6 +1379,7 @@ impl PlatformWindow for WaylandWindow {
|
||||||
|
|
||||||
// The current scene references atlas textures that were cleared during recovery.
|
// The current scene references atlas textures that were cleared during recovery.
|
||||||
// Skip this frame and let the next frame rebuild the scene with fresh textures.
|
// Skip this frame and let the next frame rebuild the scene with fresh textures.
|
||||||
|
state.force_render_after_recovery = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1883,11 +1883,14 @@ impl X11ClientState {
|
||||||
if let Some(window) = state.windows.get_mut(&x_window) {
|
if let Some(window) = state.windows.get_mut(&x_window) {
|
||||||
let expose_event_received = window.expose_event_received;
|
let expose_event_received = window.expose_event_received;
|
||||||
window.expose_event_received = false;
|
window.expose_event_received = false;
|
||||||
|
let force_render = std::mem::take(
|
||||||
|
&mut window.window.state.borrow_mut().force_render_after_recovery,
|
||||||
|
);
|
||||||
let window = window.window.clone();
|
let window = window.window.clone();
|
||||||
drop(state);
|
drop(state);
|
||||||
window.refresh(RequestFrameOptions {
|
window.refresh(RequestFrameOptions {
|
||||||
require_presentation: expose_event_received,
|
require_presentation: expose_event_received,
|
||||||
force_render: false,
|
force_render,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
xcb_connection
|
xcb_connection
|
||||||
|
|
|
||||||
|
|
@ -277,6 +277,7 @@ pub struct X11WindowState {
|
||||||
hidden: bool,
|
hidden: bool,
|
||||||
active: bool,
|
active: bool,
|
||||||
hovered: bool,
|
hovered: bool,
|
||||||
|
pub(crate) force_render_after_recovery: bool,
|
||||||
fullscreen: bool,
|
fullscreen: bool,
|
||||||
client_side_decorations_supported: bool,
|
client_side_decorations_supported: bool,
|
||||||
decorations: WindowDecorations,
|
decorations: WindowDecorations,
|
||||||
|
|
@ -750,6 +751,7 @@ impl X11WindowState {
|
||||||
input_handler: None,
|
input_handler: None,
|
||||||
active: false,
|
active: false,
|
||||||
hovered: false,
|
hovered: false,
|
||||||
|
force_render_after_recovery: false,
|
||||||
fullscreen: false,
|
fullscreen: false,
|
||||||
maximized_vertical: false,
|
maximized_vertical: false,
|
||||||
maximized_horizontal: false,
|
maximized_horizontal: false,
|
||||||
|
|
@ -1637,6 +1639,7 @@ impl PlatformWindow for X11Window {
|
||||||
|
|
||||||
// The current scene references atlas textures that were cleared during recovery.
|
// The current scene references atlas textures that were cleared during recovery.
|
||||||
// Skip this frame and let the next frame rebuild the scene with fresh textures.
|
// Skip this frame and let the next frame rebuild the scene with fresh textures.
|
||||||
|
inner.force_render_after_recovery = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1143,10 +1143,11 @@ impl WindowsWindowInner {
|
||||||
fn draw_window(&self, handle: HWND, force_render: bool) -> Option<isize> {
|
fn draw_window(&self, handle: HWND, force_render: bool) -> Option<isize> {
|
||||||
let mut request_frame = self.state.callbacks.request_frame.take()?;
|
let mut request_frame = self.state.callbacks.request_frame.take()?;
|
||||||
|
|
||||||
// we are instructing gpui to force render a frame, this will
|
if force_render {
|
||||||
// re-populate all the gpu textures for us so we can resume drawing in
|
// Re-enable drawing after a device loss recovery. The forced render
|
||||||
// case we disabled drawing earlier due to a device loss
|
// will rebuild the scene with fresh atlas textures.
|
||||||
self.state.renderer.borrow_mut().mark_drawable();
|
self.state.renderer.borrow_mut().mark_drawable();
|
||||||
|
}
|
||||||
request_frame(RequestFrameOptions {
|
request_frame(RequestFrameOptions {
|
||||||
require_presentation: false,
|
require_presentation: false,
|
||||||
force_render,
|
force_render,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue