chore: add timing demo bin

This commit is contained in:
Ryan Walters
2025-09-03 17:23:20 -05:00
parent 0907b5ebe7
commit a489bff0d1
2 changed files with 92 additions and 0 deletions

View File

@@ -13,6 +13,7 @@ keywords = ["game", "pacman", "arcade", "sdl2"]
categories = ["games", "emulators"] categories = ["games", "emulators"]
publish = false publish = false
exclude = ["/assets/unpacked/**", "/assets/site/**", "/bacon.toml", "/Justfile"] exclude = ["/assets/unpacked/**", "/assets/site/**", "/bacon.toml", "/Justfile"]
default-run = "pacman"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

91
src/bin/timing_demo.rs Normal file
View File

@@ -0,0 +1,91 @@
use circular_buffer::CircularBuffer;
use pacman::constants::CANVAS_SIZE;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::pixels::Color;
use std::time::{Duration, Instant};
fn main() -> Result<(), String> {
let sdl_context = sdl2::init()?;
let video_subsystem = sdl_context.video()?;
let window = video_subsystem
.window("SDL2 Timing Demo", CANVAS_SIZE.x, CANVAS_SIZE.y)
.opengl()
.position_centered()
.build()
.map_err(|e| e.to_string())?;
let mut canvas = window.into_canvas().accelerated().build().map_err(|e| e.to_string())?;
canvas
.set_logical_size(CANVAS_SIZE.x, CANVAS_SIZE.y)
.map_err(|e| e.to_string())?;
let mut event_pump = sdl_context.event_pump()?;
// Store frame timings in milliseconds
let mut frame_timings = CircularBuffer::<20_000, f64>::new();
let mut last_report_time = Instant::now();
let report_interval = Duration::from_millis(500);
'running: loop {
let frame_start_time = Instant::now();
for event in event_pump.poll_iter() {
match event {
Event::Quit { .. }
| Event::KeyDown {
keycode: Some(Keycode::Escape),
..
} => {
break 'running;
}
_ => {}
}
}
// Clear the screen
canvas.set_draw_color(Color::RGB(0, 0, 0));
canvas.clear();
canvas.present();
// Record timing
let frame_duration = frame_start_time.elapsed();
frame_timings.push_back(frame_duration.as_secs_f64());
// Report stats every `report_interval`
let elapsed = last_report_time.elapsed();
if elapsed >= report_interval {
if !frame_timings.is_empty() {
let count = frame_timings.len() as f64;
let sum: f64 = frame_timings.iter().sum();
let mean = sum / count;
let variance = frame_timings
.iter()
.map(|value| {
let diff = mean - value;
diff * diff
})
.sum::<f64>()
/ count;
let std_dev = variance.sqrt();
println!(
"Rendered {count} frames at {fps:.1} fps (last {elapsed:.2?}): mean={mean:.3?}, std_dev={std_dev:.3?}",
count = frame_timings.len(),
fps = count / elapsed.as_secs_f64(),
elapsed = elapsed,
mean = Duration::from_secs_f64(mean),
std_dev = Duration::from_secs_f64(std_dev),
);
}
// Reset for next interval
frame_timings.clear();
last_report_time = Instant::now();
}
}
Ok(())
}