summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar emmauss2016-12-07 07:33:19 +1200
committerGravatar bunnei2016-12-06 14:33:19 -0500
commitc4e4fa53d9200bbac34a498d55cde381e3112764 (patch)
tree1056916dce234655fa9e7807fd63cf2f12dfb9b4 /src
parentMerge pull request #2264 from JayFoxRox/print-shader (diff)
downloadyuzu-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.cpp2
-rw-r--r--src/citra/default_ini.h4
-rw-r--r--src/citra_qt/config.cpp2
-rw-r--r--src/citra_qt/configure_graphics.cpp2
-rw-r--r--src/citra_qt/configure_graphics.ui7
-rw-r--r--src/core/hw/gpu.cpp33
-rw-r--r--src/core/settings.cpp1
-rw-r--r--src/core/settings.h1
-rw-r--r--src/video_core/video_core.cpp1
-rw-r--r--src/video_core/video_core.h1
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
65layout_option = 65layout_option =
66 66
67#Whether to toggle frame limiter on or off.
68# 0: Off , 1 (default): On
69toggle_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;
35static int vblank_event; 38static int vblank_event;
36/// Total number of frames drawn 39/// Total number of frames drawn
37static u64 frame_count; 40static u64 frame_count;
41/// Start clock for frame limiter
42static u32 time_point;
43/// Total delay caused by slow frames
44static float time_delay;
45constexpr 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
48constexpr float MAX_LAG_TIME = 18;
38 49
39template <typename T> 50template <typename T>
40inline void Read(T& var, const u32 raw_addr) { 51inline void Read(T& var, const u32 raw_addr) {
@@ -512,6 +523,21 @@ template void Write<u32>(u32 addr, const u32 data);
512template void Write<u16>(u32 addr, const u16 data); 523template void Write<u16>(u32 addr, const u16 data);
513template void Write<u8>(u32 addr, const u8 data); 524template void Write<u8>(u32 addr, const u8 data);
514 525
526static 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
516static void VBlankCallback(u64 userdata, int cycles_late) { 542static 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;
21std::atomic<bool> g_shader_jit_enabled; 21std::atomic<bool> g_shader_jit_enabled;
22std::atomic<bool> g_scaled_resolution_enabled; 22std::atomic<bool> g_scaled_resolution_enabled;
23std::atomic<bool> g_vsync_enabled; 23std::atomic<bool> g_vsync_enabled;
24std::atomic<bool> g_toggle_framelimit_enabled;
24 25
25/// Initialize the video core 26/// Initialize the video core
26bool Init(EmuWindow* emu_window) { 27bool 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
38extern std::atomic<bool> g_hw_renderer_enabled; 38extern std::atomic<bool> g_hw_renderer_enabled;
39extern std::atomic<bool> g_shader_jit_enabled; 39extern std::atomic<bool> g_shader_jit_enabled;
40extern std::atomic<bool> g_scaled_resolution_enabled; 40extern std::atomic<bool> g_scaled_resolution_enabled;
41extern std::atomic<bool> g_toggle_framelimit_enabled;
41 42
42/// Start the video core 43/// Start the video core
43void Start(); 44void Start();