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, } 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, } } 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 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 = (firmware.os.last_frame_cpu_time_us as f64 / 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.telemetry_last.completed_logical_frames, ); 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; } } }