diff --git a/rpcs3/Emu/Cell/Modules/cellGcmSys.cpp b/rpcs3/Emu/Cell/Modules/cellGcmSys.cpp index 398b246431ba..18fa2ac21a25 100644 --- a/rpcs3/Emu/Cell/Modules/cellGcmSys.cpp +++ b/rpcs3/Emu/Cell/Modules/cellGcmSys.cpp @@ -586,7 +586,6 @@ void cellGcmSetSecondVFrequency(u32 freq) switch (freq) { case CELL_GCM_DISPLAY_FREQUENCY_59_94HZ: - render->fps_limit = 59.94; break; case CELL_GCM_DISPLAY_FREQUENCY_SCANOUT: cellGcmSys.todo("Unimplemented display frequency: Scanout"); diff --git a/rpcs3/Emu/Cell/lv2/sys_sync.h b/rpcs3/Emu/Cell/lv2/sys_sync.h index 46b89306759b..75f73927ce6c 100644 --- a/rpcs3/Emu/Cell/lv2/sys_sync.h +++ b/rpcs3/Emu/Cell/lv2/sys_sync.h @@ -251,13 +251,19 @@ struct lv2_obj } } - template + template static bool wait_timeout(u64 usec, cpu_thread* const cpu = {}) { static_assert(UINT64_MAX / cond_variable::max_timeout >= 100, "max timeout is not valid for scaling"); - // Clamp and scale the result - usec = std::min(std::min(usec, UINT64_MAX / 100) * 100 / g_cfg.core.clocks_scale, cond_variable::max_timeout); + if constexpr (scale) + { + // Scale time + usec = std::min(usec, UINT64_MAX / 100) * 100 / g_cfg.core.clocks_scale; + } + + // Clamp + usec = std::min(usec, cond_variable::max_timeout); extern u64 get_system_time(); @@ -301,7 +307,7 @@ struct lv2_obj } } - if (Emu.IsStopped()) + if (thread_ctrl::state() == thread_state::aborting) { return false; } diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 61d99c266910..4dc780740a0f 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -2654,33 +2654,38 @@ namespace rsx case frame_limit_type::_50: limit = 50.; break; case frame_limit_type::_60: limit = 60.; break; case frame_limit_type::_30: limit = 30.; break; - case frame_limit_type::_auto: limit = fps_limit; break; // TODO + case frame_limit_type::_auto: limit = g_cfg.video.vblank_rate; break; // TODO default: break; } if (limit) { - const u64 time = get_system_time() - Emu.GetPauseTime() - start_rsx_time; + const u64 time = get_system_time() - Emu.GetPauseTime(); + const u64 needed_us = static_cast(1000000 / limit); if (int_flip_index == 0) { - start_rsx_time = time; + target_rsx_flip_time = time; } else { - // Convert limit to expected time value - double expected = int_flip_index * 1000000. / limit; - - while (time >= expected + 1000000. / limit) + do { - expected = int_flip_index++ * 1000000. / limit; + target_rsx_flip_time += needed_us; } + while (time >= target_rsx_flip_time + needed_us); - if (expected > time + 1000) + if (target_rsx_flip_time > time + 1000) { - const auto delay_us = static_cast(expected - time); - std::this_thread::sleep_for(std::chrono::milliseconds{ delay_us / 1000 }); + const auto delay_us = target_rsx_flip_time - time; + lv2_obj::wait_timeout(delay_us); + + if (thread_ctrl::state() == thread_state::aborting) + { + return; + } + performance_counters.idle_time += delay_us; } } diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index 45e494d545ed..3ae4b99f1070 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -710,10 +710,7 @@ namespace rsx void get_current_fragment_program(const std::array, rsx::limits::fragment_textures_count>& sampler_descriptors); public: - double fps_limit = 59.94; - - public: - u64 start_rsx_time = 0; + u64 target_rsx_flip_time = 0; u64 int_flip_index = 0; u64 last_flip_time = 0; vm::ptr flip_handler = vm::null; diff --git a/rpcs3/Emu/system_config.h b/rpcs3/Emu/system_config.h index 2f46aaa02582..c732c4928563 100644 --- a/rpcs3/Emu/system_config.h +++ b/rpcs3/Emu/system_config.h @@ -96,7 +96,7 @@ struct cfg_root : cfg::node cfg::_enum resolution{ this, "Resolution", video_resolution::_720 }; cfg::_enum aspect_ratio{ this, "Aspect ratio", video_aspect::_16_9 }; - cfg::_enum frame_limit{ this, "Frame limit", frame_limit_type::none }; + cfg::_enum frame_limit{ this, "Frame limit", frame_limit_type::none, true }; cfg::_enum antialiasing_level{ this, "MSAA", msaa_level::_auto }; cfg::_bool write_color_buffers{ this, "Write Color Buffers" }; @@ -109,7 +109,7 @@ struct cfg_root : cfg::node cfg::_bool overlay{ this, "Debug overlay" }; cfg::_bool gl_legacy_buffers{ this, "Use Legacy OpenGL Buffers" }; cfg::_bool use_gpu_texture_scaling{ this, "Use GPU texture scaling", false }; - cfg::_bool stretch_to_display_area{ this, "Stretch To Display Area" }; + cfg::_bool stretch_to_display_area{ this, "Stretch To Display Area", false, true }; cfg::_bool force_high_precision_z_buffer{ this, "Force High Precision Z buffer" }; cfg::_bool strict_rendering_mode{ this, "Strict Rendering Mode" }; cfg::_bool disable_zcull_queries{ this, "Disable ZCull Occlusion Queries", false };