diff options
| author | 2016-12-07 07:33:19 +1200 | |
|---|---|---|
| committer | 2016-12-06 14:33:19 -0500 | |
| commit | c4e4fa53d9200bbac34a498d55cde381e3112764 (patch) | |
| tree | 1056916dce234655fa9e7807fd63cf2f12dfb9b4 /src | |
| 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')
| -rw-r--r-- | src/citra/config.cpp | 2 | ||||
| -rw-r--r-- | src/citra/default_ini.h | 4 | ||||
| -rw-r--r-- | src/citra_qt/config.cpp | 2 | ||||
| -rw-r--r-- | src/citra_qt/configure_graphics.cpp | 2 | ||||
| -rw-r--r-- | src/citra_qt/configure_graphics.ui | 7 | ||||
| -rw-r--r-- | src/core/hw/gpu.cpp | 33 | ||||
| -rw-r--r-- | src/core/settings.cpp | 1 | ||||
| -rw-r--r-- | src/core/settings.h | 1 | ||||
| -rw-r--r-- | src/video_core/video_core.cpp | 1 | ||||
| -rw-r--r-- | src/video_core/video_core.h | 1 |
10 files changed, 54 insertions, 0 deletions
diff --git a/src/citra/config.cpp b/src/citra/config.cpp index fe74fcd72..29462c982 100644 --- a/src/citra/config.cpp +++ b/src/citra/config.cpp | |||
| @@ -66,6 +66,8 @@ void Config::ReadValues() { | |||
| 66 | Settings::values.use_scaled_resolution = | 66 | Settings::values.use_scaled_resolution = |
| 67 | sdl2_config->GetBoolean("Renderer", "use_scaled_resolution", false); | 67 | sdl2_config->GetBoolean("Renderer", "use_scaled_resolution", false); |
| 68 | Settings::values.use_vsync = sdl2_config->GetBoolean("Renderer", "use_vsync", false); | 68 | Settings::values.use_vsync = sdl2_config->GetBoolean("Renderer", "use_vsync", false); |
| 69 | Settings::values.toggle_framelimit = | ||
| 70 | sdl2_config->GetBoolean("Renderer", "toggle_framelimit", true); | ||
| 69 | 71 | ||
| 70 | Settings::values.bg_red = (float)sdl2_config->GetReal("Renderer", "bg_red", 1.0); | 72 | Settings::values.bg_red = (float)sdl2_config->GetReal("Renderer", "bg_red", 1.0); |
| 71 | Settings::values.bg_green = (float)sdl2_config->GetReal("Renderer", "bg_green", 1.0); | 73 | Settings::values.bg_green = (float)sdl2_config->GetReal("Renderer", "bg_green", 1.0); |
diff --git a/src/citra/default_ini.h b/src/citra/default_ini.h index b98dc4d83..001b18ac2 100644 --- a/src/citra/default_ini.h +++ b/src/citra/default_ini.h | |||
| @@ -64,6 +64,10 @@ use_vsync = | |||
| 64 | # 0 (default): Default Top Bottom Screen, 1: Single Screen Only, 2: Large Screen Small Screen | 64 | # 0 (default): Default Top Bottom Screen, 1: Single Screen Only, 2: Large Screen Small Screen |
| 65 | layout_option = | 65 | layout_option = |
| 66 | 66 | ||
| 67 | #Whether to toggle frame limiter on or off. | ||
| 68 | # 0: Off , 1 (default): On | ||
| 69 | toggle_framelimit = | ||
| 70 | |||
| 67 | # Swaps the prominent screen with the other screen. | 71 | # Swaps the prominent screen with the other screen. |
| 68 | # For example, if Single Screen is chosen, setting this to 1 will display the bottom screen instead of the top screen. | 72 | # For example, if Single Screen is chosen, setting this to 1 will display the bottom screen instead of the top screen. |
| 69 | # 0 (default): Top Screen is prominent, 1: Bottom Screen is prominent | 73 | # 0 (default): Top Screen is prominent, 1: Bottom Screen is prominent |
diff --git a/src/citra_qt/config.cpp b/src/citra_qt/config.cpp index 3cdfe6443..06a4e9d25 100644 --- a/src/citra_qt/config.cpp +++ b/src/citra_qt/config.cpp | |||
| @@ -47,6 +47,7 @@ void Config::ReadValues() { | |||
| 47 | Settings::values.use_scaled_resolution = | 47 | Settings::values.use_scaled_resolution = |
| 48 | qt_config->value("use_scaled_resolution", false).toBool(); | 48 | qt_config->value("use_scaled_resolution", false).toBool(); |
| 49 | Settings::values.use_vsync = qt_config->value("use_vsync", false).toBool(); | 49 | Settings::values.use_vsync = qt_config->value("use_vsync", false).toBool(); |
| 50 | Settings::values.toggle_framelimit = qt_config->value("toggle_framelimit", true).toBool(); | ||
| 50 | 51 | ||
| 51 | Settings::values.bg_red = qt_config->value("bg_red", 1.0).toFloat(); | 52 | Settings::values.bg_red = qt_config->value("bg_red", 1.0).toFloat(); |
| 52 | Settings::values.bg_green = qt_config->value("bg_green", 1.0).toFloat(); | 53 | Settings::values.bg_green = qt_config->value("bg_green", 1.0).toFloat(); |
| @@ -152,6 +153,7 @@ void Config::SaveValues() { | |||
| 152 | qt_config->setValue("use_shader_jit", Settings::values.use_shader_jit); | 153 | qt_config->setValue("use_shader_jit", Settings::values.use_shader_jit); |
| 153 | qt_config->setValue("use_scaled_resolution", Settings::values.use_scaled_resolution); | 154 | qt_config->setValue("use_scaled_resolution", Settings::values.use_scaled_resolution); |
| 154 | qt_config->setValue("use_vsync", Settings::values.use_vsync); | 155 | qt_config->setValue("use_vsync", Settings::values.use_vsync); |
| 156 | qt_config->setValue("toggle_framelimit", Settings::values.toggle_framelimit); | ||
| 155 | 157 | ||
| 156 | // Cast to double because Qt's written float values are not human-readable | 158 | // Cast to double because Qt's written float values are not human-readable |
| 157 | qt_config->setValue("bg_red", (double)Settings::values.bg_red); | 159 | qt_config->setValue("bg_red", (double)Settings::values.bg_red); |
diff --git a/src/citra_qt/configure_graphics.cpp b/src/citra_qt/configure_graphics.cpp index 29834e11b..36f10c8d7 100644 --- a/src/citra_qt/configure_graphics.cpp +++ b/src/citra_qt/configure_graphics.cpp | |||
| @@ -23,6 +23,7 @@ void ConfigureGraphics::setConfiguration() { | |||
| 23 | ui->toggle_shader_jit->setChecked(Settings::values.use_shader_jit); | 23 | ui->toggle_shader_jit->setChecked(Settings::values.use_shader_jit); |
| 24 | ui->toggle_scaled_resolution->setChecked(Settings::values.use_scaled_resolution); | 24 | ui->toggle_scaled_resolution->setChecked(Settings::values.use_scaled_resolution); |
| 25 | ui->toggle_vsync->setChecked(Settings::values.use_vsync); | 25 | ui->toggle_vsync->setChecked(Settings::values.use_vsync); |
| 26 | ui->toggle_framelimit->setChecked(Settings::values.toggle_framelimit); | ||
| 26 | ui->layout_combobox->setCurrentIndex(static_cast<int>(Settings::values.layout_option)); | 27 | ui->layout_combobox->setCurrentIndex(static_cast<int>(Settings::values.layout_option)); |
| 27 | ui->swap_screen->setChecked(Settings::values.swap_screen); | 28 | ui->swap_screen->setChecked(Settings::values.swap_screen); |
| 28 | } | 29 | } |
| @@ -32,6 +33,7 @@ void ConfigureGraphics::applyConfiguration() { | |||
| 32 | Settings::values.use_shader_jit = ui->toggle_shader_jit->isChecked(); | 33 | Settings::values.use_shader_jit = ui->toggle_shader_jit->isChecked(); |
| 33 | Settings::values.use_scaled_resolution = ui->toggle_scaled_resolution->isChecked(); | 34 | Settings::values.use_scaled_resolution = ui->toggle_scaled_resolution->isChecked(); |
| 34 | Settings::values.use_vsync = ui->toggle_vsync->isChecked(); | 35 | Settings::values.use_vsync = ui->toggle_vsync->isChecked(); |
| 36 | Settings::values.toggle_framelimit = ui->toggle_framelimit->isChecked(); | ||
| 35 | Settings::values.layout_option = | 37 | Settings::values.layout_option = |
| 36 | static_cast<Settings::LayoutOption>(ui->layout_combobox->currentIndex()); | 38 | static_cast<Settings::LayoutOption>(ui->layout_combobox->currentIndex()); |
| 37 | Settings::values.swap_screen = ui->swap_screen->isChecked(); | 39 | Settings::values.swap_screen = ui->swap_screen->isChecked(); |
diff --git a/src/citra_qt/configure_graphics.ui b/src/citra_qt/configure_graphics.ui index af16a4292..964aa0bbd 100644 --- a/src/citra_qt/configure_graphics.ui +++ b/src/citra_qt/configure_graphics.ui | |||
| @@ -50,6 +50,13 @@ | |||
| 50 | </property> | 50 | </property> |
| 51 | </widget> | 51 | </widget> |
| 52 | </item> | 52 | </item> |
| 53 | <item> | ||
| 54 | <widget class="QCheckBox" name="toggle_framelimit"> | ||
| 55 | <property name="text"> | ||
| 56 | <string>Limit framerate</string> | ||
| 57 | </property> | ||
| 58 | </widget> | ||
| 59 | </item> | ||
| 53 | </layout> | 60 | </layout> |
| 54 | </widget> | 61 | </widget> |
| 55 | </item> | 62 | </item> |
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); |
diff --git a/src/core/settings.cpp b/src/core/settings.cpp index 05f41f798..626e06cd9 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp | |||
| @@ -21,6 +21,7 @@ void Apply() { | |||
| 21 | VideoCore::g_hw_renderer_enabled = values.use_hw_renderer; | 21 | VideoCore::g_hw_renderer_enabled = values.use_hw_renderer; |
| 22 | VideoCore::g_shader_jit_enabled = values.use_shader_jit; | 22 | VideoCore::g_shader_jit_enabled = values.use_shader_jit; |
| 23 | VideoCore::g_scaled_resolution_enabled = values.use_scaled_resolution; | 23 | VideoCore::g_scaled_resolution_enabled = values.use_scaled_resolution; |
| 24 | VideoCore::g_toggle_framelimit_enabled = values.toggle_framelimit; | ||
| 24 | 25 | ||
| 25 | if (VideoCore::g_emu_window) { | 26 | if (VideoCore::g_emu_window) { |
| 26 | auto layout = VideoCore::g_emu_window->GetFramebufferLayout(); | 27 | auto layout = VideoCore::g_emu_window->GetFramebufferLayout(); |
diff --git a/src/core/settings.h b/src/core/settings.h index 7470fdbeb..db4c8fada 100644 --- a/src/core/settings.h +++ b/src/core/settings.h | |||
| @@ -90,6 +90,7 @@ struct Values { | |||
| 90 | bool use_shader_jit; | 90 | bool use_shader_jit; |
| 91 | bool use_scaled_resolution; | 91 | bool use_scaled_resolution; |
| 92 | bool use_vsync; | 92 | bool use_vsync; |
| 93 | bool toggle_framelimit; | ||
| 93 | 94 | ||
| 94 | LayoutOption layout_option; | 95 | LayoutOption layout_option; |
| 95 | bool swap_screen; | 96 | bool swap_screen; |
diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp index 83e33dfc2..8db882f59 100644 --- a/src/video_core/video_core.cpp +++ b/src/video_core/video_core.cpp | |||
| @@ -21,6 +21,7 @@ std::atomic<bool> g_hw_renderer_enabled; | |||
| 21 | std::atomic<bool> g_shader_jit_enabled; | 21 | std::atomic<bool> g_shader_jit_enabled; |
| 22 | std::atomic<bool> g_scaled_resolution_enabled; | 22 | std::atomic<bool> g_scaled_resolution_enabled; |
| 23 | std::atomic<bool> g_vsync_enabled; | 23 | std::atomic<bool> g_vsync_enabled; |
| 24 | std::atomic<bool> g_toggle_framelimit_enabled; | ||
| 24 | 25 | ||
| 25 | /// Initialize the video core | 26 | /// Initialize the video core |
| 26 | bool Init(EmuWindow* emu_window) { | 27 | bool Init(EmuWindow* emu_window) { |
diff --git a/src/video_core/video_core.h b/src/video_core/video_core.h index e2d725ab1..c397c1974 100644 --- a/src/video_core/video_core.h +++ b/src/video_core/video_core.h | |||
| @@ -38,6 +38,7 @@ extern EmuWindow* g_emu_window; ///< Emu window | |||
| 38 | extern std::atomic<bool> g_hw_renderer_enabled; | 38 | extern std::atomic<bool> g_hw_renderer_enabled; |
| 39 | extern std::atomic<bool> g_shader_jit_enabled; | 39 | extern std::atomic<bool> g_shader_jit_enabled; |
| 40 | extern std::atomic<bool> g_scaled_resolution_enabled; | 40 | extern std::atomic<bool> g_scaled_resolution_enabled; |
| 41 | extern std::atomic<bool> g_toggle_framelimit_enabled; | ||
| 41 | 42 | ||
| 42 | /// Start the video core | 43 | /// Start the video core |
| 43 | void Start(); | 44 | void Start(); |