summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManuel Moos <z-man@users.sf.net>2020-02-15 23:50:25 +0100
committerManuel Moos <z-man@users.sf.net>2021-08-31 22:16:23 +0200
commit6be702bace06604281b3358ce7015086bcb7e2fb (patch)
treec70226637172b8a17b9e6baf2d90926fa5810356
parent794606657745e77b89523f19c5e3b69c838f0cb7 (diff)
Fix negative delta arguments
Three attack points, all after the regular calculations: 1. Prevent negative physics timestep counts. They could occur if physics_jtter_fix is changed at runtime. 2. idle_step is not allowed to go below 1/8th of the input step. That could happen on physics_jitter_fix changes or heavily fluctuating performance. 3. Prevent that the idle_step modification breaks the promise that Engine.get_physics_interpolation_fraction() is between 0 and 1 by doing more physics steps than the base system wants. Fixes #26887 Co-authored-by: Hugo Locurcio <hugo.locurcio@hugo.pro>
-rw-r--r--main/main_timer_sync.cpp43
1 files changed, 42 insertions, 1 deletions
diff --git a/main/main_timer_sync.cpp b/main/main_timer_sync.cpp
index 0d172be65e..42023e5a2f 100644
--- a/main/main_timer_sync.cpp
+++ b/main/main_timer_sync.cpp
@@ -57,7 +57,7 @@ int MainTimerSync::get_average_physics_steps(double &p_min, double &p_max) {
const double typical_lower = typical_physics_steps[i];
const double current_min = typical_lower / (i + 1);
if (current_min > p_max) {
- return i; // bail out of further restrictions would void the interval
+ return i; // bail out if further restrictions would void the interval
} else if (current_min > p_min) {
p_min = current_min;
}
@@ -105,6 +105,12 @@ MainFrameTime MainTimerSync::advance_core(double p_physics_step, int p_physics_t
}
}
+#ifdef DEBUG_ENABLED
+ if (max_typical_steps < 0) {
+ WARN_PRINT_ONCE("`max_typical_steps` is negative. This could hint at an engine bug or system timer misconfiguration.");
+ }
+#endif
+
// try to keep it consistent with previous iterations
if (ret.physics_steps < min_typical_steps) {
const int max_possible_steps = floor((time_accum)*p_physics_ticks_per_second + get_physics_jitter_fix());
@@ -124,6 +130,10 @@ MainFrameTime MainTimerSync::advance_core(double p_physics_step, int p_physics_t
}
}
+ if (ret.physics_steps < 0) {
+ ret.physics_steps = 0;
+ }
+
time_accum -= ret.physics_steps * p_physics_step;
// keep track of accumulated step counts
@@ -151,6 +161,9 @@ MainFrameTime MainTimerSync::advance_checked(double p_physics_step, int p_physic
p_process_step = 1.0 / fixed_fps;
}
+ float min_output_step = p_process_step / 8;
+ min_output_step = MAX(min_output_step, 1E-6);
+
// compensate for last deficit
p_process_step += time_deficit;
@@ -177,9 +190,37 @@ MainFrameTime MainTimerSync::advance_checked(double p_physics_step, int p_physic
// last clamping: make sure time_accum is between 0 and p_physics_step for consistency between physics and process
ret.clamp_process_step(process_minus_accum, process_minus_accum + p_physics_step);
+ // all the operations above may have turned ret.p_process_step negative or zero, keep a minimal value
+ if (ret.process_step < min_output_step) {
+ ret.process_step = min_output_step;
+ }
+
// restore time_accum
time_accum = ret.process_step - process_minus_accum;
+ // forcing ret.process_step to be positive may trigger a violation of the
+ // promise that time_accum is between 0 and p_physics_step
+#ifdef DEBUG_ENABLED
+ if (time_accum < -1E-7) {
+ WARN_PRINT_ONCE("Intermediate value of `time_accum` is negative. This could hint at an engine bug or system timer misconfiguration.");
+ }
+#endif
+
+ if (time_accum > p_physics_step) {
+ const int extra_physics_steps = floor(time_accum * p_physics_ticks_per_second);
+ time_accum -= extra_physics_steps * p_physics_step;
+ ret.physics_steps += extra_physics_steps;
+ }
+
+#ifdef DEBUG_ENABLED
+ if (time_accum < -1E-7) {
+ WARN_PRINT_ONCE("Final value of `time_accum` is negative. It should always be between 0 and `p_physics_step`. This hints at an engine bug.");
+ }
+ if (time_accum > p_physics_step + 1E-7) {
+ WARN_PRINT_ONCE("Final value of `time_accum` is larger than `p_physics_step`. It should always be between 0 and `p_physics_step`. This hints at an engine bug.");
+ }
+#endif
+
// track deficit
time_deficit = p_process_step - ret.process_step;