mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 15:14:50 +00:00
Fix crash on Linux Nvidia 550 driver (#12542)
# Objective Fix crashing on Linux with latest stable Nvidia 550 driver when resizing. The crash happens at startup with some setups. Fixes #12199 I think this would be nice to get into 0.13.1 ## Solution Ignore `wgpu::SurfaceError::Outdated` always on this platform+driver. It looks like Nvidia considered the previous behaviour of not returning this error a bug: "Fixed a bug where vkAcquireNextImageKHR() was not returning VK_ERROR_OUT_OF_DATE_KHR when it should with WSI X11 swapchains" (https://www.nvidia.com/Download/driverResults.aspx/218826/en-us/) What I gather from this is that the surface was outdated on previous drivers too, but they just didn't report it as an error. So behaviour shouldn't change. In the issue conversation we experimented with calling `continue` when this error happens, but I found that it results in some small issues like bevy_egui scale not updating with the window sometimes. Just doing nothing seems to work better. ## Changelog - Fixed crashing on Linux with Nvidia 550 driver when resizing the window ## Migration Guide --------- Co-authored-by: James Liu <contact@jamessliu.com>
This commit is contained in:
parent
3e1c84690b
commit
70c69cdd51
1 changed files with 31 additions and 4 deletions
|
@ -8,6 +8,8 @@ use crate::{
|
||||||
};
|
};
|
||||||
use bevy_app::{App, Plugin};
|
use bevy_app::{App, Plugin};
|
||||||
use bevy_ecs::{entity::EntityHashMap, prelude::*};
|
use bevy_ecs::{entity::EntityHashMap, prelude::*};
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
use bevy_utils::warn_once;
|
||||||
use bevy_utils::{default, tracing::debug, HashSet};
|
use bevy_utils::{default, tracing::debug, HashSet};
|
||||||
use bevy_window::{
|
use bevy_window::{
|
||||||
CompositeAlphaMode, PresentMode, PrimaryWindow, RawHandleWrapper, Window, WindowClosed,
|
CompositeAlphaMode, PresentMode, PrimaryWindow, RawHandleWrapper, Window, WindowClosed,
|
||||||
|
@ -216,6 +218,9 @@ impl WindowSurfaces {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
const NVIDIA_VENDOR_ID: u32 = 0x10DE;
|
||||||
|
|
||||||
/// (re)configures window surfaces, and obtains a swapchain texture for rendering.
|
/// (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
|
/// NOTE: `get_current_texture` in `prepare_windows` can take a long time if the GPU workload is
|
||||||
|
@ -304,19 +309,41 @@ pub fn prepare_windows(
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
let is_nvidia = || {
|
||||||
|
render_instance
|
||||||
|
.enumerate_adapters(wgpu::Backends::VULKAN)
|
||||||
|
.iter()
|
||||||
|
.any(|adapter| adapter.get_info().vendor & 0xFFFF == NVIDIA_VENDOR_ID)
|
||||||
|
};
|
||||||
|
|
||||||
let not_already_configured = window_surfaces.configured_windows.insert(window.entity);
|
let not_already_configured = window_surfaces.configured_windows.insert(window.entity);
|
||||||
|
|
||||||
let surface = &surface_data.surface;
|
let surface = &surface_data.surface;
|
||||||
if not_already_configured || window.size_changed || window.present_mode_changed {
|
if not_already_configured || window.size_changed || window.present_mode_changed {
|
||||||
let frame = surface
|
match surface.get_current_texture() {
|
||||||
.get_current_texture()
|
Ok(frame) => window.set_swapchain_texture(frame),
|
||||||
.expect("Error configuring surface");
|
#[cfg(target_os = "linux")]
|
||||||
window.set_swapchain_texture(frame);
|
Err(wgpu::SurfaceError::Outdated) if is_nvidia() => {
|
||||||
|
warn_once!(
|
||||||
|
"Couldn't get swap chain texture. This often happens with \
|
||||||
|
the NVIDIA drivers on Linux. It can be safely ignored."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Err(err) => panic!("Error configuring surface: {err}"),
|
||||||
|
};
|
||||||
} else {
|
} else {
|
||||||
match surface.get_current_texture() {
|
match surface.get_current_texture() {
|
||||||
Ok(frame) => {
|
Ok(frame) => {
|
||||||
window.set_swapchain_texture(frame);
|
window.set_swapchain_texture(frame);
|
||||||
}
|
}
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
Err(wgpu::SurfaceError::Outdated) if is_nvidia() => {
|
||||||
|
warn_once!(
|
||||||
|
"Couldn't get swap chain texture. This often happens with \
|
||||||
|
the Nvidia 550 driver. It can be safely ignored."
|
||||||
|
);
|
||||||
|
}
|
||||||
Err(wgpu::SurfaceError::Outdated) => {
|
Err(wgpu::SurfaceError::Outdated) => {
|
||||||
render_device.configure_surface(surface, &surface_data.configuration);
|
render_device.configure_surface(surface, &surface_data.configuration);
|
||||||
let frame = surface
|
let frame = surface
|
||||||
|
|
Loading…
Reference in a new issue