Fix window size change panic (#2858)
# Objective Using fullscreen or trying to resize a window caused a panic. Fix that. ## Solution - Don't wholesale overwrite the ExtractedWindows resource when extracting windows - This could cause an accumulation of unused windows that are holding onto swap chain frames? - Check the if width and/or height changed since the last frame - If the size changed, recreate the swap chain - Ensure dimensions are >= 1 to avoid panics due to any dimension being 0
This commit is contained in:
parent
08969a24b8
commit
fb33d591df
@ -77,8 +77,8 @@ fn extract_cameras(
|
|||||||
ExtractedView {
|
ExtractedView {
|
||||||
projection: camera.projection_matrix,
|
projection: camera.projection_matrix,
|
||||||
transform: *transform,
|
transform: *transform,
|
||||||
width: window.physical_width(),
|
width: window.physical_width().max(1),
|
||||||
height: window.physical_height(),
|
height: window.physical_height().max(1),
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,11 @@ use crate::{
|
|||||||
render_resource::TextureView,
|
render_resource::TextureView,
|
||||||
renderer::{RenderDevice, RenderInstance},
|
renderer::{RenderDevice, RenderInstance},
|
||||||
texture::BevyDefault,
|
texture::BevyDefault,
|
||||||
RenderApp, RenderStage,
|
RenderApp, RenderStage, RenderWorld,
|
||||||
};
|
};
|
||||||
use bevy_app::{App, Plugin};
|
use bevy_app::{App, Plugin};
|
||||||
use bevy_ecs::prelude::*;
|
use bevy_ecs::prelude::*;
|
||||||
use bevy_utils::HashMap;
|
use bevy_utils::{tracing::debug, HashMap};
|
||||||
use bevy_window::{RawWindowHandleWrapper, WindowId, Windows};
|
use bevy_window::{RawWindowHandleWrapper, WindowId, Windows};
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use wgpu::TextureFormat;
|
use wgpu::TextureFormat;
|
||||||
@ -20,6 +20,7 @@ pub struct WindowRenderPlugin;
|
|||||||
impl Plugin for WindowRenderPlugin {
|
impl Plugin for WindowRenderPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.sub_app(RenderApp)
|
app.sub_app(RenderApp)
|
||||||
|
.init_resource::<ExtractedWindows>()
|
||||||
.init_resource::<WindowSurfaces>()
|
.init_resource::<WindowSurfaces>()
|
||||||
.init_resource::<NonSendMarker>()
|
.init_resource::<NonSendMarker>()
|
||||||
.add_system_to_stage(RenderStage::Extract, extract_windows)
|
.add_system_to_stage(RenderStage::Extract, extract_windows)
|
||||||
@ -34,6 +35,7 @@ pub struct ExtractedWindow {
|
|||||||
pub physical_height: u32,
|
pub physical_height: u32,
|
||||||
pub vsync: bool,
|
pub vsync: bool,
|
||||||
pub swap_chain_frame: Option<TextureView>,
|
pub swap_chain_frame: Option<TextureView>,
|
||||||
|
pub size_changed: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
@ -55,23 +57,44 @@ impl DerefMut for ExtractedWindows {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extract_windows(mut commands: Commands, windows: Res<Windows>) {
|
fn extract_windows(mut render_world: ResMut<RenderWorld>, windows: Res<Windows>) {
|
||||||
let mut extracted_windows = ExtractedWindows::default();
|
let mut extracted_windows = render_world.get_resource_mut::<ExtractedWindows>().unwrap();
|
||||||
for window in windows.iter() {
|
for window in windows.iter() {
|
||||||
extracted_windows.insert(
|
let (new_width, new_height) = (
|
||||||
window.id(),
|
window.physical_width().max(1),
|
||||||
ExtractedWindow {
|
window.physical_height().max(1),
|
||||||
id: window.id(),
|
|
||||||
handle: window.raw_window_handle(),
|
|
||||||
physical_width: window.physical_width(),
|
|
||||||
physical_height: window.physical_height(),
|
|
||||||
vsync: window.vsync(),
|
|
||||||
swap_chain_frame: None,
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
commands.insert_resource(extracted_windows);
|
let mut extracted_window =
|
||||||
|
extracted_windows
|
||||||
|
.entry(window.id())
|
||||||
|
.or_insert(ExtractedWindow {
|
||||||
|
id: window.id(),
|
||||||
|
handle: window.raw_window_handle(),
|
||||||
|
physical_width: new_width,
|
||||||
|
physical_height: new_height,
|
||||||
|
vsync: window.vsync(),
|
||||||
|
swap_chain_frame: None,
|
||||||
|
size_changed: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
// NOTE: Drop the swap chain frame here
|
||||||
|
extracted_window.swap_chain_frame = None;
|
||||||
|
extracted_window.size_changed = new_width != extracted_window.physical_width
|
||||||
|
|| new_height != extracted_window.physical_height;
|
||||||
|
|
||||||
|
if extracted_window.size_changed {
|
||||||
|
debug!(
|
||||||
|
"Window size changed from {}x{} to {}x{}",
|
||||||
|
extracted_window.physical_width,
|
||||||
|
extracted_window.physical_height,
|
||||||
|
new_width,
|
||||||
|
new_height
|
||||||
|
);
|
||||||
|
extracted_window.physical_width = new_width;
|
||||||
|
extracted_window.physical_height = new_height;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
@ -111,6 +134,13 @@ pub fn prepare_windows(
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if window.size_changed {
|
||||||
|
window_surfaces.swap_chains.insert(
|
||||||
|
window.id,
|
||||||
|
render_device.create_swap_chain(surface, &swap_chain_descriptor),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let swap_chain = window_surfaces
|
let swap_chain = window_surfaces
|
||||||
.swap_chains
|
.swap_chains
|
||||||
.entry(window.id)
|
.entry(window.id)
|
||||||
|
Loading…
Reference in New Issue
Block a user