diff options
| author | Zephyron <zephyron@citron-emu.org> | 2025-04-16 22:02:10 +1000 |
|---|---|---|
| committer | Mike Lothian <mike@fireburn.co.uk> | 2025-05-12 12:46:19 +0100 |
| commit | ea8bb22148a69ebe19b186073a06b21614913525 (patch) | |
| tree | b344da696dacba2c24921e6965c176015b44dedd | |
| parent | 6a845fd03bdfcf3435f7da840e6af1be6b74fee3 (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.h | 1 | ||||
| -rw-r--r-- | src/common/wall_clock.h | 33 | ||||
| -rw-r--r-- | src/core/hardware_properties.h | 3 | ||||
| -rw-r--r-- | src/core/hle/service/apm/apm_controller.cpp | 5 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_cpu.cpp | 23 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_cpu.ui | 61 |
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> |
