diff options
| author | 2016-12-07 07:33:19 +1200 | |
|---|---|---|
| committer | 2016-12-06 14:33:19 -0500 | |
| commit | c4e4fa53d9200bbac34a498d55cde381e3112764 (patch) | |
| tree | 1056916dce234655fa9e7807fd63cf2f12dfb9b4 /src/core/hw/gpu.cpp | |
| parent | Merge pull request #2264 from JayFoxRox/print-shader (diff) | |
| download | yuzu-c4e4fa53d9200bbac34a498d55cde381e3112764.tar.gz yuzu-c4e4fa53d9200bbac34a498d55cde381e3112764.tar.xz yuzu-c4e4fa53d9200bbac34a498d55cde381e3112764.zip | |
Implement Frame rate limiter (#2223)
* implement frame limiter
* fixes
Diffstat (limited to 'src/core/hw/gpu.cpp')
| -rw-r--r-- | src/core/hw/gpu.cpp | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp index 45dedea68..cfba82e51 100644 --- a/src/core/hw/gpu.cpp +++ b/src/core/hw/gpu.cpp | |||
| @@ -8,7 +8,10 @@ | |||
| 8 | #include "common/color.h" | 8 | #include "common/color.h" |
| 9 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 10 | #include "common/logging/log.h" | 10 | #include "common/logging/log.h" |
| 11 | #include "common/math_util.h" | ||
| 11 | #include "common/microprofile.h" | 12 | #include "common/microprofile.h" |
| 13 | #include "common/thread.h" | ||
| 14 | #include "common/timer.h" | ||
| 12 | #include "common/vector_math.h" | 15 | #include "common/vector_math.h" |
| 13 | #include "core/core_timing.h" | 16 | #include "core/core_timing.h" |
| 14 | #include "core/hle/service/gsp_gpu.h" | 17 | #include "core/hle/service/gsp_gpu.h" |
| @@ -35,6 +38,14 @@ const u64 frame_ticks = 268123480ull / 60; | |||
| 35 | static int vblank_event; | 38 | static int vblank_event; |
| 36 | /// Total number of frames drawn | 39 | /// Total number of frames drawn |
| 37 | static u64 frame_count; | 40 | static u64 frame_count; |
| 41 | /// Start clock for frame limiter | ||
| 42 | static u32 time_point; | ||
| 43 | /// Total delay caused by slow frames | ||
| 44 | static float time_delay; | ||
| 45 | constexpr float FIXED_FRAME_TIME = 1000.0f / 60; | ||
| 46 | // Max lag caused by slow frames. Can be adjusted to compensate for too many slow frames. Higher | ||
| 47 | // values increases time needed to limit frame rate after spikes | ||
| 48 | constexpr float MAX_LAG_TIME = 18; | ||
| 38 | 49 | ||
| 39 | template <typename T> | 50 | template <typename T> |
| 40 | inline void Read(T& var, const u32 raw_addr) { | 51 | inline void Read(T& var, const u32 raw_addr) { |
| @@ -512,6 +523,21 @@ template void Write<u32>(u32 addr, const u32 data); | |||
| 512 | template void Write<u16>(u32 addr, const u16 data); | 523 | template void Write<u16>(u32 addr, const u16 data); |
| 513 | template void Write<u8>(u32 addr, const u8 data); | 524 | template void Write<u8>(u32 addr, const u8 data); |
| 514 | 525 | ||
| 526 | static void FrameLimiter() { | ||
| 527 | time_delay += FIXED_FRAME_TIME; | ||
| 528 | time_delay = MathUtil::Clamp(time_delay, -MAX_LAG_TIME, MAX_LAG_TIME); | ||
| 529 | s32 desired_time = static_cast<s32>(time_delay); | ||
| 530 | s32 elapsed_time = static_cast<s32>(Common::Timer::GetTimeMs() - time_point); | ||
| 531 | |||
| 532 | if (elapsed_time < desired_time) { | ||
| 533 | Common::SleepCurrentThread(desired_time - elapsed_time); | ||
| 534 | } | ||
| 535 | |||
| 536 | u32 frame_time = Common::Timer::GetTimeMs() - time_point; | ||
| 537 | |||
| 538 | time_delay -= frame_time; | ||
| 539 | } | ||
| 540 | |||
| 515 | /// Update hardware | 541 | /// Update hardware |
| 516 | static void VBlankCallback(u64 userdata, int cycles_late) { | 542 | static void VBlankCallback(u64 userdata, int cycles_late) { |
| 517 | frame_count++; | 543 | frame_count++; |
| @@ -528,6 +554,12 @@ static void VBlankCallback(u64 userdata, int cycles_late) { | |||
| 528 | // Check for user input updates | 554 | // Check for user input updates |
| 529 | Service::HID::Update(); | 555 | Service::HID::Update(); |
| 530 | 556 | ||
| 557 | if (!Settings::values.use_vsync && Settings::values.toggle_framelimit) { | ||
| 558 | FrameLimiter(); | ||
| 559 | } | ||
| 560 | |||
| 561 | time_point = Common::Timer::GetTimeMs(); | ||
| 562 | |||
| 531 | // Reschedule recurrent event | 563 | // Reschedule recurrent event |
| 532 | CoreTiming::ScheduleEvent(frame_ticks - cycles_late, vblank_event); | 564 | CoreTiming::ScheduleEvent(frame_ticks - cycles_late, vblank_event); |
| 533 | } | 565 | } |
| @@ -563,6 +595,7 @@ void Init() { | |||
| 563 | framebuffer_sub.active_fb = 0; | 595 | framebuffer_sub.active_fb = 0; |
| 564 | 596 | ||
| 565 | frame_count = 0; | 597 | frame_count = 0; |
| 598 | time_point = Common::Timer::GetTimeMs(); | ||
| 566 | 599 | ||
| 567 | vblank_event = CoreTiming::RegisterEvent("GPU::VBlankCallback", VBlankCallback); | 600 | vblank_event = CoreTiming::RegisterEvent("GPU::VBlankCallback", VBlankCallback); |
| 568 | CoreTiming::ScheduleEvent(frame_ticks, vblank_event); | 601 | CoreTiming::ScheduleEvent(frame_ticks, vblank_event); |