From 38f233e616697e6ac26822b93896dc1d495236a0 Mon Sep 17 00:00:00 2001 From: tyler274 Date: Mon, 10 Mar 2025 18:58:28 -0400 Subject: [PATCH 1/3] Fix surface validation errors in WSL2 environments during window resizing --- .../bevy_render/src/renderer/render_device.rs | 1 + crates/bevy_render/src/view/window/mod.rs | 86 ++++++++++++++++++- 2 files changed, 85 insertions(+), 2 deletions(-) diff --git a/crates/bevy_render/src/renderer/render_device.rs b/crates/bevy_render/src/renderer/render_device.rs index d33139745baf8..400d0765e29dd 100644 --- a/crates/bevy_render/src/renderer/render_device.rs +++ b/crates/bevy_render/src/renderer/render_device.rs @@ -250,6 +250,7 @@ impl RenderDevice { /// - A old [`SurfaceTexture`](wgpu::SurfaceTexture) is still alive referencing an old surface. /// - Texture format requested is unsupported on the surface. pub fn configure_surface(&self, surface: &wgpu::Surface, config: &wgpu::SurfaceConfiguration) { + // We're now letting the caller decide how to handle errors surface.configure(&self.device, config); } diff --git a/crates/bevy_render/src/view/window/mod.rs b/crates/bevy_render/src/view/window/mod.rs index 14a984ff3921e..f1349d36e626a 100644 --- a/crates/bevy_render/src/view/window/mod.rs +++ b/crates/bevy_render/src/view/window/mod.rs @@ -19,6 +19,9 @@ use wgpu::{ SurfaceConfiguration, SurfaceTargetUnsafe, TextureFormat, TextureUsages, TextureViewDescriptor, }; +#[cfg(target_os = "linux")] +use std::io::Read; + pub mod screenshot; use screenshot::{ScreenshotPlugin, ScreenshotToScreenPipeline}; @@ -193,6 +196,61 @@ impl WindowSurfaces { } } +/// Determines if the application is running in a Windows Subsystem for Linux (WSL) environment +#[cfg(target_os = "linux")] +fn is_running_in_wsl() -> bool { + // Check for the existence of /proc/sys/kernel/osrelease which should contain "microsoft" or "WSL" if running in WSL + if let Ok(mut file) = std::fs::File::open("/proc/sys/kernel/osrelease") { + let mut content = String::new(); + if file.read_to_string(&mut content).is_ok() { + let content_lower = content.to_lowercase(); + return content_lower.contains("microsoft") || content_lower.contains("wsl"); + } + } + false +} + +#[cfg(not(target_os = "linux"))] +fn is_running_in_wsl() -> bool { + false +} + +/// Captures a potential panic during surface configuration and logs it instead of crashing +/// This is especially useful for WSL2 environments where surface reconfiguration can fail +fn safely_configure_surface( + render_device: &RenderDevice, + surface: &wgpu::Surface, + config: &SurfaceConfiguration, + is_wsl: bool, +) { + if is_wsl { + // Use a closure to avoid polluting the backtrace with catch_unwind machinery + let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { + render_device.configure_surface(surface, config); + })); + + if let Err(panic_err) = result { + // Log the error but don't crash the application + if let Some(err_str) = panic_err.downcast_ref::() { + warn!("Failed to configure surface in WSL: {}", err_str); + } else if let Some(err_str) = panic_err.downcast_ref::<&str>() { + warn!("Failed to configure surface in WSL: {}", err_str); + } else { + warn!("Failed to configure surface in WSL (unknown error type)"); + } + + if let Some(err_str) = panic_err.downcast_ref::() { + if err_str.contains("Surface does not support the adapter's queue family") { + warn!("This is a known issue with Vulkan surfaces in WSL2 environments during window resizing"); + } + } + } + } else { + // Regular behavior for non-WSL environments + render_device.configure_surface(surface, config); + } +} + /// (re)configures window surfaces, and obtains a swapchain texture for rendering. /// /// NOTE: `get_current_texture` in `prepare_windows` can take a long time if the GPU workload is @@ -220,6 +278,9 @@ pub fn prepare_windows( render_device: Res, #[cfg(target_os = "linux")] render_instance: Res, ) { + // Detect if we're running in WSL + let is_wsl = is_running_in_wsl(); + for window in windows.windows.values_mut() { let window_surfaces = window_surfaces.deref_mut(); let Some(surface_data) = window_surfaces.surfaces.get(&window.entity) else { @@ -252,7 +313,14 @@ pub fn prepare_windows( window.set_swapchain_texture(frame); } Err(wgpu::SurfaceError::Outdated) => { - render_device.configure_surface(surface, &surface_data.configuration); + // Use our safe configuration function + safely_configure_surface( + &render_device, + surface, + &surface_data.configuration, + is_wsl, + ); + let frame = match surface.get_current_texture() { Ok(frame) => frame, Err(err) => { @@ -271,6 +339,10 @@ pub fn prepare_windows( of your Linux GPU driver, so it can be safely ignored." ); } + // Handle WSL-specific surface errors + Err(err) if is_wsl => { + warn!("Encountered surface error in WSL environment: {}. This may be due to WSL2 graphics compatibility issues. Graphics may be temporarily distorted but the application will continue.", err); + } Err(err) => { panic!("Couldn't get swap chain texture, operation unrecoverable: {err}"); } @@ -313,6 +385,14 @@ pub fn create_surfaces( render_adapter: Res, render_device: Res, ) { + // Detect if we're running in WSL + let is_wsl = is_running_in_wsl(); + if is_wsl { + debug!( + "Detected WSL environment - enabling special handling for window surface operations" + ); + } + for window in windows.windows.values() { let data = window_surfaces .surfaces @@ -400,7 +480,9 @@ pub fn create_surfaces( PresentMode::AutoVsync => wgpu::PresentMode::AutoVsync, PresentMode::AutoNoVsync => wgpu::PresentMode::AutoNoVsync, }; - render_device.configure_surface(&data.surface, &data.configuration); + + // Configure surface with special WSL handling if needed + safely_configure_surface(&render_device, &data.surface, &data.configuration, is_wsl); } window_surfaces.configured_windows.insert(window.entity); From 60bc2b5412856776e3a804a3d4d989dd62844f8c Mon Sep 17 00:00:00 2001 From: Tyler Date: Tue, 11 Mar 2025 16:00:25 -0400 Subject: [PATCH 2/3] Update crates/bevy_render/src/view/window/mod.rs Co-authored-by: Alice Cecile --- crates/bevy_render/src/view/window/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_render/src/view/window/mod.rs b/crates/bevy_render/src/view/window/mod.rs index f1349d36e626a..913c1dc9641d6 100644 --- a/crates/bevy_render/src/view/window/mod.rs +++ b/crates/bevy_render/src/view/window/mod.rs @@ -225,7 +225,7 @@ fn safely_configure_surface( ) { if is_wsl { // Use a closure to avoid polluting the backtrace with catch_unwind machinery - let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { + let result = core::panic::catch_unwind(core::panic::AssertUnwindSafe(|| { render_device.configure_surface(surface, config); })); From dce0bbf36b25e4dae9b657e14a16a54df435cc77 Mon Sep 17 00:00:00 2001 From: Tyler Date: Tue, 11 Mar 2025 16:09:42 -0400 Subject: [PATCH 3/3] point to right module --- crates/bevy_render/src/view/window/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_render/src/view/window/mod.rs b/crates/bevy_render/src/view/window/mod.rs index 913c1dc9641d6..d2b69604baa5e 100644 --- a/crates/bevy_render/src/view/window/mod.rs +++ b/crates/bevy_render/src/view/window/mod.rs @@ -225,7 +225,7 @@ fn safely_configure_surface( ) { if is_wsl { // Use a closure to avoid polluting the backtrace with catch_unwind machinery - let result = core::panic::catch_unwind(core::panic::AssertUnwindSafe(|| { + let result = core::intrinsics::catch_unwind(core::panic::AssertUnwindSafe(|| { render_device.configure_surface(surface, config); }));