Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rsx: Improve frame-limiter #7723

Merged
merged 6 commits into from Mar 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 0 additions & 1 deletion rpcs3/Emu/Cell/Modules/cellGcmSys.cpp
Expand Up @@ -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");
Expand Down
14 changes: 10 additions & 4 deletions rpcs3/Emu/Cell/lv2/sys_sync.h
Expand Up @@ -251,13 +251,19 @@ struct lv2_obj
}
}

template<bool is_usleep = false>
template<bool is_usleep = false, bool scale = true>
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<u64>(std::min<u64>(usec, UINT64_MAX / 100) * 100 / g_cfg.core.clocks_scale, cond_variable::max_timeout);
if constexpr (scale)
{
// Scale time
usec = std::min<u64>(usec, UINT64_MAX / 100) * 100 / g_cfg.core.clocks_scale;
}

// Clamp
usec = std::min<u64>(usec, cond_variable::max_timeout);

extern u64 get_system_time();

Expand Down Expand Up @@ -301,7 +307,7 @@ struct lv2_obj
}
}

if (Emu.IsStopped())
if (thread_ctrl::state() == thread_state::aborting)
{
return false;
}
Expand Down
27 changes: 16 additions & 11 deletions rpcs3/Emu/RSX/RSXThread.cpp
Expand Up @@ -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<u64>(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<s64>(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<false, false>(delay_us);

if (thread_ctrl::state() == thread_state::aborting)
{
return;
}

performance_counters.idle_time += delay_us;
}
}
Expand Down
5 changes: 1 addition & 4 deletions rpcs3/Emu/RSX/RSXThread.h
Expand Up @@ -710,10 +710,7 @@ namespace rsx
void get_current_fragment_program(const std::array<std::unique_ptr<rsx::sampled_image_descriptor_base>, 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<void(u32)> flip_handler = vm::null;
Expand Down
4 changes: 2 additions & 2 deletions rpcs3/Emu/system_config.h
Expand Up @@ -96,7 +96,7 @@ struct cfg_root : cfg::node

cfg::_enum<video_resolution> resolution{ this, "Resolution", video_resolution::_720 };
cfg::_enum<video_aspect> aspect_ratio{ this, "Aspect ratio", video_aspect::_16_9 };
cfg::_enum<frame_limit_type> frame_limit{ this, "Frame limit", frame_limit_type::none };
cfg::_enum<frame_limit_type> frame_limit{ this, "Frame limit", frame_limit_type::none, true };
cfg::_enum<msaa_level> antialiasing_level{ this, "MSAA", msaa_level::_auto };

cfg::_bool write_color_buffers{ this, "Write Color Buffers" };
Expand All @@ -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 };
Expand Down