diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index 25025efbd2..a7ec2b7e0a 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -15,7 +15,6 @@ #include #include "Utilities/Thread.h" -#include "Utilities/Timer.h" #include "Utilities/geometry.h" #include "rsx_trace.h" #include "restore_new.h" @@ -155,8 +154,6 @@ namespace rsx RsxDmaControl* ctrl = nullptr; atomic_t internal_get{ 0 }; - Timer timer_sync; - GcmTileInfo tiles[limits::tiles_count]; GcmZcullInfo zculls[limits::zculls_count]; @@ -218,6 +215,8 @@ namespace rsx double fps_limit = 59.94; public: + u64 start_rsx_time = 0; + u64 int_flip_index = 0; u64 last_flip_time; vm::ps3::ptr flip_handler = vm::null; vm::ps3::ptr user_handler = vm::null; diff --git a/rpcs3/Emu/RSX/rsx_methods.cpp b/rpcs3/Emu/RSX/rsx_methods.cpp index aaf93b3af3..1cf8999d28 100644 --- a/rpcs3/Emu/RSX/rsx_methods.cpp +++ b/rpcs3/Emu/RSX/rsx_methods.cpp @@ -940,12 +940,33 @@ namespace rsx case frame_limit_type::_30: limit = 30.; break; case frame_limit_type::_auto: limit = rsx->fps_limit; break; // TODO } + if (limit) { - std::this_thread::sleep_for(std::chrono::milliseconds((s64)(1000.0 / limit - rsx->timer_sync.GetElapsedTimeInMilliSec()))); - rsx->timer_sync.Start(); + const u64 time = get_system_time() - Emu.GetPauseTime() - rsx->start_rsx_time; + + if (rsx->int_flip_index == 0) + { + rsx->start_rsx_time = time; + } + else + { + // Convert limit to expected time value + double expected = rsx->int_flip_index * 1000000. / limit; + + while (time >= expected + 1000000. / limit) + { + expected = rsx->int_flip_index++ * 1000000. / limit; + } + + if (expected > time + 1000) + { + std::this_thread::sleep_for(std::chrono::milliseconds{static_cast(expected - time) / 1000}); + } + } } + rsx->int_flip_index++; rsx->current_display_buffer = arg; rsx->flip(arg); // After each flip PS3 system is executing a routine that changes registers value to some default.