From 08eb5d95676a6f60a973b13ed72efd7fc4ad9f87 Mon Sep 17 00:00:00 2001 From: Eero Lehtinen Date: Sun, 17 Mar 2024 21:17:45 +0200 Subject: [PATCH] Fix crash on Linux Nvidia 550 driver --- crates/bevy_render/src/view/window/mod.rs | 66 ++++++++++++++--------- 1 file changed, 40 insertions(+), 26 deletions(-) diff --git a/crates/bevy_render/src/view/window/mod.rs b/crates/bevy_render/src/view/window/mod.rs index 64d089cee0f7ca..78d7ad1b459f05 100644 --- a/crates/bevy_render/src/view/window/mod.rs +++ b/crates/bevy_render/src/view/window/mod.rs @@ -304,38 +304,52 @@ pub fn prepare_windows( }) }; + // Nvidia 550.54.14 driver introduced a change, where it returns + // `wgpu::SurfaceError::Outdated` after the window is resized. The + // previous behaviour of returning no error seemed to have been a bug, + // but it didn't affect the application's functionality, so just ignore + // the error if it happens. + #[cfg(target_os = "linux")] + let ignore_outdated = || { + render_instance + .enumerate_adapters(wgpu::Backends::VULKAN) + .iter() + .any(|adapter| { + let info = adapter.get_info(); + info.name.starts_with("NVIDIA") && info.driver_info.starts_with("550") + }) + }; + let not_already_configured = window_surfaces.configured_windows.insert(window.entity); let surface = &surface_data.surface; if not_already_configured || window.size_changed || window.present_mode_changed { - let frame = surface - .get_current_texture() - .expect("Error configuring surface"); - window.set_swapchain_texture(frame); - } else { - match surface.get_current_texture() { - Ok(frame) => { - window.set_swapchain_texture(frame); - } - Err(wgpu::SurfaceError::Outdated) => { - render_device.configure_surface(surface, &surface_data.configuration); - let frame = surface - .get_current_texture() - .expect("Error reconfiguring surface"); - window.set_swapchain_texture(frame); - } - #[cfg(target_os = "linux")] - Err(wgpu::SurfaceError::Timeout) if may_erroneously_timeout() => { - bevy_utils::tracing::trace!( - "Couldn't get swap chain texture. This is probably a quirk \ + render_device.configure_surface(surface, &surface_data.configuration); + } + match surface.get_current_texture() { + Ok(frame) => { + window.set_swapchain_texture(frame); + } + #[cfg(target_os = "linux")] + Err(wgpu::SurfaceError::Outdated) if ignore_outdated() => {} + Err(wgpu::SurfaceError::Outdated) => { + render_device.configure_surface(surface, &surface_data.configuration); + let frame = surface + .get_current_texture() + .expect("Error reconfiguring surface"); + window.set_swapchain_texture(frame); + } + #[cfg(target_os = "linux")] + Err(wgpu::SurfaceError::Timeout) if may_erroneously_timeout() => { + bevy_utils::tracing::trace!( + "Couldn't get swap chain texture. This is probably a quirk \ of your Linux GPU driver, so it can be safely ignored." - ); - } - Err(err) => { - panic!("Couldn't get swap chain texture, operation unrecoverable: {err}"); - } + ); } - }; + Err(err) => { + panic!("Couldn't get swap chain texture, operation unrecoverable: {err}"); + } + } window.swap_chain_texture_format = Some(surface_data.configuration.format); if window.screenshot_func.is_some() {