diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 3f721da53f..37b1c5e638 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -2780,10 +2780,59 @@ namespace rsx return result; } - void thread::fifo_wake_delay(u32 div) + void thread::fifo_wake_delay(u64 div) { + // TODO: Nanoseconds accuracy + u64 remaining = g_cfg.video.driver_wakeup_delay; + + if (!remaining) + { + return; + } + // Some cases do not need full delay - thread_ctrl::wait_for_accurate(utils::aligned_div(+g_cfg.video.driver_wakeup_delay, div)); + remaining = utils::aligned_div(remaining, div); + const u64 until = rsx::uclock() + remaining; + + while (true) + { +#ifdef __linux__ + // NOTE: Assumption that timer initialization has succeeded + u64 host_min_quantum = remaining <= 1000 ? 10 : 50; +#else + // Host scheduler quantum for windows (worst case) + // NOTE: On ps3 this function has very high accuracy + constexpr u64 host_min_quantum = 500; +#endif + if (remaining >= host_min_quantum) + { +#ifdef __linux__ + // Do not wait for the last quantum to avoid loss of accuracy + thread_ctrl::wait_for(remaining - ((remaining % host_min_quantum) + host_min_quantum), false); +#else + // Wait on multiple of min quantum for large durations to avoid overloading low thread cpus + thread_ctrl::wait_for(remaining - (remaining % host_min_quantum), false); +#endif + } + // TODO: Determine best value for yield delay + else if (remaining >= host_min_quantum / 2) + { + std::this_thread::yield(); + } + else + { + busy_wait(100); + } + + const u64 current = rsx::uclock(); + + if (current >= until) + { + break; + } + + remaining = until - current; + } } u32 thread::get_fifo_cmd() const diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index 917c98b0ca..f767880058 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -24,7 +24,6 @@ #include "Capture/rsx_trace.h" #include "Capture/rsx_replay.h" -#include "Emu/system_config.h" #include "Emu/Cell/lv2/sys_rsx.h" #include "Emu/IdManager.h" #include "Emu/system_config.h" @@ -519,7 +518,7 @@ namespace rsx const char* file = __builtin_FILE(), const char* func = __builtin_FUNCTION()); - static void fifo_wake_delay(u32 div = 1); + static void fifo_wake_delay(u64 div = 1); u32 get_fifo_cmd() const; void dump_regs(std::string&) const override;