citra_qt: Add option to adjust screen refresh rate
This commit is contained in:
parent
b5d6f645bd
commit
ce115869c9
8 changed files with 138 additions and 20 deletions
|
@ -447,6 +447,7 @@ void Config::ReadCoreValues() {
|
|||
qt_config->beginGroup(QStringLiteral("Core"));
|
||||
|
||||
ReadGlobalSetting(Settings::values.cpu_clock_percentage);
|
||||
ReadGlobalSetting(Settings::values.refresh_rate);
|
||||
|
||||
if (global) {
|
||||
ReadBasicSetting(Settings::values.use_cpu_jit);
|
||||
|
@ -963,6 +964,7 @@ void Config::SaveCoreValues() {
|
|||
qt_config->beginGroup(QStringLiteral("Core"));
|
||||
|
||||
WriteGlobalSetting(Settings::values.cpu_clock_percentage);
|
||||
WriteGlobalSetting(Settings::values.refresh_rate);
|
||||
|
||||
if (global) {
|
||||
WriteBasicSetting(Settings::values.use_cpu_jit);
|
||||
|
|
|
@ -42,13 +42,21 @@ ConfigureDebug::ConfigureDebug(QWidget* parent)
|
|||
// Set a minimum width for the label to prevent the slider from changing size.
|
||||
// This scales across DPIs. (This value should be enough for "xxx%")
|
||||
ui->clock_display_label->setMinimumWidth(40);
|
||||
ui->refresh_display_label->setMinimumWidth(40);
|
||||
|
||||
connect(ui->slider_clock_speed, &QSlider::valueChanged, this, [&](int value) {
|
||||
ui->clock_display_label->setText(QStringLiteral("%1%").arg(SliderToSettings(value)));
|
||||
});
|
||||
|
||||
ui->clock_speed_label->setVisible(Settings::IsConfiguringGlobal());
|
||||
ui->clock_speed_combo->setVisible(!Settings::IsConfiguringGlobal());
|
||||
connect(ui->slider_refresh_rate, &QSlider::valueChanged, this, [&](int value) {
|
||||
ui->refresh_display_label->setText(QStringLiteral("%1Hz").arg(value));
|
||||
});
|
||||
|
||||
const bool is_global = Settings::IsConfiguringGlobal();
|
||||
ui->clock_speed_label->setVisible(is_global);
|
||||
ui->refresh_rate_label->setVisible(is_global);
|
||||
ui->clock_speed_combo->setVisible(!is_global);
|
||||
ui->refresh_rate_combo->setVisible(!is_global);
|
||||
|
||||
SetupPerGameUI();
|
||||
}
|
||||
|
@ -73,14 +81,26 @@ void ConfigureDebug::SetConfiguration() {
|
|||
ui->clock_speed_combo->setCurrentIndex(1);
|
||||
ui->slider_clock_speed->setEnabled(true);
|
||||
}
|
||||
if (Settings::values.refresh_rate.UsingGlobal()) {
|
||||
ui->refresh_rate_combo->setCurrentIndex(0);
|
||||
ui->slider_refresh_rate->setEnabled(false);
|
||||
} else {
|
||||
ui->refresh_rate_combo->setCurrentIndex(1);
|
||||
ui->slider_refresh_rate->setEnabled(true);
|
||||
}
|
||||
ConfigurationShared::SetHighlight(ui->clock_speed_widget,
|
||||
!Settings::values.cpu_clock_percentage.UsingGlobal());
|
||||
ConfigurationShared::SetHighlight(ui->refresh_rate_widget,
|
||||
!Settings::values.refresh_rate.UsingGlobal());
|
||||
}
|
||||
|
||||
ui->slider_clock_speed->setValue(
|
||||
SettingsToSlider(Settings::values.cpu_clock_percentage.GetValue()));
|
||||
ui->clock_display_label->setText(
|
||||
QStringLiteral("%1%").arg(Settings::values.cpu_clock_percentage.GetValue()));
|
||||
ui->slider_refresh_rate->setValue(Settings::values.refresh_rate.GetValue());
|
||||
ui->refresh_display_label->setText(
|
||||
QStringLiteral("%1Hz").arg(Settings::values.refresh_rate.GetValue()));
|
||||
}
|
||||
|
||||
void ConfigureDebug::ApplyConfiguration() {
|
||||
|
@ -98,22 +118,32 @@ void ConfigureDebug::ApplyConfiguration() {
|
|||
ConfigurationShared::ApplyPerGameSetting(
|
||||
&Settings::values.cpu_clock_percentage, ui->clock_speed_combo,
|
||||
[this](s32) { return SliderToSettings(ui->slider_clock_speed->value()); });
|
||||
|
||||
ConfigurationShared::ApplyPerGameSetting(
|
||||
&Settings::values.refresh_rate, ui->refresh_rate_combo,
|
||||
[this](s32) { return ui->slider_refresh_rate->value(); });
|
||||
}
|
||||
|
||||
void ConfigureDebug::SetupPerGameUI() {
|
||||
// Block the global settings if a game is currently running that overrides them
|
||||
if (Settings::IsConfiguringGlobal()) {
|
||||
ui->slider_clock_speed->setEnabled(Settings::values.cpu_clock_percentage.UsingGlobal());
|
||||
ui->slider_refresh_rate->setEnabled(Settings::values.refresh_rate.UsingGlobal());
|
||||
return;
|
||||
}
|
||||
|
||||
connect(ui->refresh_rate_combo, qOverload<int>(&QComboBox::activated), this, [this](int index) {
|
||||
ui->slider_refresh_rate->setEnabled(index == 1);
|
||||
ConfigurationShared::SetHighlight(ui->refresh_rate_widget, index == 1);
|
||||
});
|
||||
|
||||
connect(ui->clock_speed_combo, qOverload<int>(&QComboBox::activated), this, [this](int index) {
|
||||
ui->slider_clock_speed->setEnabled(index == 1);
|
||||
ConfigurationShared::SetHighlight(ui->clock_speed_widget, index == 1);
|
||||
});
|
||||
|
||||
ui->groupBox->setVisible(false);
|
||||
ui->groupBox_2->setVisible(false);
|
||||
ui->gdb_group->setVisible(false);
|
||||
ui->logging_group->setVisible(false);
|
||||
ui->toggle_cpu_jit->setVisible(false);
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>523</width>
|
||||
<height>447</height>
|
||||
<height>495</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -17,7 +17,7 @@
|
|||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<widget class="QGroupBox" name="gdb_group">
|
||||
<property name="title">
|
||||
<string>GDB</string>
|
||||
</property>
|
||||
|
@ -66,7 +66,7 @@
|
|||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<widget class="QGroupBox" name="logging_group">
|
||||
<property name="title">
|
||||
<string>Logging</string>
|
||||
</property>
|
||||
|
@ -107,18 +107,15 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_4">
|
||||
<widget class="QGroupBox" name="cpu_group">
|
||||
<property name="title">
|
||||
<string>CPU</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="toggle_cpu_jit">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Enables the use of the ARM JIT compiler for emulating the 3DS CPUs. Don't disable unless for debugging purposes</p></body></html></string>
|
||||
</property>
|
||||
<item row="4" column="0">
|
||||
<widget class="QCheckBox" name="toggle_renderer_debug">
|
||||
<property name="text">
|
||||
<string>Enable CPU JIT</string>
|
||||
<string>Enable debug renderer</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -203,10 +200,81 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="toggle_renderer_debug">
|
||||
<property name="text">
|
||||
<string>Enable debug renderer</string>
|
||||
<widget class="QCheckBox" name="toggle_cpu_jit">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Enables the use of the ARM JIT compiler for emulating the 3DS CPUs. Don't disable unless for debugging purposes</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Enable CPU JIT</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QWidget" name="refresh_rate_widget" native="true">
|
||||
<layout class="QHBoxLayout" name="refresh_rate_widget_2">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QComboBox" name="refresh_rate_combo">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Use global refresh rate</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Set refresh rate:</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="refresh_rate_label">
|
||||
<property name="text">
|
||||
<string>Refresh rate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="slider_refresh_rate">
|
||||
<property name="minimum">
|
||||
<number>30</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>360</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>30</number>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<number>30</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>60</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="refresh_display_label">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
|
|
@ -51,6 +51,8 @@ void Apply() {
|
|||
GDBStub::SetServerPort(values.gdbstub_port.GetValue());
|
||||
GDBStub::ToggleServer(values.use_gdbstub.GetValue());
|
||||
|
||||
GPU::SetRefreshRate(values.refresh_rate.GetValue());
|
||||
|
||||
VideoCore::g_shader_jit_enabled = values.use_shader_jit.GetValue();
|
||||
VideoCore::g_hw_shader_enabled = values.use_hw_shader.GetValue();
|
||||
VideoCore::g_separable_shader_enabled = values.separable_shader.GetValue();
|
||||
|
@ -112,6 +114,7 @@ void LogSettings() {
|
|||
LOG_INFO(Config, "Citra Configuration:");
|
||||
log_setting("Core_UseCpuJit", values.use_cpu_jit.GetValue());
|
||||
log_setting("Core_CPUClockPercentage", values.cpu_clock_percentage.GetValue());
|
||||
log_setting("Core_RefreshRate", values.refresh_rate.GetValue());
|
||||
log_setting("Renderer_UseGLES", values.use_gles.GetValue());
|
||||
log_setting("Renderer_GraphicsAPI", GetGraphicsAPIName(values.graphics_api.GetValue()));
|
||||
log_setting("Renderer_UseHwShader", values.use_hw_shader.GetValue());
|
||||
|
@ -195,6 +198,7 @@ void RestoreGlobalState(bool is_powered_on) {
|
|||
|
||||
// Core
|
||||
values.cpu_clock_percentage.SetGlobal(true);
|
||||
values.refresh_rate.SetGlobal(true);
|
||||
values.is_new_3ds.SetGlobal(true);
|
||||
|
||||
// Renderer
|
||||
|
|
|
@ -490,6 +490,7 @@ struct Values {
|
|||
std::unordered_map<std::string, bool> lle_modules;
|
||||
Setting<bool> use_gdbstub{false, "use_gdbstub"};
|
||||
Setting<u16> gdbstub_port{24689, "gdbstub_port"};
|
||||
SwitchableSetting<u32, true> refresh_rate{60, 30, 360, "refresh_rate"};
|
||||
|
||||
// Miscellaneous
|
||||
Setting<std::string> log_filter{"*:Info", "log_filter"};
|
||||
|
|
|
@ -27,6 +27,11 @@
|
|||
|
||||
namespace GPU {
|
||||
|
||||
// Measured on hardware to be 2240568 timer cycles or 4481136 ARM11 cycles
|
||||
u64 frame_ticks = 4481136ull;
|
||||
|
||||
double SCREEN_REFRESH_RATE = BASE_CLOCK_RATE_ARM11 / static_cast<double>(frame_ticks);
|
||||
|
||||
Regs g_regs;
|
||||
Memory::MemorySystem* g_memory;
|
||||
|
||||
|
@ -561,4 +566,9 @@ void Shutdown() {
|
|||
LOG_DEBUG(HW_GPU, "shutdown OK");
|
||||
}
|
||||
|
||||
void SetRefreshRate(u32 refresh) {
|
||||
frame_ticks = (4481136ull * 60) / refresh;
|
||||
SCREEN_REFRESH_RATE = BASE_CLOCK_RATE_ARM11 / static_cast<double>(frame_ticks);
|
||||
}
|
||||
|
||||
} // namespace GPU
|
||||
|
|
|
@ -21,11 +21,11 @@ class MemorySystem;
|
|||
namespace GPU {
|
||||
|
||||
// Measured on hardware to be 2240568 timer cycles or 4481136 ARM11 cycles
|
||||
constexpr u64 frame_ticks = 4481136ull;
|
||||
extern u64 frame_ticks;
|
||||
|
||||
// Refresh rate defined by ratio of ARM11 frequency to ARM11 ticks per frame
|
||||
// (268,111,856) / (4,481,136) = 59.83122493939037Hz
|
||||
constexpr double SCREEN_REFRESH_RATE = BASE_CLOCK_RATE_ARM11 / static_cast<double>(frame_ticks);
|
||||
extern double SCREEN_REFRESH_RATE;
|
||||
|
||||
// Returns index corresponding to the Regs member labeled by field_name
|
||||
#define GPU_REG_INDEX(field_name) (offsetof(GPU::Regs, field_name) / sizeof(u32))
|
||||
|
@ -328,4 +328,7 @@ void Init(Memory::MemorySystem& memory);
|
|||
/// Shutdown hardware
|
||||
void Shutdown();
|
||||
|
||||
/// Sets the screen refresh rate
|
||||
void SetRefreshRate(u32 refresh);
|
||||
|
||||
} // namespace GPU
|
||||
|
|
|
@ -115,7 +115,7 @@ PerfStats::Results PerfStats::GetAndResetStats(microseconds current_system_time_
|
|||
double PerfStats::GetLastFrameTimeScale() const {
|
||||
std::lock_guard lock{object_mutex};
|
||||
|
||||
constexpr double FRAME_LENGTH = 1.0 / GPU::SCREEN_REFRESH_RATE;
|
||||
const double FRAME_LENGTH = 1.0 / GPU::SCREEN_REFRESH_RATE;
|
||||
return duration_cast<DoubleSecs>(previous_frame_length).count() / FRAME_LENGTH;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue