Somewhat functional clock timing setting
Some checks failed
eden-build / windows (msvc) (pull_request) Successful in 35m58s
eden-build / source (pull_request) Has been cancelled
eden-build / linux (pull_request) Has been cancelled
eden-build / android (pull_request) Has been cancelled
eden-license / license-header (pull_request_target) Has been cancelled

hangs when clock timing or both is set

Signed-off-by: swurl <swurl@swurl.xyz>
This commit is contained in:
swurl 2025-04-17 13:33:49 -04:00
parent 449edd5224
commit ec60d21616
Signed by: crueter
GPG key ID: A5A7629F109C8FD1
10 changed files with 64 additions and 60 deletions

View file

@ -231,11 +231,16 @@ struct Values {
CpuAccuracy::Auto, CpuAccuracy::Paranoid,
"cpu_accuracy", Category::Cpu};
SwitchableSetting<u32, true> cpu_clock_rate{linkage, 1020,
500, 1785,
SwitchableSetting<u32, true> cpu_clock_rate{linkage, 1,
1, 6,
"cpu_clock_rate", Category::Cpu,
Specialization::Scalar};
SwitchableSetting<CpuClockStrategy, true> cpu_clock_strategy{linkage, CpuClockStrategy::Clock,
CpuClockStrategy::None, CpuClockStrategy::Both,
"cpu_clock_strategy", Category::Cpu};
SwitchableSetting<bool> cpu_debug_mode{linkage, false, "cpu_debug_mode", Category::CpuDebug};
Setting<bool> cpuopt_page_tables{linkage, true, "cpuopt_page_tables", Category::CpuDebug};

View file

@ -134,6 +134,8 @@ ENUM(CpuBackend, Dynarmic, Nce);
ENUM(CpuAccuracy, Auto, Accurate, Unsafe, Paranoid);
ENUM(CpuClockStrategy, None, Clock, Timing, Both)
ENUM(MemoryLayout, Memory_4Gb, Memory_6Gb, Memory_8Gb);
ENUM(ConfirmStop, Ask_Always, Ask_Based_On_Game, Ask_Never);

View file

@ -8,7 +8,6 @@
#include <ratio>
#include "common/common_types.h"
#include "core/hardware_properties.h"
namespace Common {
@ -16,9 +15,7 @@ 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 inline u64 CPUTickFreq() {
return Core::Hardware::BASE_CLOCK_RATE();
}
static constexpr u64 CPUTickFreq = 1'020'000; // CPU Frequency = 1020.0MHz
virtual ~WallClock() = default;
@ -54,19 +51,19 @@ public:
// Cycle Timing
static inline u64 CPUTickToNS(u64 cpu_tick) {
return cpu_tick * CPUTickToNsRatio::num / CPUTickToNsRatio::den();
return cpu_tick * CPUTickToNsRatio::num / CPUTickToNsRatio::den;
}
static inline u64 CPUTickToUS(u64 cpu_tick) {
return cpu_tick * CPUTickToUsRatio::num / CPUTickToUsRatio::den();
return cpu_tick * CPUTickToUsRatio::num / CPUTickToUsRatio::den;
}
static inline u64 CPUTickToCNTPCT(u64 cpu_tick) {
return cpu_tick * CPUTickToCNTPCTRatio::num / CPUTickToCNTPCTRatio::den();
return cpu_tick * CPUTickToCNTPCTRatio::num / CPUTickToCNTPCTRatio::den;
}
static inline u64 CPUTickToGPUTick(u64 cpu_tick) {
return cpu_tick * CPUTickToGPUTickRatio::num / CPUTickToGPUTickRatio::den();
return cpu_tick * CPUTickToGPUTickRatio::num / CPUTickToGPUTickRatio::den;
}
protected:
@ -80,34 +77,10 @@ protected:
using NsToGPUTickRatio = std::ratio<GPUTickFreq, std::nano::den>;
// Cycle Timing
struct CPUTickToNsRatio {
static inline std::intmax_t num = std::nano::den;
static inline std::intmax_t den() {
return CPUTickFreq();
}
};
struct CPUTickToUsRatio {
static inline std::intmax_t num = std::micro::den;
static inline std::intmax_t den() {
return CPUTickFreq();
}
};
struct CPUTickToCNTPCTRatio {
static inline std::intmax_t num = CNTFRQ;
static inline std::intmax_t den() {
return CPUTickFreq();
}
};
struct CPUTickToGPUTickRatio {
static inline std::intmax_t num = GPUTickFreq;
static inline std::intmax_t den() {
return 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>;
};
std::unique_ptr<WallClock> CreateOptimalClock();

View file

@ -1,25 +1,28 @@
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <algorithm>
#include <mutex>
#include <string>
#include <tuple>
#include <iostream>
#include "common/settings.h"
#ifdef _WIN32
#include "common/windows/timer_resolution.h"
#endif
#ifdef ARCHITECTURE_x86_64
#include "common/x64/cpu_wait.h"
#endif
#include "common/microprofile.h"
#include "core/core_timing.h"
#include "core/hardware_properties.h"
namespace Core::Timing {
int CoreTiming::rate_multiplier = 1;
int CoreTiming::time_multiplier = 1;
constexpr s64 MAX_SLICE_LENGTH = 10000;
std::shared_ptr<EventType> CreateEvent(std::string name, TimedCallback&& callback) {
@ -185,14 +188,14 @@ void CoreTiming::ResetTicks() {
u64 CoreTiming::GetClockTicks() const {
if (is_multicore) [[likely]] {
return clock->GetCNTPCT();
return clock->GetCNTPCT() * rate_multiplier;
}
return Common::WallClock::CPUTickToCNTPCT(cpu_ticks);
}
u64 CoreTiming::GetGPUTicks() const {
if (is_multicore) [[likely]] {
return clock->GetGPUTick();
return clock->GetGPUTick() * rate_multiplier;
}
return Common::WallClock::CPUTickToGPUTick(cpu_ticks);
}
@ -302,6 +305,7 @@ void CoreTiming::ThreadLoop() {
}
void CoreTiming::Reset() {
std::cout << "reset called" << std::endl;
paused = true;
shutting_down = true;
pause_event.Set();
@ -311,18 +315,27 @@ void CoreTiming::Reset() {
}
timer_thread.reset();
has_started = false;
auto clock_strategy = Settings::values.cpu_clock_strategy.GetValue();
auto multiplier = Settings::values.cpu_clock_rate.GetValue();
time_multiplier = (clock_strategy == Settings::CpuClockStrategy::Timing || clock_strategy == Settings::CpuClockStrategy::Both) ? multiplier : 1;
rate_multiplier = (clock_strategy == Settings::CpuClockStrategy::Clock || clock_strategy == Settings::CpuClockStrategy::Both) ? multiplier : 1;
std::cout << "reset finished " << time_multiplier << " " << rate_multiplier << " " << (int) clock_strategy << " " << multiplier << " " << this << std::endl;
}
std::chrono::nanoseconds CoreTiming::GetGlobalTimeNs() const {
if (is_multicore) [[likely]] {
return clock->GetTimeNS();
LOG_INFO(Core, "GLOBAL TIME MULTIPLIER {:X}", time_multiplier);
return clock->GetTimeNS() * CoreTiming::time_multiplier;
}
return std::chrono::nanoseconds{Common::WallClock::CPUTickToNS(cpu_ticks)};
}
std::chrono::microseconds CoreTiming::GetGlobalTimeUs() const {
if (is_multicore) [[likely]] {
return clock->GetTimeUS();
return clock->GetTimeUS() * time_multiplier;
}
return std::chrono::microseconds{Common::WallClock::CPUTickToUS(cpu_ticks)};
}

View file

@ -15,6 +15,7 @@
#include <boost/heap/fibonacci_heap.hpp>
#include "common/common_types.h"
#include "common/settings_enums.h"
#include "common/thread.h"
#include "common/wall_clock.h"
@ -178,6 +179,10 @@ private:
/// Cycle timing
u64 cpu_ticks{};
s64 downcount{};
// Clock multipliers
static int rate_multiplier;
static int time_multiplier;
};
/// Creates a core timing event with the given name and callback.

View file

@ -5,22 +5,15 @@
#pragma once
#include <array>
#include <iostream>
#include "common/bit_util.h"
#include "common/common_types.h"
#include "common/settings.h"
#include "common/logging/log.h"
namespace Core {
namespace Hardware {
inline u64 BASE_CLOCK_RATE() {
LOG_DEBUG(Core, "Settings reported clock rate={:08X}", Settings::values.cpu_clock_rate.GetValue());
// std::cout << Settings::values.cpu_clock_rate.GetValue() << std::endl;
return Settings::values.cpu_clock_rate.GetValue() * 1'000'000;
}
constexpr u64 BASE_CLOCK_RATE = 1'020'000; // CPU Frequency = 1020.0 MHz
constexpr u64 CNTFREQ = 19'200'000; // CNTPCT_EL0 Frequency = 19.2 MHz
constexpr u32 NUM_CPU_CORES = 4; // Number of CPU Cores

View file

@ -80,10 +80,6 @@ PerformanceConfiguration Controller::GetCurrentPerformanceConfiguration(Performa
void Controller::SetClockSpeed(u32 mhz) {
LOG_DEBUG(Service_APM, "called, mhz={:08X}", mhz);
// TODO: needs to be verified
// Settings::values.cpu_clock_rate.SetGlobal(false);
// Settings::values.cpu_clock_rate.SetValue(mhz);
}
} // namespace Service::APM

View file

@ -9,7 +9,7 @@
#include "core/hle/service/vi/display_list.h"
#include "core/hle/service/vi/vsync_manager.h"
constexpr auto FrameNs = std::chrono::nanoseconds{1000000000 / 60};
constexpr auto FrameNs = std::chrono::nanoseconds{1'000'000'000 / 60};
namespace Service::VI {

View file

@ -74,7 +74,8 @@ void ConfigureCpu::Setup(const ConfigurationShared::Builder& builder) {
} else if (setting->Id() == Settings::values.cpu_backend.Id()) {
backend_layout->addWidget(widget);
backend_combobox = widget->combobox;
} else if (setting->Id() == Settings::values.cpu_clock_rate.Id()) {
} else if (setting->Id() == Settings::values.cpu_clock_rate.Id()
|| setting->Id() == Settings::values.cpu_clock_strategy.Id()) {
clock_layout->addWidget(widget);
} else {
// Presently, all other settings here are unsafe checkboxes

View file

@ -77,8 +77,14 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QWidget* parent) {
tr("This setting controls the accuracy of the emulated CPU.\nDon't change this unless "
"you know what you are doing."));
INSERT(Settings, cpu_backend, tr("Backend:"), QStringLiteral());
INSERT(Settings, cpu_clock_rate, tr("CPU Clock Rate (MHz):"), tr("Increasing CPU clock rate may "
INSERT(Settings, cpu_clock_rate, tr("CPU Clock Multiplier:"), tr("Increasing CPU clock speed may "
"improve performance, but may also reduce stability."));
INSERT(Settings, cpu_clock_strategy, tr("Clock Strategy:"),
tr("Some games use clock rate for timings, others use clock timing, and some even use both.\n"
"Generally, this setting will increase a game's default FPS, but may cause unintended\n"
"speedups or gameplay issues; for this reason, dedicated mods that unlock VSync and\n"
"enable dynamic FPS are preferred over this setting.\nOnly change if you know what you're "
"doing."));
// Cpu Debug
@ -356,6 +362,16 @@ std::unique_ptr<ComboboxTranslationMap> ComboboxEnumeration(QWidget* parent) {
PAIR(CpuAccuracy, Unsafe, tr("Unsafe")),
PAIR(CpuAccuracy, Paranoid, tr("Paranoid (disables most optimizations)")),
}});
translations->insert(
{Settings::EnumMetadata<Settings::CpuClockStrategy>::Index(),
{
PAIR(CpuClockStrategy, None, tr("None")),
PAIR(CpuClockStrategy, Clock, tr("Clock Rate")),
PAIR(CpuClockStrategy, Timing, tr("Clock Timing")),
PAIR(CpuClockStrategy, Both, tr("Both")),
}});
translations->insert({Settings::EnumMetadata<Settings::CpuBackend>::Index(),
{
PAIR(CpuBackend, Dynarmic, tr("Dynarmic")),