diff --git a/CHANGELOG.md b/CHANGELOG.md index 40a27cf9fa..b2b5d68eb9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -152,6 +152,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed an issue where prices weren't properly making their way from econsim to the actual trade values. - Fixed entities with voxel colliders being off by one physics tick for collision. - Airships no longer oscillate dramatically into the sky due to mistaking velocity for acceleration. +- The login and character selection screens no longer cause high GPU usage when the framerate limit is set to Unlimited. ## [0.9.0] - 2021-03-20 diff --git a/voxygen/src/lib.rs b/voxygen/src/lib.rs index ae15b7a07d..4d2a1a04dd 100644 --- a/voxygen/src/lib.rs +++ b/voxygen/src/lib.rs @@ -132,6 +132,9 @@ pub trait PlayState { /// Get a descriptive name for this state type. fn name(&self) -> &'static str; + /// Determines whether the play state should have an enforced FPS cap + fn capped_fps(&self) -> bool; + /// Draw the play state. fn render(&mut self, renderer: &mut Renderer, settings: &Settings); } diff --git a/voxygen/src/menu/char_selection/mod.rs b/voxygen/src/menu/char_selection/mod.rs index 2b9acd78b6..4b8093bc8e 100644 --- a/voxygen/src/menu/char_selection/mod.rs +++ b/voxygen/src/menu/char_selection/mod.rs @@ -232,6 +232,8 @@ impl PlayState for CharSelectionState { fn name(&self) -> &'static str { "Character Selection" } + fn capped_fps(&self) -> bool { true } + fn render(&mut self, renderer: &mut Renderer, _: &Settings) { let mut drawer = match renderer .start_recording_frame(self.scene.global_bind_group()) diff --git a/voxygen/src/menu/main/mod.rs b/voxygen/src/menu/main/mod.rs index 0aa482913d..ca4bd328a4 100644 --- a/voxygen/src/menu/main/mod.rs +++ b/voxygen/src/menu/main/mod.rs @@ -317,6 +317,8 @@ impl PlayState for MainMenuState { fn name(&self) -> &'static str { "Title" } + fn capped_fps(&self) -> bool { true } + fn render(&mut self, renderer: &mut Renderer, _: &Settings) { let mut drawer = match renderer .start_recording_frame(self.scene.global_bind_group()) diff --git a/voxygen/src/run.rs b/voxygen/src/run.rs index f1711dfc6a..35137ecad0 100644 --- a/voxygen/src/run.rs +++ b/voxygen/src/run.rs @@ -164,12 +164,15 @@ fn handle_main_events_cleared( *control_flow = winit::event_loop::ControlFlow::Exit; } + let mut capped_fps = false; + drop(guard); if let Some(last) = states.last_mut() { span!(guard, "Render"); let renderer = global_state.window.renderer_mut(); // Render the screen using the global renderer last.render(renderer, &global_state.settings); + capped_fps = last.capped_fps(); drop(guard); } @@ -177,9 +180,21 @@ fn handle_main_events_cleared( if !exit { // Wait for the next tick. span!(guard, "Main thread sleep"); - global_state.clock.set_target_dt(Duration::from_secs_f64( - 1.0 / get_fps(global_state.settings.graphics.max_fps) as f64, - )); + + // Enforce an FPS cap for the non-game session play states to prevent them + // running at hundreds/thousands of FPS resulting in high GPU usage for + // effectively doing nothing. + let max_fps = get_fps(global_state.settings.graphics.max_fps); + const TITLE_SCREEN_FPS_CAP: u32 = 60; + let target_fps = if capped_fps { + u32::min(TITLE_SCREEN_FPS_CAP, max_fps) + } else { + max_fps + }; + + global_state + .clock + .set_target_dt(Duration::from_secs_f64(1.0 / target_fps as f64)); global_state.clock.tick(); drop(guard); #[cfg(feature = "tracy")] diff --git a/voxygen/src/session/mod.rs b/voxygen/src/session/mod.rs index 4cf91a6171..32c584af77 100644 --- a/voxygen/src/session/mod.rs +++ b/voxygen/src/session/mod.rs @@ -1387,6 +1387,8 @@ impl PlayState for SessionState { fn name(&self) -> &'static str { "Session" } + fn capped_fps(&self) -> bool { false } + /// Render the session to the screen. /// /// This method should be called once per frame.