| 92 | } |
| 93 | |
| 94 | pub fn begin_frame(&mut self) { |
| 95 | let now = Instant::now(); |
| 96 | self.delta_time = now.duration_since(self.last_frame_time).as_secs_f64(); |
| 97 | self.last_frame_time = now; |
| 98 | |
| 99 | // DRS samples wall-clock frame time and may step render_scale |
| 100 | // up or down before this frame's renderer work begins. No-op |
| 101 | // when disabled (default) — and the controller's own cooldown |
| 102 | // + hysteresis bound how often a step actually happens. |
| 103 | self.drs.tick(self.delta_time, &mut self.renderer); |
| 104 | |
| 105 | self.fps_frame_count += 1; |
| 106 | let fps_elapsed = now.duration_since(self.fps_timer).as_secs_f64(); |
| 107 | if fps_elapsed >= 1.0 { |
| 108 | self.current_fps = self.fps_frame_count as f64 / fps_elapsed; |
| 109 | self.fps_frame_count = 0; |
| 110 | self.fps_timer = now; |
| 111 | } |
| 112 | |
| 113 | self.input.begin_frame(); |
| 114 | self.renderer.begin_frame(); |
| 115 | self.frame_count += 1; |
| 116 | |
| 117 | // Run frame callbacks after begin_frame (matching R3F's useFrame timing) |
| 118 | self.profiler.begin("frame_callbacks"); |
| 119 | self.frame_callbacks.run_all(self.delta_time); |
| 120 | self.profiler.end("frame_callbacks"); |
| 121 | } |
| 122 | |
| 123 | pub fn end_frame(&mut self) { |
| 124 | if self.direct_2d_mode { |