Reconfigure surface on present mode change (#6049)

# Objective

- Reconfigure surface after present mode changes. It seems that this is not done currently at runtime. It's pretty common for games to change such graphical settings at runtime.
- Fixes present mode issue in #5111 

## Solution

- Exactly like resolution change gets tracked when extracting window, do the same for present mode.

Additionally, I added present mode (vsync) toggling to window settings example.
This commit is contained in:
Okko Hakola 2022-09-21 22:35:15 +00:00
parent cd15f0f5be
commit 69d08c5ef4
2 changed files with 37 additions and 2 deletions

View file

@ -46,6 +46,7 @@ pub struct ExtractedWindow {
pub present_mode: PresentMode, pub present_mode: PresentMode,
pub swap_chain_texture: Option<TextureView>, pub swap_chain_texture: Option<TextureView>,
pub size_changed: bool, pub size_changed: bool,
pub present_mode_changed: bool,
} }
#[derive(Default, Resource)] #[derive(Default, Resource)]
@ -77,6 +78,7 @@ fn extract_windows(
window.physical_width().max(1), window.physical_width().max(1),
window.physical_height().max(1), window.physical_height().max(1),
); );
let new_present_mode = window.present_mode();
let mut extracted_window = let mut extracted_window =
extracted_windows extracted_windows
@ -89,12 +91,14 @@ fn extract_windows(
present_mode: window.present_mode(), present_mode: window.present_mode(),
swap_chain_texture: None, swap_chain_texture: None,
size_changed: false, size_changed: false,
present_mode_changed: false,
}); });
// NOTE: Drop the swap chain frame here // NOTE: Drop the swap chain frame here
extracted_window.swap_chain_texture = None; extracted_window.swap_chain_texture = None;
extracted_window.size_changed = new_width != extracted_window.physical_width extracted_window.size_changed = new_width != extracted_window.physical_width
|| new_height != extracted_window.physical_height; || new_height != extracted_window.physical_height;
extracted_window.present_mode_changed = new_present_mode != extracted_window.present_mode;
if extracted_window.size_changed { if extracted_window.size_changed {
debug!( debug!(
@ -107,6 +111,14 @@ fn extract_windows(
extracted_window.physical_width = new_width; extracted_window.physical_width = new_width;
extracted_window.physical_height = new_height; extracted_window.physical_height = new_height;
} }
if extracted_window.present_mode_changed {
debug!(
"Window Present Mode changed from {:?} to {:?}",
extracted_window.present_mode, new_present_mode
);
extracted_window.present_mode = new_present_mode;
}
} }
for closed_window in closed.iter() { for closed_window in closed.iter() {
extracted_windows.remove(&closed_window.id); extracted_windows.remove(&closed_window.id);
@ -174,8 +186,12 @@ pub fn prepare_windows(
}, },
}; };
// Do the initial surface configuration if it hasn't been configured yet // Do the initial surface configuration if it hasn't been configured yet. Or if size or
if window_surfaces.configured_windows.insert(window.id) || window.size_changed { // present mode changed.
if window_surfaces.configured_windows.insert(window.id)
|| window.size_changed
|| window.present_mode_changed
{
render_device.configure_surface(surface, &swap_chain_descriptor); render_device.configure_surface(surface, &swap_chain_descriptor);
} }

View file

@ -2,6 +2,7 @@
//! the mouse pointer in various ways. //! the mouse pointer in various ways.
use bevy::{prelude::*, window::PresentMode}; use bevy::{prelude::*, window::PresentMode};
use bevy_internal::diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin};
fn main() { fn main() {
App::new() App::new()
@ -13,12 +14,30 @@ fn main() {
..default() ..default()
}) })
.add_plugins(DefaultPlugins) .add_plugins(DefaultPlugins)
.add_plugin(LogDiagnosticsPlugin::default())
.add_plugin(FrameTimeDiagnosticsPlugin)
.add_system(change_title) .add_system(change_title)
.add_system(toggle_cursor) .add_system(toggle_cursor)
.add_system(toggle_vsync)
.add_system(cycle_cursor_icon) .add_system(cycle_cursor_icon)
.run(); .run();
} }
/// This system toggles the vsync mode when pressing the button V.
/// You'll see fps increase displayed in the console.
fn toggle_vsync(input: Res<Input<KeyCode>>, mut windows: ResMut<Windows>) {
if input.just_pressed(KeyCode::V) {
let window = windows.primary_mut();
window.set_present_mode(if matches!(window.present_mode(), PresentMode::AutoVsync) {
PresentMode::AutoNoVsync
} else {
PresentMode::AutoVsync
});
info!("PRESENT_MODE: {:?}", window.present_mode());
}
}
/// This system will then change the title during execution /// This system will then change the title during execution
fn change_title(time: Res<Time>, mut windows: ResMut<Windows>) { fn change_title(time: Res<Time>, mut windows: ResMut<Windows>) {
let window = windows.primary_mut(); let window = windows.primary_mut();