From 807b095b15016a309e209496f2aa26f119fef4b1 Mon Sep 17 00:00:00 2001 From: Khang Date: Sun, 3 Jan 2021 19:18:38 -0500 Subject: [PATCH 1/3] mitigations for windows' broken system timer --- src/lib.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 815a62d..f720646 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -141,7 +141,15 @@ impl Game { let state_ref = unsafe { &mut *self.state.get() }; if state_ref.timing_mode != TimingMode::FrameSynchronized { - let n1 = (self.start_time.elapsed().as_nanos() - self.last_tick) as f64; + // Even with the non-monotonic Instant mitigation at the start of the event loop, + // there's still a theoretical chance of it not working. + // This check here should trigger if that happens and makes sure there's no panic from an underflow. + let mut elapsed = self.start_time.elapsed().as_nanos(); + if elapsed < self.last_tick { + warn!("Elapsed time was less than last tick! elapsed: {}, last tick: {}", elapsed, self.last_tick); + elapsed = self.last_tick; + } + let n1 = (elapsed - self.last_tick) as f64; let n2 = (self.next_tick - self.last_tick) as f64; state_ref.frame_time = n1 / n2; } @@ -331,6 +339,12 @@ pub fn init() -> GameResult { context = Some(init_ctx(&event_loop, resource_dir.clone())?); event_loop.run(move |event, target, flow| { + #[cfg(target_os = "windows")] + { + // Windows' system clock implementation isn't monotonic when the process gets switched to another core. + // Rust has mitigations for this, but apparently aren't very effective unless Instant is called very often. + let _ = Instant::now(); + } if let Some(ctx) = &mut context { ctx.process_event(&event); From 348cb3045bfd7435f4ccd179f0aaa17812cdcb45 Mon Sep 17 00:00:00 2001 From: Khang Date: Sun, 3 Jan 2021 19:22:36 -0500 Subject: [PATCH 2/3] handle 0x0 windows, fixes minimizing on windows --- src/lib.rs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index f720646..23da9d0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -398,15 +398,18 @@ pub fn init() -> GameResult { } *flow = ControlFlow::Exit; } - WindowEvent::Resized(_) => { - if let (Some(ctx), Some(game)) = (&mut context, &mut game) { - let state_ref = unsafe { &mut *game.state.get() }; + WindowEvent::Resized(size) => { + // Minimizing a window on Windows causes this event to get called with a 0x0 size + if size.width != 0 && size.height != 0 { + if let (Some(ctx), Some(game)) = (&mut context, &mut game) { + let state_ref = unsafe { &mut *game.state.get() }; - state_ref.tmp_canvas = Canvas::with_window_size(ctx).unwrap(); - state_ref.game_canvas = Canvas::with_window_size(ctx).unwrap(); - state_ref.lightmap_canvas = Canvas::with_window_size(ctx).unwrap(); - state_ref.handle_resize(ctx).unwrap(); - graphics::window(ctx).update_gfx(&mut game.ui.main_color, &mut game.ui.main_depth); + state_ref.tmp_canvas = Canvas::with_window_size(ctx).unwrap(); + state_ref.game_canvas = Canvas::with_window_size(ctx).unwrap(); + state_ref.lightmap_canvas = Canvas::with_window_size(ctx).unwrap(); + state_ref.handle_resize(ctx).unwrap(); + graphics::window(ctx).update_gfx(&mut game.ui.main_color, &mut game.ui.main_depth); + } } } WindowEvent::Touch(touch) => { From 7e308676ff3f9c655b5b0b59bbee0e5df891e9ee Mon Sep 17 00:00:00 2001 From: Khang Date: Mon, 4 Jan 2021 00:08:17 -0500 Subject: [PATCH 3/3] address comments --- src/lib.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 23da9d0..0d8b568 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -141,13 +141,14 @@ impl Game { let state_ref = unsafe { &mut *self.state.get() }; if state_ref.timing_mode != TimingMode::FrameSynchronized { - // Even with the non-monotonic Instant mitigation at the start of the event loop, - // there's still a theoretical chance of it not working. - // This check here should trigger if that happens and makes sure there's no panic from an underflow. let mut elapsed = self.start_time.elapsed().as_nanos(); - if elapsed < self.last_tick { - warn!("Elapsed time was less than last tick! elapsed: {}, last tick: {}", elapsed, self.last_tick); - elapsed = self.last_tick; + #[cfg(target_os = "windows")] + { + // Even with the non-monotonic Instant mitigation at the start of the event loop, there's still a chance of it not working. + // This check here should trigger if that happens and makes sure there's no panic from an underflow. + if elapsed < self.last_tick { + elapsed = self.last_tick; + } } let n1 = (elapsed - self.last_tick) as f64; let n2 = (self.next_tick - self.last_tick) as f64;