1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
use std::time::Instant;
pub struct AdaptiveFramePacer {
target_fps: u32,
frame_history: Vec<f64>, // Frame times in ms
_prediction_error_margin: f64, // ms
last_frame_start: Instant,
}
impl AdaptiveFramePacer {
pub fn new(target_fps: u32) -> Self {
Self {
target_fps,
frame_history: Vec::with_capacity(60),
_prediction_error_margin: 0.5, // 0.5ms safety
last_frame_start: Instant::now(),
}
}
pub fn target_frame_time_ms(&self) -> f64 {
1000.0 / self.target_fps as f64
}
pub fn mark_frame_start(&mut self) {
self.last_frame_start = Instant::now();
}
pub fn mark_frame_end(&mut self) {
let duration = self.last_frame_start.elapsed().as_secs_f64() * 1000.0;
self.frame_history.push(duration);
if self.frame_history.len() > 60 {
self.frame_history.remove(0);
}
}
fn average_frame_time(&self) -> f64 {
if self.frame_history.is_empty() {
return self.target_frame_time_ms();
}
self.frame_history.iter().sum::<f64>() / self.frame_history.len() as f64
}
/// Returns time to wait/sleep before sampling input to align closely with VSync/Render
/// Returns 0.0 if we should sample immediately.
pub fn time_until_input_sample(&self, _present_time_estimate: Instant) -> f64 {
// Simple strategy: We want to sample input as late as possible,
// effectively (PresentTime - EstimatedFrameProcessingTime - SafetyMargin).
// For MVP, assume we call this at the start of the frame loop?
// Or users loop calls this?
// Frame structure:
// Start -> Sleep(time_until_input) -> Poll Input -> Update -> Render -> Present
// We know Average Update+Render time from history.
let _avg_work_time = self.average_frame_time();
// But `mark_frame_end` usually measures TOTAL frame time including Wait?
// We need to measure WORK time separately.
// For now, let's assume `mark_frame_end` is called before SwapBuffers/Wait.
// Stub: Just return 0 for now until integrated with a real loop structure
0.0
}
}