109 lines
3.5 KiB
Rust
109 lines
3.5 KiB
Rust
use prometeu_drivers::hardware::Hardware;
|
|
use prometeu_firmware::Firmware;
|
|
use std::time::{Duration, Instant};
|
|
use winit::window::Window;
|
|
|
|
pub struct HostStats {
|
|
pub last_stats_update: Instant,
|
|
pub frames_since_last_update: u64,
|
|
pub current_fps: f64,
|
|
pub audio_load_accum_us: u64,
|
|
pub audio_load_samples: u64,
|
|
recent_host_cpu_us: [u64; 5],
|
|
recent_host_cpu_count: usize,
|
|
recent_host_cpu_cursor: usize,
|
|
}
|
|
|
|
impl Default for HostStats {
|
|
fn default() -> Self {
|
|
Self::new()
|
|
}
|
|
}
|
|
|
|
impl HostStats {
|
|
pub fn new() -> Self {
|
|
Self {
|
|
last_stats_update: Instant::now(),
|
|
frames_since_last_update: 0,
|
|
current_fps: 0.0,
|
|
audio_load_accum_us: 0,
|
|
audio_load_samples: 0,
|
|
recent_host_cpu_us: [0; 5],
|
|
recent_host_cpu_count: 0,
|
|
recent_host_cpu_cursor: 0,
|
|
}
|
|
}
|
|
|
|
pub fn record_frame(&mut self) {
|
|
self.frames_since_last_update += 1;
|
|
}
|
|
|
|
pub fn record_audio_perf(&mut self, us: u64) {
|
|
self.audio_load_accum_us += us;
|
|
self.audio_load_samples += 1;
|
|
}
|
|
|
|
pub fn record_host_cpu_time(&mut self, us: u64) {
|
|
self.recent_host_cpu_us[self.recent_host_cpu_cursor] = us;
|
|
self.recent_host_cpu_cursor =
|
|
(self.recent_host_cpu_cursor + 1) % self.recent_host_cpu_us.len();
|
|
self.recent_host_cpu_count =
|
|
self.recent_host_cpu_count.saturating_add(1).min(self.recent_host_cpu_us.len());
|
|
}
|
|
|
|
pub fn average_host_cpu_ms(&self) -> f64 {
|
|
if self.recent_host_cpu_count == 0 {
|
|
0.0
|
|
} else {
|
|
let sum: u64 = self.recent_host_cpu_us.iter().take(self.recent_host_cpu_count).sum();
|
|
(sum as f64 / self.recent_host_cpu_count as f64) / 1000.0
|
|
}
|
|
}
|
|
|
|
pub fn update(
|
|
&mut self,
|
|
now: Instant,
|
|
window: Option<&Window>,
|
|
_hardware: &Hardware,
|
|
firmware: &Firmware,
|
|
) {
|
|
let stats_elapsed = now.duration_since(self.last_stats_update);
|
|
if stats_elapsed >= Duration::from_secs(1) {
|
|
self.current_fps = self.frames_since_last_update as f64 / stats_elapsed.as_secs_f64();
|
|
|
|
if let Some(window) = window {
|
|
// Fixed comparison always against 60Hz, keep even when doing CPU stress tests
|
|
let frame_budget_us = 16666.0;
|
|
let cpu_load_core = (self.average_host_cpu_ms() * 1000.0 / frame_budget_us) * 100.0;
|
|
|
|
let cpu_load_audio = if self.audio_load_samples > 0 {
|
|
(self.audio_load_accum_us as f64 / stats_elapsed.as_micros() as f64) * 100.0
|
|
} else {
|
|
0.0
|
|
};
|
|
|
|
let title = format!(
|
|
"PROMETEU | GFX: {:.1} KB | FPS: {:.1} | Load: {:.1}% (C) + {:.1}% (A) | Frame: tick {} logical {} done {}",
|
|
0,
|
|
self.current_fps,
|
|
cpu_load_core,
|
|
cpu_load_audio,
|
|
firmware.os.tick_index,
|
|
firmware.os.logical_frame_index,
|
|
firmware
|
|
.os
|
|
.atomic_telemetry
|
|
.completed_logical_frames
|
|
.load(std::sync::atomic::Ordering::Relaxed),
|
|
);
|
|
window.set_title(&title);
|
|
}
|
|
|
|
self.last_stats_update = now;
|
|
self.frames_since_last_update = 0;
|
|
self.audio_load_accum_us = 0;
|
|
self.audio_load_samples = 0;
|
|
}
|
|
}
|
|
}
|