mirror of
https://github.com/Lime3DS/Lime3DS
synced 2024-12-27 01:22:37 -06:00
parent
c0d9e4e435
commit
c4e4fa53d9
10 changed files with 54 additions and 0 deletions
|
@ -66,6 +66,8 @@ void Config::ReadValues() {
|
|||
Settings::values.use_scaled_resolution =
|
||||
sdl2_config->GetBoolean("Renderer", "use_scaled_resolution", 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_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
|
||||
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.
|
||||
# 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
|
||||
|
|
|
@ -47,6 +47,7 @@ void Config::ReadValues() {
|
|||
Settings::values.use_scaled_resolution =
|
||||
qt_config->value("use_scaled_resolution", 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_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_scaled_resolution", Settings::values.use_scaled_resolution);
|
||||
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
|
||||
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_scaled_resolution->setChecked(Settings::values.use_scaled_resolution);
|
||||
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->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_scaled_resolution = ui->toggle_scaled_resolution->isChecked();
|
||||
Settings::values.use_vsync = ui->toggle_vsync->isChecked();
|
||||
Settings::values.toggle_framelimit = ui->toggle_framelimit->isChecked();
|
||||
Settings::values.layout_option =
|
||||
static_cast<Settings::LayoutOption>(ui->layout_combobox->currentIndex());
|
||||
Settings::values.swap_screen = ui->swap_screen->isChecked();
|
||||
|
|
|
@ -50,6 +50,13 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="toggle_framelimit">
|
||||
<property name="text">
|
||||
<string>Limit framerate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
@ -8,7 +8,10 @@
|
|||
#include "common/color.h"
|
||||
#include "common/common_types.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/math_util.h"
|
||||
#include "common/microprofile.h"
|
||||
#include "common/thread.h"
|
||||
#include "common/timer.h"
|
||||
#include "common/vector_math.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/hle/service/gsp_gpu.h"
|
||||
|
@ -35,6 +38,14 @@ const u64 frame_ticks = 268123480ull / 60;
|
|||
static int vblank_event;
|
||||
/// Total number of frames drawn
|
||||
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>
|
||||
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<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
|
||||
static void VBlankCallback(u64 userdata, int cycles_late) {
|
||||
frame_count++;
|
||||
|
@ -528,6 +554,12 @@ static void VBlankCallback(u64 userdata, int cycles_late) {
|
|||
// Check for user input updates
|
||||
Service::HID::Update();
|
||||
|
||||
if (!Settings::values.use_vsync && Settings::values.toggle_framelimit) {
|
||||
FrameLimiter();
|
||||
}
|
||||
|
||||
time_point = Common::Timer::GetTimeMs();
|
||||
|
||||
// Reschedule recurrent event
|
||||
CoreTiming::ScheduleEvent(frame_ticks - cycles_late, vblank_event);
|
||||
}
|
||||
|
@ -563,6 +595,7 @@ void Init() {
|
|||
framebuffer_sub.active_fb = 0;
|
||||
|
||||
frame_count = 0;
|
||||
time_point = Common::Timer::GetTimeMs();
|
||||
|
||||
vblank_event = CoreTiming::RegisterEvent("GPU::VBlankCallback", VBlankCallback);
|
||||
CoreTiming::ScheduleEvent(frame_ticks, vblank_event);
|
||||
|
|
|
@ -21,6 +21,7 @@ void Apply() {
|
|||
VideoCore::g_hw_renderer_enabled = values.use_hw_renderer;
|
||||
VideoCore::g_shader_jit_enabled = values.use_shader_jit;
|
||||
VideoCore::g_scaled_resolution_enabled = values.use_scaled_resolution;
|
||||
VideoCore::g_toggle_framelimit_enabled = values.toggle_framelimit;
|
||||
|
||||
if (VideoCore::g_emu_window) {
|
||||
auto layout = VideoCore::g_emu_window->GetFramebufferLayout();
|
||||
|
|
|
@ -90,6 +90,7 @@ struct Values {
|
|||
bool use_shader_jit;
|
||||
bool use_scaled_resolution;
|
||||
bool use_vsync;
|
||||
bool toggle_framelimit;
|
||||
|
||||
LayoutOption layout_option;
|
||||
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_scaled_resolution_enabled;
|
||||
std::atomic<bool> g_vsync_enabled;
|
||||
std::atomic<bool> g_toggle_framelimit_enabled;
|
||||
|
||||
/// Initialize the video core
|
||||
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_shader_jit_enabled;
|
||||
extern std::atomic<bool> g_scaled_resolution_enabled;
|
||||
extern std::atomic<bool> g_toggle_framelimit_enabled;
|
||||
|
||||
/// Start the video core
|
||||
void Start();
|
||||
|
|
Loading…
Reference in a new issue