Merge pull request #51495 from lawnjelly/fix_delta_overflow

Delta smoothing - fix overflow for long frames
This commit is contained in:
Rémi Verschelde 2021-08-11 12:23:32 +02:00 committed by GitHub
commit 35096325b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 23 additions and 17 deletions

View File

@ -43,7 +43,7 @@ void MainFrameTime::clamp_idle(float min_idle_step, float max_idle_step) {
/////////////////////////////////
void MainTimerSync::DeltaSmoother::update_refresh_rate_estimator(int p_delta) {
void MainTimerSync::DeltaSmoother::update_refresh_rate_estimator(int64_t p_delta) {
// the calling code should prevent 0 or negative values of delta
// (preventing divide by zero)
@ -195,7 +195,7 @@ void MainTimerSync::DeltaSmoother::update_refresh_rate_estimator(int p_delta) {
}
}
bool MainTimerSync::DeltaSmoother::fps_allows_smoothing(int p_delta) {
bool MainTimerSync::DeltaSmoother::fps_allows_smoothing(int64_t p_delta) {
_measurement_time += p_delta;
_measurement_frame_count++;
@ -209,8 +209,8 @@ bool MainTimerSync::DeltaSmoother::fps_allows_smoothing(int p_delta) {
// estimate fps
if (time_passed) {
float fps = 1000000.0f / time_passed;
float ratio = fps / (float)_estimated_fps;
double fps = 1000000.0 / time_passed;
double ratio = fps / (double)_estimated_fps;
//print_line("ratio : " + String(Variant(ratio)));
@ -230,7 +230,7 @@ bool MainTimerSync::DeltaSmoother::fps_allows_smoothing(int p_delta) {
return _measurement_allows_smoothing;
}
int MainTimerSync::DeltaSmoother::smooth_delta(int p_delta) {
int64_t MainTimerSync::DeltaSmoother::smooth_delta(int64_t p_delta) {
// Conditions to disable smoothing.
// Note that vsync is a request, it cannot be relied on, the OS may override this.
// If the OS turns vsync on without vsync in the app, smoothing will not be enabled.
@ -240,6 +240,12 @@ int MainTimerSync::DeltaSmoother::smooth_delta(int p_delta) {
return p_delta;
}
// Very important, ignore long deltas and pass them back unmodified.
// This is to deal with resuming after suspend for long periods.
if (p_delta > 1000000) {
return p_delta;
}
// keep a running guesstimate of the FPS, and turn off smoothing if
// conditions not close to the estimated FPS
if (!fps_allows_smoothing(p_delta)) {
@ -266,7 +272,7 @@ int MainTimerSync::DeltaSmoother::smooth_delta(int p_delta) {
_leftover_time += p_delta;
// how many vsyncs units can we fit?
int units = _leftover_time / _vsync_delta;
int64_t units = _leftover_time / _vsync_delta;
// a delta must include minimum 1 vsync
// (if it is less than that, it is either random error or we are no longer running at the vsync rate,

View File

@ -48,11 +48,11 @@ class MainTimerSync {
class DeltaSmoother {
public:
// pass the recorded delta, returns a smoothed delta
int smooth_delta(int p_delta);
int64_t smooth_delta(int64_t p_delta);
private:
void update_refresh_rate_estimator(int p_delta);
bool fps_allows_smoothing(int p_delta);
void update_refresh_rate_estimator(int64_t p_delta);
bool fps_allows_smoothing(int64_t p_delta);
// estimated vsync delta (monitor refresh rate)
int64_t _vsync_delta = 16666;
@ -75,19 +75,19 @@ class MainTimerSync {
// we can estimate the fps by growing it on condition
// that a large proportion of frames are higher than the current estimate.
int _estimated_fps = 0;
int _hits_at_estimated = 0;
int _hits_above_estimated = 0;
int _hits_below_estimated = 0;
int _hits_one_above_estimated = 0;
int _hits_one_below_estimated = 0;
int32_t _estimated_fps = 0;
int32_t _hits_at_estimated = 0;
int32_t _hits_above_estimated = 0;
int32_t _hits_below_estimated = 0;
int32_t _hits_one_above_estimated = 0;
int32_t _hits_one_below_estimated = 0;
bool _estimate_complete = false;
bool _estimate_locked = false;
// data for averaging the delta over a second or so
// to prevent spurious values
int _estimator_total_delta = 0;
int _estimator_delta_readings = 0;
int64_t _estimator_total_delta = 0;
int32_t _estimator_delta_readings = 0;
void made_new_estimate() {
_hits_above_estimated = 0;