summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZephyron <zephyron@citron-emu.org>2025-04-16 22:02:10 +1000
committerMike Lothian <mike@fireburn.co.uk>2025-05-12 12:46:19 +0100
commitea8bb22148a69ebe19b186073a06b21614913525 (patch)
treeb344da696dacba2c24921e6965c176015b44dedd
parent6a845fd03bdfcf3435f7da840e6af1be6b74fee3 (diff)
feat: add CPU clock rate slider to settings
Implement a slider in the CPU settings tab to adjust the BASE_CLOCK_RATE up to 1,785 MHz (Switch's official maximum clock rate). Default remains at 1,020 MHz. This change: - Adds UI slider and spinbox to configure_cpu.ui with range 500-1785 MHz - Makes BASE_CLOCK_RATE dynamic by reading from settings - Modifies WallClock to handle dynamic clock rate changes - Updates APM controller to properly set the clock rate - Changes clock rate settings category from Core to CPU The user can now easily adjust the CPU clock rate to improve performance or manage thermals and power consumption. Signed-off-by: Zephyron <zephyron@citron-emu.org>
-rw-r--r--src/common/settings.h1
-rw-r--r--src/common/wall_clock.h33
-rw-r--r--src/core/hardware_properties.h3
-rw-r--r--src/core/hle/service/apm/apm_controller.cpp5
-rw-r--r--src/yuzu/configuration/configure_cpu.cpp23
-rw-r--r--src/yuzu/configuration/configure_cpu.ui61
6 files changed, 116 insertions, 10 deletions
diff --git a/src/common/settings.h b/src/common/settings.h
index ae90eda83..2df3325e8 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -199,6 +199,7 @@ struct Values {
MemoryLayout::Memory_12Gb,
"memory_layout_mode",
Category::Core};
+ SwitchableSetting<u32> cpu_clock_rate{linkage, 1'020'000'000, "cpu_clock_rate", Category::Cpu};
SwitchableSetting<bool> use_speed_limit{
linkage, true, "use_speed_limit", Category::Core, Specialization::Paired, false, true};
SwitchableSetting<u16, true> speed_limit{linkage,
diff --git a/src/common/wall_clock.h b/src/common/wall_clock.h
index 3a0c43909..8b971c3be 100644
--- a/src/common/wall_clock.h
+++ b/src/common/wall_clock.h
@@ -1,4 +1,5 @@
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
+// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
@@ -8,6 +9,7 @@
#include <ratio>
#include "common/common_types.h"
+#include "core/hardware_properties.h"
namespace Common {
@@ -15,7 +17,10 @@ class WallClock {
public:
static constexpr u64 CNTFRQ = 19'200'000; // CNTPCT_EL0 Frequency = 19.2 MHz
static constexpr u64 GPUTickFreq = 614'400'000; // GM20B GPU Tick Frequency = 614.4 MHz
- static constexpr u64 CPUTickFreq = 1'020'000'000; // T210/4 A57 CPU Tick Frequency = 1020.0 MHz
+ // Changed from constexpr to function to get dynamic value from settings
+ static inline u64 CPUTickFreq() {
+ return Core::Hardware::BASE_CLOCK_RATE();
+ } // T210/4 A57 CPU Tick Frequency from settings
virtual ~WallClock() = default;
@@ -76,12 +81,28 @@ protected:
using NsToCNTPCTRatio = std::ratio<CNTFRQ, std::nano::den>;
using NsToGPUTickRatio = std::ratio<GPUTickFreq, std::nano::den>;
- // Cycle Timing
+ // Cycle Timing - using functions for dynamic values
+
+ // Update these to use functions instead of constexpr
+ struct CPUTickToNsRatio {
+ static inline std::intmax_t num = std::nano::den;
+ static inline std::intmax_t den = CPUTickFreq();
+ };
+
+ struct CPUTickToUsRatio {
+ static inline std::intmax_t num = std::micro::den;
+ static inline std::intmax_t den = CPUTickFreq();
+ };
+
+ struct CPUTickToCNTPCTRatio {
+ static inline std::intmax_t num = CNTFRQ;
+ static inline std::intmax_t den = CPUTickFreq();
+ };
- using CPUTickToNsRatio = std::ratio<std::nano::den, CPUTickFreq>;
- using CPUTickToUsRatio = std::ratio<std::micro::den, CPUTickFreq>;
- using CPUTickToCNTPCTRatio = std::ratio<CNTFRQ, CPUTickFreq>;
- using CPUTickToGPUTickRatio = std::ratio<GPUTickFreq, CPUTickFreq>;
+ struct CPUTickToGPUTickRatio {
+ static inline std::intmax_t num = GPUTickFreq;
+ static inline std::intmax_t den = CPUTickFreq();
+ };
};
std::unique_ptr<WallClock> CreateOptimalClock();
diff --git a/src/core/hardware_properties.h b/src/core/hardware_properties.h
index 5b4630ec5..1b389be29 100644
--- a/src/core/hardware_properties.h
+++ b/src/core/hardware_properties.h
@@ -9,12 +9,13 @@
#include "common/bit_util.h"
#include "common/common_types.h"
+#include "common/settings.h"
namespace Core {
namespace Hardware {
-constexpr u64 BASE_CLOCK_RATE = 1'020'000'000; // Default CPU Frequency = 1020 MHz
+inline u64 BASE_CLOCK_RATE() { return Settings::values.cpu_clock_rate.GetValue(); } // Default CPU Frequency set in settings, defaults to 1020 MHz
constexpr u64 CNTFREQ = 19'200'000; // CNTPCT_EL0 Frequency = 19.2 MHz
constexpr u32 NUM_CPU_CORES = 4; // Number of CPU Cores
diff --git a/src/core/hle/service/apm/apm_controller.cpp b/src/core/hle/service/apm/apm_controller.cpp
index 4f1aa5cc2..abbee804b 100644
--- a/src/core/hle/service/apm/apm_controller.cpp
+++ b/src/core/hle/service/apm/apm_controller.cpp
@@ -1,4 +1,5 @@
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
+// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <algorithm>
@@ -81,8 +82,8 @@ PerformanceConfiguration Controller::GetCurrentPerformanceConfiguration(Performa
void Controller::SetClockSpeed(u32 mhz) {
LOG_DEBUG(Service_APM, "called, mhz={:08X}", mhz);
- // TODO(DarkLordZach): Actually signal core_timing to change clock speed.
- // TODO(Rodrigo): Remove [[maybe_unused]] when core_timing is used.
+ // Update the clock rate setting with the provided MHz value (convert to Hz)
+ Settings::values.cpu_clock_rate = mhz * 1'000'000;
}
} // namespace Service::APM
diff --git a/src/yuzu/configuration/configure_cpu.cpp b/src/yuzu/configuration/configure_cpu.cpp
index 36232a1e4..35780fc24 100644
--- a/src/yuzu/configuration/configure_cpu.cpp
+++ b/src/yuzu/configuration/configure_cpu.cpp
@@ -1,10 +1,13 @@
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
+// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <memory>
#include <typeinfo>
#include <vector>
#include <QComboBox>
+#include <QSpinBox>
+#include <QSlider>
#include "common/common_types.h"
#include "common/settings.h"
#include "common/settings_enums.h"
@@ -38,7 +41,22 @@ ConfigureCpu::ConfigureCpu(const Core::System& system_,
ConfigureCpu::~ConfigureCpu() = default;
-void ConfigureCpu::SetConfiguration() {}
+void ConfigureCpu::SetConfiguration() {
+ // Set clock rate values from settings
+ const u32 clock_rate_mhz = Settings::values.cpu_clock_rate.GetValue() / 1'000'000;
+ ui->clock_rate_slider->setValue(static_cast<int>(clock_rate_mhz));
+ ui->clock_rate_spinbox->setValue(static_cast<int>(clock_rate_mhz));
+
+ // Connect slider and spinbox signals to keep them in sync
+ connect(ui->clock_rate_slider, &QSlider::valueChanged, this, [this](int value) {
+ ui->clock_rate_spinbox->setValue(value);
+ });
+
+ connect(ui->clock_rate_spinbox, QOverload<int>::of(&QSpinBox::valueChanged), this, [this](int value) {
+ ui->clock_rate_slider->setValue(value);
+ });
+}
+
void ConfigureCpu::Setup(const ConfigurationShared::Builder& builder) {
auto* accuracy_layout = ui->widget_accuracy->layout();
auto* backend_layout = ui->widget_backend->layout();
@@ -99,6 +117,9 @@ void ConfigureCpu::ApplyConfiguration() {
for (const auto& apply_func : apply_funcs) {
apply_func(is_powered_on);
}
+
+ // Save the clock rate setting (convert from MHz to Hz)
+ Settings::values.cpu_clock_rate = static_cast<u32>(ui->clock_rate_spinbox->value()) * 1'000'000;
}
void ConfigureCpu::changeEvent(QEvent* event) {
diff --git a/src/yuzu/configuration/configure_cpu.ui b/src/yuzu/configuration/configure_cpu.ui
index 13fd43605..3521f3ab1 100644
--- a/src/yuzu/configuration/configure_cpu.ui
+++ b/src/yuzu/configuration/configure_cpu.ui
@@ -127,6 +127,67 @@
</widget>
</item>
<item>
+ <widget class="QGroupBox" name="clock_rate_group">
+ <property name="title">
+ <string>CPU Clock Rate</string>
+ </property>
+ <layout class="QVBoxLayout">
+ <item>
+ <widget class="QLabel" name="label_clock_description">
+ <property name="text">
+ <string>CPU clock rate in MHz. Setting a higher clock rate will improve performance but may cause system instability. Default is 1020 MHz.</string>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout">
+ <item>
+ <widget class="QSlider" name="clock_rate_slider">
+ <property name="minimum">
+ <number>500</number>
+ </property>
+ <property name="maximum">
+ <number>1785</number>
+ </property>
+ <property name="value">
+ <number>1020</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TicksBelow</enum>
+ </property>
+ <property name="tickInterval">
+ <number>100</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSpinBox" name="clock_rate_spinbox">
+ <property name="suffix">
+ <string> MHz</string>
+ </property>
+ <property name="minimum">
+ <number>500</number>
+ </property>
+ <property name="maximum">
+ <number>1785</number>
+ </property>
+ <property name="value">
+ <number>1020</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>