parent
c0d9e4e435
commit
c4e4fa53d9
|
@ -66,6 +66,8 @@ void Config::ReadValues() {
|
||||||
Settings::values.use_scaled_resolution =
|
Settings::values.use_scaled_resolution =
|
||||||
sdl2_config->GetBoolean("Renderer", "use_scaled_resolution", false);
|
sdl2_config->GetBoolean("Renderer", "use_scaled_resolution", false);
|
||||||
Settings::values.use_vsync = sdl2_config->GetBoolean("Renderer", "use_vsync", false);
|
Settings::values.use_vsync = sdl2_config->GetBoolean("Renderer", "use_vsync", false);
|
||||||
|
Settings::values.toggle_framelimit =
|
||||||
|
sdl2_config->GetBoolean("Renderer", "toggle_framelimit", true);
|
||||||
|
|
||||||
Settings::values.bg_red = (float)sdl2_config->GetReal("Renderer", "bg_red", 1.0);
|
Settings::values.bg_red = (float)sdl2_config->GetReal("Renderer", "bg_red", 1.0);
|
||||||
Settings::values.bg_green = (float)sdl2_config->GetReal("Renderer", "bg_green", 1.0);
|
Settings::values.bg_green = (float)sdl2_config->GetReal("Renderer", "bg_green", 1.0);
|
||||||
|
|
|
@ -64,6 +64,10 @@ use_vsync =
|
||||||
# 0 (default): Default Top Bottom Screen, 1: Single Screen Only, 2: Large Screen Small Screen
|
# 0 (default): Default Top Bottom Screen, 1: Single Screen Only, 2: Large Screen Small Screen
|
||||||
layout_option =
|
layout_option =
|
||||||
|
|
||||||
|
#Whether to toggle frame limiter on or off.
|
||||||
|
# 0: Off , 1 (default): On
|
||||||
|
toggle_framelimit =
|
||||||
|
|
||||||
# Swaps the prominent screen with the other screen.
|
# Swaps the prominent screen with the other screen.
|
||||||
# For example, if Single Screen is chosen, setting this to 1 will display the bottom screen instead of the top screen.
|
# For example, if Single Screen is chosen, setting this to 1 will display the bottom screen instead of the top screen.
|
||||||
# 0 (default): Top Screen is prominent, 1: Bottom Screen is prominent
|
# 0 (default): Top Screen is prominent, 1: Bottom Screen is prominent
|
||||||
|
|
|
@ -47,6 +47,7 @@ void Config::ReadValues() {
|
||||||
Settings::values.use_scaled_resolution =
|
Settings::values.use_scaled_resolution =
|
||||||
qt_config->value("use_scaled_resolution", false).toBool();
|
qt_config->value("use_scaled_resolution", false).toBool();
|
||||||
Settings::values.use_vsync = qt_config->value("use_vsync", false).toBool();
|
Settings::values.use_vsync = qt_config->value("use_vsync", false).toBool();
|
||||||
|
Settings::values.toggle_framelimit = qt_config->value("toggle_framelimit", true).toBool();
|
||||||
|
|
||||||
Settings::values.bg_red = qt_config->value("bg_red", 1.0).toFloat();
|
Settings::values.bg_red = qt_config->value("bg_red", 1.0).toFloat();
|
||||||
Settings::values.bg_green = qt_config->value("bg_green", 1.0).toFloat();
|
Settings::values.bg_green = qt_config->value("bg_green", 1.0).toFloat();
|
||||||
|
@ -152,6 +153,7 @@ void Config::SaveValues() {
|
||||||
qt_config->setValue("use_shader_jit", Settings::values.use_shader_jit);
|
qt_config->setValue("use_shader_jit", Settings::values.use_shader_jit);
|
||||||
qt_config->setValue("use_scaled_resolution", Settings::values.use_scaled_resolution);
|
qt_config->setValue("use_scaled_resolution", Settings::values.use_scaled_resolution);
|
||||||
qt_config->setValue("use_vsync", Settings::values.use_vsync);
|
qt_config->setValue("use_vsync", Settings::values.use_vsync);
|
||||||
|
qt_config->setValue("toggle_framelimit", Settings::values.toggle_framelimit);
|
||||||
|
|
||||||
// Cast to double because Qt's written float values are not human-readable
|
// Cast to double because Qt's written float values are not human-readable
|
||||||
qt_config->setValue("bg_red", (double)Settings::values.bg_red);
|
qt_config->setValue("bg_red", (double)Settings::values.bg_red);
|
||||||
|
|
|
@ -23,6 +23,7 @@ void ConfigureGraphics::setConfiguration() {
|
||||||
ui->toggle_shader_jit->setChecked(Settings::values.use_shader_jit);
|
ui->toggle_shader_jit->setChecked(Settings::values.use_shader_jit);
|
||||||
ui->toggle_scaled_resolution->setChecked(Settings::values.use_scaled_resolution);
|
ui->toggle_scaled_resolution->setChecked(Settings::values.use_scaled_resolution);
|
||||||
ui->toggle_vsync->setChecked(Settings::values.use_vsync);
|
ui->toggle_vsync->setChecked(Settings::values.use_vsync);
|
||||||
|
ui->toggle_framelimit->setChecked(Settings::values.toggle_framelimit);
|
||||||
ui->layout_combobox->setCurrentIndex(static_cast<int>(Settings::values.layout_option));
|
ui->layout_combobox->setCurrentIndex(static_cast<int>(Settings::values.layout_option));
|
||||||
ui->swap_screen->setChecked(Settings::values.swap_screen);
|
ui->swap_screen->setChecked(Settings::values.swap_screen);
|
||||||
}
|
}
|
||||||
|
@ -32,6 +33,7 @@ void ConfigureGraphics::applyConfiguration() {
|
||||||
Settings::values.use_shader_jit = ui->toggle_shader_jit->isChecked();
|
Settings::values.use_shader_jit = ui->toggle_shader_jit->isChecked();
|
||||||
Settings::values.use_scaled_resolution = ui->toggle_scaled_resolution->isChecked();
|
Settings::values.use_scaled_resolution = ui->toggle_scaled_resolution->isChecked();
|
||||||
Settings::values.use_vsync = ui->toggle_vsync->isChecked();
|
Settings::values.use_vsync = ui->toggle_vsync->isChecked();
|
||||||
|
Settings::values.toggle_framelimit = ui->toggle_framelimit->isChecked();
|
||||||
Settings::values.layout_option =
|
Settings::values.layout_option =
|
||||||
static_cast<Settings::LayoutOption>(ui->layout_combobox->currentIndex());
|
static_cast<Settings::LayoutOption>(ui->layout_combobox->currentIndex());
|
||||||
Settings::values.swap_screen = ui->swap_screen->isChecked();
|
Settings::values.swap_screen = ui->swap_screen->isChecked();
|
||||||
|
|
|
@ -50,6 +50,13 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="toggle_framelimit">
|
||||||
|
<property name="text">
|
||||||
|
<string>Limit framerate</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
|
@ -8,7 +8,10 @@
|
||||||
#include "common/color.h"
|
#include "common/color.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
|
#include "common/math_util.h"
|
||||||
#include "common/microprofile.h"
|
#include "common/microprofile.h"
|
||||||
|
#include "common/thread.h"
|
||||||
|
#include "common/timer.h"
|
||||||
#include "common/vector_math.h"
|
#include "common/vector_math.h"
|
||||||
#include "core/core_timing.h"
|
#include "core/core_timing.h"
|
||||||
#include "core/hle/service/gsp_gpu.h"
|
#include "core/hle/service/gsp_gpu.h"
|
||||||
|
@ -35,6 +38,14 @@ const u64 frame_ticks = 268123480ull / 60;
|
||||||
static int vblank_event;
|
static int vblank_event;
|
||||||
/// Total number of frames drawn
|
/// Total number of frames drawn
|
||||||
static u64 frame_count;
|
static u64 frame_count;
|
||||||
|
/// Start clock for frame limiter
|
||||||
|
static u32 time_point;
|
||||||
|
/// Total delay caused by slow frames
|
||||||
|
static float time_delay;
|
||||||
|
constexpr float FIXED_FRAME_TIME = 1000.0f / 60;
|
||||||
|
// Max lag caused by slow frames. Can be adjusted to compensate for too many slow frames. Higher
|
||||||
|
// values increases time needed to limit frame rate after spikes
|
||||||
|
constexpr float MAX_LAG_TIME = 18;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline void Read(T& var, const u32 raw_addr) {
|
inline void Read(T& var, const u32 raw_addr) {
|
||||||
|
@ -512,6 +523,21 @@ template void Write<u32>(u32 addr, const u32 data);
|
||||||
template void Write<u16>(u32 addr, const u16 data);
|
template void Write<u16>(u32 addr, const u16 data);
|
||||||
template void Write<u8>(u32 addr, const u8 data);
|
template void Write<u8>(u32 addr, const u8 data);
|
||||||
|
|
||||||
|
static void FrameLimiter() {
|
||||||
|
time_delay += FIXED_FRAME_TIME;
|
||||||
|
time_delay = MathUtil::Clamp(time_delay, -MAX_LAG_TIME, MAX_LAG_TIME);
|
||||||
|
s32 desired_time = static_cast<s32>(time_delay);
|
||||||
|
s32 elapsed_time = static_cast<s32>(Common::Timer::GetTimeMs() - time_point);
|
||||||
|
|
||||||
|
if (elapsed_time < desired_time) {
|
||||||
|
Common::SleepCurrentThread(desired_time - elapsed_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 frame_time = Common::Timer::GetTimeMs() - time_point;
|
||||||
|
|
||||||
|
time_delay -= frame_time;
|
||||||
|
}
|
||||||
|
|
||||||
/// Update hardware
|
/// Update hardware
|
||||||
static void VBlankCallback(u64 userdata, int cycles_late) {
|
static void VBlankCallback(u64 userdata, int cycles_late) {
|
||||||
frame_count++;
|
frame_count++;
|
||||||
|
@ -528,6 +554,12 @@ static void VBlankCallback(u64 userdata, int cycles_late) {
|
||||||
// Check for user input updates
|
// Check for user input updates
|
||||||
Service::HID::Update();
|
Service::HID::Update();
|
||||||
|
|
||||||
|
if (!Settings::values.use_vsync && Settings::values.toggle_framelimit) {
|
||||||
|
FrameLimiter();
|
||||||
|
}
|
||||||
|
|
||||||
|
time_point = Common::Timer::GetTimeMs();
|
||||||
|
|
||||||
// Reschedule recurrent event
|
// Reschedule recurrent event
|
||||||
CoreTiming::ScheduleEvent(frame_ticks - cycles_late, vblank_event);
|
CoreTiming::ScheduleEvent(frame_ticks - cycles_late, vblank_event);
|
||||||
}
|
}
|
||||||
|
@ -563,6 +595,7 @@ void Init() {
|
||||||
framebuffer_sub.active_fb = 0;
|
framebuffer_sub.active_fb = 0;
|
||||||
|
|
||||||
frame_count = 0;
|
frame_count = 0;
|
||||||
|
time_point = Common::Timer::GetTimeMs();
|
||||||
|
|
||||||
vblank_event = CoreTiming::RegisterEvent("GPU::VBlankCallback", VBlankCallback);
|
vblank_event = CoreTiming::RegisterEvent("GPU::VBlankCallback", VBlankCallback);
|
||||||
CoreTiming::ScheduleEvent(frame_ticks, vblank_event);
|
CoreTiming::ScheduleEvent(frame_ticks, vblank_event);
|
||||||
|
|
|
@ -21,6 +21,7 @@ void Apply() {
|
||||||
VideoCore::g_hw_renderer_enabled = values.use_hw_renderer;
|
VideoCore::g_hw_renderer_enabled = values.use_hw_renderer;
|
||||||
VideoCore::g_shader_jit_enabled = values.use_shader_jit;
|
VideoCore::g_shader_jit_enabled = values.use_shader_jit;
|
||||||
VideoCore::g_scaled_resolution_enabled = values.use_scaled_resolution;
|
VideoCore::g_scaled_resolution_enabled = values.use_scaled_resolution;
|
||||||
|
VideoCore::g_toggle_framelimit_enabled = values.toggle_framelimit;
|
||||||
|
|
||||||
if (VideoCore::g_emu_window) {
|
if (VideoCore::g_emu_window) {
|
||||||
auto layout = VideoCore::g_emu_window->GetFramebufferLayout();
|
auto layout = VideoCore::g_emu_window->GetFramebufferLayout();
|
||||||
|
|
|
@ -90,6 +90,7 @@ struct Values {
|
||||||
bool use_shader_jit;
|
bool use_shader_jit;
|
||||||
bool use_scaled_resolution;
|
bool use_scaled_resolution;
|
||||||
bool use_vsync;
|
bool use_vsync;
|
||||||
|
bool toggle_framelimit;
|
||||||
|
|
||||||
LayoutOption layout_option;
|
LayoutOption layout_option;
|
||||||
bool swap_screen;
|
bool swap_screen;
|
||||||
|
|
|
@ -21,6 +21,7 @@ std::atomic<bool> g_hw_renderer_enabled;
|
||||||
std::atomic<bool> g_shader_jit_enabled;
|
std::atomic<bool> g_shader_jit_enabled;
|
||||||
std::atomic<bool> g_scaled_resolution_enabled;
|
std::atomic<bool> g_scaled_resolution_enabled;
|
||||||
std::atomic<bool> g_vsync_enabled;
|
std::atomic<bool> g_vsync_enabled;
|
||||||
|
std::atomic<bool> g_toggle_framelimit_enabled;
|
||||||
|
|
||||||
/// Initialize the video core
|
/// Initialize the video core
|
||||||
bool Init(EmuWindow* emu_window) {
|
bool Init(EmuWindow* emu_window) {
|
||||||
|
|
|
@ -38,6 +38,7 @@ extern EmuWindow* g_emu_window; ///< Emu window
|
||||||
extern std::atomic<bool> g_hw_renderer_enabled;
|
extern std::atomic<bool> g_hw_renderer_enabled;
|
||||||
extern std::atomic<bool> g_shader_jit_enabled;
|
extern std::atomic<bool> g_shader_jit_enabled;
|
||||||
extern std::atomic<bool> g_scaled_resolution_enabled;
|
extern std::atomic<bool> g_scaled_resolution_enabled;
|
||||||
|
extern std::atomic<bool> g_toggle_framelimit_enabled;
|
||||||
|
|
||||||
/// Start the video core
|
/// Start the video core
|
||||||
void Start();
|
void Start();
|
||||||
|
|
Reference in New Issue