Timing improvements

master
Mark 2024-01-10 19:47:30 -08:00
parent be2cca79b0
commit 188dc9eb89
Signed by: Mark
GPG Key ID: C6D63995FE72FD80
10 changed files with 100 additions and 35 deletions

1
Cargo.lock generated
View File

@ -714,6 +714,7 @@ dependencies = [
"crossbeam",
"galactica-content",
"galactica-galaxy",
"galactica-util",
"nalgebra",
"rand",
"rapier2d",

View File

@ -121,11 +121,11 @@ impl Game {
pub fn update(&mut self) {
let t: f32 = self.last_update.elapsed().as_secs_f32() * self.time_scale;
self.timing.start();
self.timing.start_frame();
self.timing.start_galaxy();
self.galaxy.step(t);
self.timing.mark_galaxy();
self.timing.start();
self.systemsim.step(StepResources {
player: self.player,
player_controls: ShipControls {
@ -137,9 +137,9 @@ impl Game {
ct: &self.content,
gx: &mut self.galaxy,
particles: &mut self.new_particles,
timing: &mut self.timing,
t,
});
self.timing.mark_physics();
if self.input.v_scroll != 0.0 {
self.camera.zoom = (self.camera.zoom + self.input.v_scroll).clamp(ZOOM_MIN, ZOOM_MAX);
@ -153,6 +153,7 @@ impl Game {
};
self.last_update = Instant::now();
self.timing.mark_frame();
}
pub fn get_frame_state(&mut self) -> RenderInput {
@ -166,7 +167,7 @@ impl Game {
player_data: self.player,
data: &self.galaxy,
current_system: SystemHandle { index: 0 },
timing: &self.timing,
timing: &mut self.timing,
}
}
}

View File

@ -41,7 +41,7 @@ pub struct RenderInput<'a> {
pub particles: &'a mut Vec<ParticleBuilder>,
/// Time we spent in each part of the game loop
pub timing: &'a Timing,
pub timing: &'a mut Timing,
}
/// Renderer state. A reference to this struct is often passed to helper functions.

View File

@ -19,7 +19,7 @@ use crate::{
impl super::GPUState {
/// Main render function. Draws sprites on a window.
pub fn render(&mut self, input: RenderInput) -> Result<(), wgpu::SurfaceError> {
// Set up text renderer
input.timing.start_render();
let output = self.surface.get_current_texture()?;
let view = output.texture.create_view(&Default::default());
@ -214,6 +214,7 @@ impl super::GPUState {
self.state.queue.submit(iter::once(encoder.finish()));
output.present();
input.timing.mark_render();
Ok(())
}
}

View File

@ -1,11 +1,9 @@
use glyphon::{Attrs, Buffer, Color, Family, Metrics, Shaping, TextArea, TextBounds};
use std::time::Instant;
use crate::{datastructs::RenderState, RenderInput};
pub(super) struct FpsIndicator {
buffer: Buffer,
last_update: Instant,
update_counter: u32,
}
@ -21,7 +19,6 @@ impl FpsIndicator {
Self {
buffer,
last_update: Instant::now(),
update_counter: 0,
}
}
@ -39,15 +36,16 @@ impl FpsIndicator {
self.buffer.set_text(
&mut state.text_font_system,
&format!(
"Game: {:.02?}\nPhys: {:.02?}\nRender: {:.02?}",
1.0 / input.timing.galaxy,
1.0 / input.timing.physics,
1.0 / (self.last_update.elapsed().as_secs_f32() / 100.0)
"Frame: {:04.02?}%\nGame: {:04.02?}%\nShips: {:04.02?}%\nPhys: {:04.02?}%\nRender: {:.02?}",
100.0 * (input.timing.frame / input.timing.render),
100.0 * (input.timing.galaxy / input.timing.frame),
100.0 * (input.timing.physics_sim / input.timing.frame),
100.0 * (input.timing.physics_ship / input.timing.frame),
1.0 / input.timing.render
),
Attrs::new().family(Family::SansSerif),
Attrs::new().family(Family::Monospace),
Shaping::Basic,
);
self.last_update = Instant::now();
}
pub fn get_textarea(&self) -> TextArea {

View File

@ -1,8 +1,7 @@
use glyphon::TextArea;
use crate::{datastructs::RenderState, RenderInput};
use super::{fpsindicator::FpsIndicator, radar::Radar, status::Status};
use crate::{datastructs::RenderState, RenderInput};
pub struct UiManager {
radar: Radar,
@ -26,7 +25,7 @@ impl UiManager {
self.fps.update(input, state);
}
pub fn get_textareas(&self) -> impl Iterator<Item = TextArea> {
(0..1).map(|_| self.fps.get_textarea())
pub fn get_textareas(&self) -> [TextArea; 1] {
[self.fps.get_textarea()]
}
}

View File

@ -19,6 +19,7 @@ workspace = true
[dependencies]
galactica-content = { workspace = true }
galactica-galaxy = { workspace = true }
galactica-util = { workspace = true }
rapier2d = { workspace = true }
nalgebra = { workspace = true }

View File

@ -1,6 +1,7 @@
use crate::{objects::ShipControls, ParticleBuilder};
use galactica_content::Content;
use galactica_galaxy::{Galaxy, GxShipHandle};
use galactica_util::timing::Timing;
/// External resources we need to compute time steps
#[derive(Debug)]
@ -22,4 +23,7 @@ pub struct StepResources<'a> {
/// The ship that the player controls
pub player: GxShipHandle,
/// Record detailed frame timing breakdown
pub timing: &'a mut Timing,
}

View File

@ -385,7 +385,11 @@ impl SystemSim {
/// Step this physics system by `t` seconds
pub fn step(&mut self, mut res: StepResources) {
res.timing.start_physics_ships();
self.step_ships(&mut res);
res.timing.mark_physics_ships();
res.timing.start_physics_sim();
// Update physics
self.wrapper.step(res.t, &self.collision_handler);
@ -457,6 +461,8 @@ impl SystemSim {
}
};
}
res.timing.mark_physics_sim();
}
}

View File

@ -3,42 +3,96 @@ use std::time::Instant;
/// Utility struct.
/// Keeps track of the time we spent in each part of the game loop.
#[derive(Debug)]
pub struct Timing {
timer: Option<Instant>,
/// The time we spent processing the whole frame
pub frame: f32,
frame_timer: Instant,
/// The time we spent simulating game state
pub galaxy: f32,
galaxy_timer: Instant,
/// The time we spent simulating physics
pub physics: f32,
pub physics_sim: f32,
physics_sim_timer: Instant,
/// The time we spent updating physics ships
pub physics_ship: f32,
physics_ship_timer: Instant,
/// The time we spent simulating physics
pub render: f32,
render_timer: Instant,
}
// TODO: macros
// TODO: document each duration
impl Timing {
/// Create a new timing struct
pub fn new() -> Self {
Self {
timer: None,
frame: f32::NAN,
galaxy: f32::NAN,
physics: f32::NAN,
physics_sim: f32::NAN,
physics_ship: f32::NAN,
render: f32::NAN,
galaxy_timer: Instant::now(),
physics_sim_timer: Instant::now(),
physics_ship_timer: Instant::now(),
render_timer: Instant::now(),
frame_timer: Instant::now(),
}
}
/// Start the timer
pub fn start(&mut self) {
self.timer = Some(Instant::now());
/// Start frame timer
pub fn start_frame(&mut self) {
self.frame_timer = Instant::now();
}
/// Clear timer and record galaxy simulation time.
/// Assumes timer has been started
/// Start galaxy timer
pub fn start_galaxy(&mut self) {
self.galaxy_timer = Instant::now();
}
/// Start physics sim timer
pub fn start_physics_sim(&mut self) {
self.physics_sim_timer = Instant::now();
}
/// Start physics ship timer
pub fn start_physics_ships(&mut self) {
self.physics_ship_timer = Instant::now();
}
/// Start render timer
pub fn start_render(&mut self) {
self.render_timer = Instant::now();
}
/// Record galaxy simulation time.
pub fn mark_frame(&mut self) {
self.frame = self.frame_timer.elapsed().as_secs_f32();
}
/// Record galaxy simulation time.
pub fn mark_galaxy(&mut self) {
self.galaxy = self.timer.unwrap().elapsed().as_secs_f32();
self.timer = None;
self.galaxy = self.galaxy_timer.elapsed().as_secs_f32();
}
/// Clear timer and record physics simulation time
/// Asumes timer has been started
pub fn mark_physics(&mut self) {
self.physics = self.timer.unwrap().elapsed().as_secs_f32();
self.timer = None;
/// Record physics simulation time
pub fn mark_physics_sim(&mut self) {
self.physics_sim = self.physics_sim_timer.elapsed().as_secs_f32();
}
/// Record physics ship update time
pub fn mark_physics_ships(&mut self) {
self.physics_ship = self.physics_ship_timer.elapsed().as_secs_f32();
}
/// Record physics simulation time
pub fn mark_render(&mut self) {
self.render = self.render_timer.elapsed().as_secs_f32();
}
}