diff --git a/crates/gpui_wgpu/src/wgpu_renderer.rs b/crates/gpui_wgpu/src/wgpu_renderer.rs index 2a56a10036b4daf97e0588027671c70264a1f758..43b0c171e242c0a1e335869e899a0bc95fed3e46 100644 --- a/crates/gpui_wgpu/src/wgpu_renderer.rs +++ b/crates/gpui_wgpu/src/wgpu_renderer.rs @@ -8,7 +8,7 @@ use gpui::{ use log::warn; use raw_window_handle::{HasDisplayHandle, HasWindowHandle}; use std::num::NonZeroU64; -use std::sync::Arc; +use std::sync::{Arc, Mutex}; #[repr(C)] #[derive(Clone, Copy, Pod, Zeroable)] @@ -117,6 +117,8 @@ pub struct WgpuRenderer { transparent_alpha_mode: wgpu::CompositeAlphaMode, opaque_alpha_mode: wgpu::CompositeAlphaMode, max_texture_size: u32, + last_error: Arc>>, + failed_frame_count: u32, } impl WgpuRenderer { @@ -336,6 +338,13 @@ impl WgpuRenderer { let adapter_info = context.adapter.get_info(); + let last_error: Arc>> = Arc::new(Mutex::new(None)); + let last_error_clone = Arc::clone(&last_error); + device.on_uncaptured_error(Arc::new(move |error| { + let mut guard = last_error_clone.lock().unwrap(); + *guard = Some(error.to_string()); + })); + Ok(Self { device, queue, @@ -365,6 +374,8 @@ impl WgpuRenderer { transparent_alpha_mode, opaque_alpha_mode, max_texture_size, + last_error, + failed_frame_count: 0, }) } @@ -897,6 +908,20 @@ impl WgpuRenderer { } pub fn draw(&mut self, scene: &Scene) { + let last_error = self.last_error.lock().unwrap().take(); + if let Some(error) = last_error { + self.failed_frame_count += 1; + log::error!( + "GPU error during frame (failure {} of 20): {error}", + self.failed_frame_count + ); + if self.failed_frame_count > 20 { + panic!("Too many consecutive GPU errors. Last error: {error}"); + } + } else { + self.failed_frame_count = 0; + } + self.atlas.before_frame(); let frame = match self.surface.get_current_texture() {