@@ -265,7 +265,15 @@ void OS_Windows::initialize() {
265265
266266 // set minimum resolution for periodic timers, otherwise Sleep(n) may wait at least as
267267 // long as the windows scheduler resolution (~16-30ms) even for calls like Sleep(1)
268- timeBeginPeriod (1 );
268+ TIMECAPS time_caps;
269+ if (timeGetDevCaps (&time_caps, sizeof (time_caps)) == MMSYSERR_NOERROR) {
270+ delay_resolution = time_caps.wPeriodMin * 1000 ;
271+ timeBeginPeriod (time_caps.wPeriodMin );
272+ } else {
273+ ERR_PRINT (" Unable to detect sleep timer resolution." );
274+ delay_resolution = 1000 ;
275+ timeBeginPeriod (1 );
276+ }
269277
270278 process_map = memnew ((HashMap<ProcessID, ProcessInfo>));
271279
@@ -2223,6 +2231,46 @@ String OS_Windows::get_system_ca_certificates() {
22232231 return certs;
22242232}
22252233
2234+ void OS_Windows::add_frame_delay (bool p_can_draw) {
2235+ const uint32_t frame_delay = Engine::get_singleton ()->get_frame_delay ();
2236+ if (frame_delay) {
2237+ // Add fixed frame delay to decrease CPU/GPU usage. This doesn't take
2238+ // the actual frame time into account.
2239+ // Due to the high fluctuation of the actual sleep duration, it's not recommended
2240+ // to use this as a FPS limiter.
2241+ delay_usec (frame_delay * 1000 );
2242+ }
2243+
2244+ // Add a dynamic frame delay to decrease CPU/GPU usage. This takes the
2245+ // previous frame time into account for a smoother result.
2246+ uint64_t dynamic_delay = 0 ;
2247+ if (is_in_low_processor_usage_mode () || !p_can_draw) {
2248+ dynamic_delay = get_low_processor_usage_mode_sleep_usec ();
2249+ }
2250+ const int max_fps = Engine::get_singleton ()->get_max_fps ();
2251+ if (max_fps > 0 && !Engine::get_singleton ()->is_editor_hint ()) {
2252+ // Override the low processor usage mode sleep delay if the target FPS is lower.
2253+ dynamic_delay = MAX (dynamic_delay, (uint64_t )(1000000 / max_fps));
2254+ }
2255+
2256+ if (dynamic_delay > 0 ) {
2257+ target_ticks += dynamic_delay;
2258+ uint64_t current_ticks = get_ticks_usec ();
2259+
2260+ // The minimum sleep resolution on windows is 1 ms on most systems.
2261+ if (current_ticks < (target_ticks - delay_resolution)) {
2262+ delay_usec ((target_ticks - delay_resolution) - current_ticks);
2263+ }
2264+ // Busy wait for the remainder of time.
2265+ while (get_ticks_usec () < target_ticks) {
2266+ YieldProcessor ();
2267+ }
2268+
2269+ current_ticks = get_ticks_usec ();
2270+ target_ticks = MIN (MAX (target_ticks, current_ticks - dynamic_delay), current_ticks + dynamic_delay);
2271+ }
2272+ }
2273+
22262274OS_Windows::OS_Windows (HINSTANCE _hInstance) {
22272275 hInstance = _hInstance;
22282276
0 commit comments