summaryrefslogtreecommitdiff
path: root/graphics/src/timer.rs
diff options
context:
space:
mode:
Diffstat (limited to 'graphics/src/timer.rs')
-rw-r--r--graphics/src/timer.rs94
1 files changed, 49 insertions, 45 deletions
diff --git a/graphics/src/timer.rs b/graphics/src/timer.rs
index a8317c7..e2209c7 100644
--- a/graphics/src/timer.rs
+++ b/graphics/src/timer.rs
@@ -1,67 +1,71 @@
-use std::{
- ops::{Add, Div, Mul},
- time::{Duration, Instant},
-};
+use std::time::{Duration, Instant};
-/// How often to update the fps interval on screen
-const FPS_INTERVAL: Duration = Duration::from_millis(250);
-
-/// How much to smooth he `delta_avg` amount (`AVG_RATIO`:1)
-const AVG_RATIO: u32 = 10;
+/// Number of fps samples to store
+const MAX_SAMPLES: usize = 100;
/// Keeps track of frame intervals and FPS
pub struct Timer {
- /// Last time updated
previous: Instant,
- /// Current time
- now: Instant,
- /// Rolling delta time average
- delta_avg: Duration,
- /// Computed fps
- fps: f64,
- /// Last time the fps was updated
- fps_time: Instant,
- /// Frame count
- count: u32,
+ tick_index: usize,
+ tick_sum: Duration,
+ tick_list: Box<[Duration; MAX_SAMPLES]>,
+ frame: u32,
}
impl Timer {
pub fn new() -> Self {
- let now = Instant::now();
+ let previous = Instant::now();
+ let tick_index = 0usize;
+ let tick_sum = Duration::ZERO;
+ let tick_list = Box::new([tick_sum; MAX_SAMPLES]);
+ let frame = 0u32;
+
Self {
- previous: now,
- now,
- delta_avg: Duration::ZERO,
- fps: 0.0,
- fps_time: now,
- count: 0,
+ previous,
+ tick_index,
+ tick_sum,
+ tick_list,
+ frame,
}
}
pub fn update(&mut self) {
- self.previous = self.now;
- self.now = Instant::now();
- self.delta_avg = self
- .delta_avg
- .mul(AVG_RATIO)
- .add(self.delta_time())
- .div(AVG_RATIO + 1);
- if (self.now - self.fps_time) > FPS_INTERVAL {
- self.fps = 1.0 / self.delta_avg.as_secs_f64();
- self.fps_time = self.now;
- }
- self.count += 1;
+ let time = self.previous.elapsed();
+ self.previous = Instant::now();
+
+ // caculate average tick
+ self.tick_index += 1;
+ self.tick_index %= MAX_SAMPLES;
+ self.tick_sum -= self.tick_list[self.tick_index];
+ self.tick_sum += time;
+ self.tick_list[self.tick_index] = time;
+
+ // update frame frame
+ self.frame += 1;
}
- pub const fn get_frame(&self) -> u32 {
- self.count
+ pub const fn frame(&self) -> u32 {
+ self.frame
}
#[expect(clippy::cast_possible_truncation)]
- pub fn get_fps(&self) -> u32 {
- self.fps.ceil() as u32
+ pub const fn fps(&self) -> u32 {
+ match self.frame_time().as_nanos() {
+ 0 => u32::MAX,
+ // fps can never be bigger than u32::MAX since we're
+ // computing in nanoseconds
+ nanos => 1_000_000_000u128.div_ceil(nanos) as u32,
+ }
+ }
+
+ #[expect(clippy::cast_possible_truncation)]
+ pub const fn frame_time(&self) -> Duration {
+ match self.tick_sum.checked_div(MAX_SAMPLES as u32) {
+ Some(duration) => duration,
+ None => Duration::ZERO,
+ }
}
- pub fn delta_time(&self) -> Duration {
- self.now - self.previous
+ pub const fn delta_time(&self) -> Duration {
+ self.tick_list[self.tick_index]
}
}