From 69d08c5ef491cd2fb43486d254cc4745faa997ba Mon Sep 17 00:00:00 2001 From: Okko Hakola Date: Wed, 21 Sep 2022 22:35:15 +0000 Subject: [PATCH] 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. --- crates/bevy_render/src/view/window.rs | 20 ++++++++++++++++++-- examples/window/window_settings.rs | 19 +++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/crates/bevy_render/src/view/window.rs b/crates/bevy_render/src/view/window.rs index bba940680f..6fe1bc8627 100644 --- a/crates/bevy_render/src/view/window.rs +++ b/crates/bevy_render/src/view/window.rs @@ -46,6 +46,7 @@ pub struct ExtractedWindow { pub present_mode: PresentMode, pub swap_chain_texture: Option, pub size_changed: bool, + pub present_mode_changed: bool, } #[derive(Default, Resource)] @@ -77,6 +78,7 @@ fn extract_windows( window.physical_width().max(1), window.physical_height().max(1), ); + let new_present_mode = window.present_mode(); let mut extracted_window = extracted_windows @@ -89,12 +91,14 @@ fn extract_windows( present_mode: window.present_mode(), swap_chain_texture: None, size_changed: false, + present_mode_changed: false, }); // NOTE: Drop the swap chain frame here extracted_window.swap_chain_texture = None; extracted_window.size_changed = new_width != extracted_window.physical_width || new_height != extracted_window.physical_height; + extracted_window.present_mode_changed = new_present_mode != extracted_window.present_mode; if extracted_window.size_changed { debug!( @@ -107,6 +111,14 @@ fn extract_windows( extracted_window.physical_width = new_width; 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() { 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 - if window_surfaces.configured_windows.insert(window.id) || window.size_changed { + // Do the initial surface configuration if it hasn't been configured yet. Or if size or + // 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); } diff --git a/examples/window/window_settings.rs b/examples/window/window_settings.rs index 5bda8151b7..c06153ce15 100644 --- a/examples/window/window_settings.rs +++ b/examples/window/window_settings.rs @@ -2,6 +2,7 @@ //! the mouse pointer in various ways. use bevy::{prelude::*, window::PresentMode}; +use bevy_internal::diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin}; fn main() { App::new() @@ -13,12 +14,30 @@ fn main() { ..default() }) .add_plugins(DefaultPlugins) + .add_plugin(LogDiagnosticsPlugin::default()) + .add_plugin(FrameTimeDiagnosticsPlugin) .add_system(change_title) .add_system(toggle_cursor) + .add_system(toggle_vsync) .add_system(cycle_cursor_icon) .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>, mut windows: ResMut) { + 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 fn change_title(time: Res