소스 검색

Merge pull request #51495 from lawnjelly/fix_delta_overflow

Delta smoothing - fix overflow for long frames
Rémi Verschelde 4 년 전
부모
커밋
35096325b8
2개의 변경된 파일23개의 추가작업 그리고 17개의 파일을 삭제
  1. 12 6
      main/main_timer_sync.cpp
  2. 11 11
      main/main_timer_sync.h

+ 12 - 6
main/main_timer_sync.cpp

@@ -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
 	// the calling code should prevent 0 or negative values of delta
 	// (preventing divide by zero)
 	// (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_time += p_delta;
 	_measurement_frame_count++;
 	_measurement_frame_count++;
 
 
@@ -209,8 +209,8 @@ bool MainTimerSync::DeltaSmoother::fps_allows_smoothing(int p_delta) {
 
 
 			// estimate fps
 			// estimate fps
 			if (time_passed) {
 			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)));
 				//print_line("ratio : " + String(Variant(ratio)));
 
 
@@ -230,7 +230,7 @@ bool MainTimerSync::DeltaSmoother::fps_allows_smoothing(int p_delta) {
 	return _measurement_allows_smoothing;
 	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.
 	// Conditions to disable smoothing.
 	// Note that vsync is a request, it cannot be relied on, the OS may override this.
 	// 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.
 	// 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;
 		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
 	// keep a running guesstimate of the FPS, and turn off smoothing if
 	// conditions not close to the estimated FPS
 	// conditions not close to the estimated FPS
 	if (!fps_allows_smoothing(p_delta)) {
 	if (!fps_allows_smoothing(p_delta)) {
@@ -266,7 +272,7 @@ int MainTimerSync::DeltaSmoother::smooth_delta(int p_delta) {
 	_leftover_time += p_delta;
 	_leftover_time += p_delta;
 
 
 	// how many vsyncs units can we fit?
 	// 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
 	// 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,
 	// (if it is less than that, it is either random error or we are no longer running at the vsync rate,

+ 11 - 11
main/main_timer_sync.h

@@ -48,11 +48,11 @@ class MainTimerSync {
 	class DeltaSmoother {
 	class DeltaSmoother {
 	public:
 	public:
 		// pass the recorded delta, returns a smoothed delta
 		// pass the recorded delta, returns a smoothed delta
-		int smooth_delta(int p_delta);
+		int64_t smooth_delta(int64_t p_delta);
 
 
 	private:
 	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)
 		// estimated vsync delta (monitor refresh rate)
 		int64_t _vsync_delta = 16666;
 		int64_t _vsync_delta = 16666;
@@ -75,19 +75,19 @@ class MainTimerSync {
 
 
 		// we can estimate the fps by growing it on condition
 		// we can estimate the fps by growing it on condition
 		// that a large proportion of frames are higher than the current estimate.
 		// 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_complete = false;
 		bool _estimate_locked = false;
 		bool _estimate_locked = false;
 
 
 		// data for averaging the delta over a second or so
 		// data for averaging the delta over a second or so
 		// to prevent spurious values
 		// 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() {
 		void made_new_estimate() {
 			_hits_above_estimated = 0;
 			_hits_above_estimated = 0;