Browse Source

Merge pull request #36052 from Calinou/improve-low-processor-sleep

Improve the low processor mode sleep precision
Rémi Verschelde 5 years ago
parent
commit
4dede9e644
1 changed files with 24 additions and 12 deletions
  1. 24 12
      main/main.cpp

+ 24 - 12
main/main.cpp

@@ -2266,25 +2266,37 @@ bool Main::iteration() {
 		return exit;
 		return exit;
 	}
 	}
 
 
-	if (OS::get_singleton()->is_in_low_processor_usage_mode() || !DisplayServer::get_singleton()->can_any_window_draw()) {
-		OS::get_singleton()->delay_usec(OS::get_singleton()->get_low_processor_usage_mode_sleep_usec()); //apply some delay to force idle time
-	} else {
-		uint32_t frame_delay = Engine::get_singleton()->get_frame_delay();
-		if (frame_delay) {
-			OS::get_singleton()->delay_usec(Engine::get_singleton()->get_frame_delay() * 1000);
-		}
+	const uint32_t frame_delay = Engine::get_singleton()->get_frame_delay();
+	if (frame_delay) {
+		// Add fixed frame delay to decrease CPU/GPU usage. This doesn't take
+		// the actual frame time into account.
+		// Due to the high fluctuation of the actual sleep duration, it's not recommended
+		// to use this as a FPS limiter.
+		OS::get_singleton()->delay_usec(frame_delay * 1000);
+	}
+
+	// Add a dynamic frame delay to decrease CPU/GPU usage. This takes the
+	// previous frame time into account for a smoother result.
+	uint64_t dynamic_delay = 0;
+	if (OS::get_singleton()->is_in_low_processor_usage_mode() || !DisplayServer::get_singleton()->window_can_draw()) {
+		dynamic_delay = OS::get_singleton()->get_low_processor_usage_mode_sleep_usec();
+	}
+	const int target_fps = Engine::get_singleton()->get_target_fps();
+	if (target_fps > 0 && !Engine::get_singleton()->is_editor_hint()) {
+		// Override the low processor usage mode sleep delay if the target FPS is lower.
+		dynamic_delay = MAX(dynamic_delay, (uint64_t)(1000000 / target_fps));
 	}
 	}
 
 
-	int target_fps = Engine::get_singleton()->get_target_fps();
-	if (target_fps > 0 && !Engine::get_singleton()->is_editor_hint()) {
-		uint64_t time_step = 1000000L / target_fps;
-		target_ticks += time_step;
+	if (dynamic_delay > 0) {
+		target_ticks += dynamic_delay;
 		uint64_t current_ticks = OS::get_singleton()->get_ticks_usec();
 		uint64_t current_ticks = OS::get_singleton()->get_ticks_usec();
+
 		if (current_ticks < target_ticks) {
 		if (current_ticks < target_ticks) {
 			OS::get_singleton()->delay_usec(target_ticks - current_ticks);
 			OS::get_singleton()->delay_usec(target_ticks - current_ticks);
 		}
 		}
+
 		current_ticks = OS::get_singleton()->get_ticks_usec();
 		current_ticks = OS::get_singleton()->get_ticks_usec();
-		target_ticks = MIN(MAX(target_ticks, current_ticks - time_step), current_ticks + time_step);
+		target_ticks = MIN(MAX(target_ticks, current_ticks - dynamic_delay), current_ticks + dynamic_delay);
 	}
 	}
 
 
 #ifdef TOOLS_ENABLED
 #ifdef TOOLS_ENABLED