summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Morph2023-06-07 21:38:28 -0400
committerGravatar Morph2023-06-07 21:44:42 -0400
commit2e1e7254436b032f133372c76d9484aa756d56df (patch)
treece55efc11d5dee53a87532b77ce85d3e0d2b2a76 /src
parent(wall, native)_clock: Add GetGPUTick (diff)
downloadyuzu-2e1e7254436b032f133372c76d9484aa756d56df.tar.gz
yuzu-2e1e7254436b032f133372c76d9484aa756d56df.tar.xz
yuzu-2e1e7254436b032f133372c76d9484aa756d56df.zip
core_timing: Fix SingleCore cycle timer
Diffstat (limited to 'src')
-rw-r--r--src/common/wall_clock.h36
-rw-r--r--src/core/core_timing.cpp26
-rw-r--r--src/core/core_timing.h2
-rw-r--r--src/core/hle/kernel/svc/svc_tick.cpp10
4 files changed, 31 insertions, 43 deletions
diff --git a/src/common/wall_clock.h b/src/common/wall_clock.h
index fcfdd637c..f45d3d8c5 100644
--- a/src/common/wall_clock.h
+++ b/src/common/wall_clock.h
@@ -13,8 +13,9 @@ namespace Common {
13 13
14class WallClock { 14class WallClock {
15public: 15public:
16 static constexpr u64 CNTFRQ = 19'200'000; // CNTPCT_EL0 Frequency = 19.2 MHz 16 static constexpr u64 CNTFRQ = 19'200'000; // CNTPCT_EL0 Frequency = 19.2 MHz
17 static constexpr u64 GPUTickFreq = 614'400'000; // GM20B GPU Tick Frequency = 614.4 MHz 17 static constexpr u64 GPUTickFreq = 614'400'000; // GM20B GPU Tick Frequency = 614.4 MHz
18 static constexpr u64 CPUTickFreq = 1'020'000'000; // T210/4 A57 CPU Tick Frequency = 1020.0 MHz
18 19
19 virtual ~WallClock() = default; 20 virtual ~WallClock() = default;
20 21
@@ -46,28 +47,26 @@ public:
46 return ns * NsToCNTPCTRatio::num / NsToCNTPCTRatio::den; 47 return ns * NsToCNTPCTRatio::num / NsToCNTPCTRatio::den;
47 } 48 }
48 49
49 static inline u64 USToCNTPCT(u64 us) {
50 return us * UsToCNTPCTRatio::num / UsToCNTPCTRatio::den;
51 }
52
53 static inline u64 NSToGPUTick(u64 ns) { 50 static inline u64 NSToGPUTick(u64 ns) {
54 return ns * NsToGPUTickRatio::num / NsToGPUTickRatio::den; 51 return ns * NsToGPUTickRatio::num / NsToGPUTickRatio::den;
55 } 52 }
56 53
57 static inline u64 CNTPCTToNS(u64 cntpct) { 54 // Cycle Timing
58 return cntpct * NsToCNTPCTRatio::den / NsToCNTPCTRatio::num; 55
56 static inline u64 CPUTickToNS(u64 cpu_tick) {
57 return cpu_tick * CPUTickToNsRatio::num / CPUTickToNsRatio::den;
59 } 58 }
60 59
61 static inline u64 CNTPCTToUS(u64 cntpct) { 60 static inline u64 CPUTickToUS(u64 cpu_tick) {
62 return cntpct * UsToCNTPCTRatio::den / UsToCNTPCTRatio::num; 61 return cpu_tick * CPUTickToUsRatio::num / CPUTickToUsRatio::den;
63 } 62 }
64 63
65 static inline u64 GPUTickToNS(u64 gpu_tick) { 64 static inline u64 CPUTickToCNTPCT(u64 cpu_tick) {
66 return gpu_tick * NsToGPUTickRatio::den / NsToGPUTickRatio::num; 65 return cpu_tick * CPUTickToCNTPCTRatio::num / CPUTickToCNTPCTRatio::den;
67 } 66 }
68 67
69 static inline u64 CNTPCTToGPUTick(u64 cntpct) { 68 static inline u64 CPUTickToGPUTick(u64 cpu_tick) {
70 return cntpct * CNTPCTToGPUTickRatio::num / CNTPCTToGPUTickRatio::den; 69 return cpu_tick * CPUTickToGPUTickRatio::num / CPUTickToGPUTickRatio::den;
71 } 70 }
72 71
73protected: 72protected:
@@ -78,9 +77,14 @@ protected:
78 using NsToUsRatio = std::ratio_divide<std::nano, std::micro>; 77 using NsToUsRatio = std::ratio_divide<std::nano, std::micro>;
79 using NsToMsRatio = std::ratio_divide<std::nano, std::milli>; 78 using NsToMsRatio = std::ratio_divide<std::nano, std::milli>;
80 using NsToCNTPCTRatio = std::ratio<CNTFRQ, std::nano::den>; 79 using NsToCNTPCTRatio = std::ratio<CNTFRQ, std::nano::den>;
81 using UsToCNTPCTRatio = std::ratio<CNTFRQ, std::micro::den>;
82 using NsToGPUTickRatio = std::ratio<GPUTickFreq, std::nano::den>; 80 using NsToGPUTickRatio = std::ratio<GPUTickFreq, std::nano::den>;
83 using CNTPCTToGPUTickRatio = std::ratio<GPUTickFreq, CNTFRQ>; 81
82 // Cycle Timing
83
84 using CPUTickToNsRatio = std::ratio<std::nano::den, CPUTickFreq>;
85 using CPUTickToUsRatio = std::ratio<std::micro::den, CPUTickFreq>;
86 using CPUTickToCNTPCTRatio = std::ratio<CNTFRQ, CPUTickFreq>;
87 using CPUTickToGPUTickRatio = std::ratio<GPUTickFreq, CPUTickFreq>;
84}; 88};
85 89
86std::unique_ptr<WallClock> CreateOptimalClock(); 90std::unique_ptr<WallClock> CreateOptimalClock();
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp
index e57bca70a..4f0a3f8ea 100644
--- a/src/core/core_timing.cpp
+++ b/src/core/core_timing.cpp
@@ -20,7 +20,7 @@
20 20
21namespace Core::Timing { 21namespace Core::Timing {
22 22
23constexpr s64 MAX_SLICE_LENGTH = 4000; 23constexpr s64 MAX_SLICE_LENGTH = 10000;
24 24
25std::shared_ptr<EventType> CreateEvent(std::string name, TimedCallback&& callback) { 25std::shared_ptr<EventType> CreateEvent(std::string name, TimedCallback&& callback) {
26 return std::make_shared<EventType>(std::move(callback), std::move(name)); 26 return std::make_shared<EventType>(std::move(callback), std::move(name));
@@ -65,7 +65,7 @@ void CoreTiming::Initialize(std::function<void()>&& on_thread_init_) {
65 on_thread_init = std::move(on_thread_init_); 65 on_thread_init = std::move(on_thread_init_);
66 event_fifo_id = 0; 66 event_fifo_id = 0;
67 shutting_down = false; 67 shutting_down = false;
68 ticks = 0; 68 cpu_ticks = 0;
69 const auto empty_timed_callback = [](std::uintptr_t, u64, std::chrono::nanoseconds) 69 const auto empty_timed_callback = [](std::uintptr_t, u64, std::chrono::nanoseconds)
70 -> std::optional<std::chrono::nanoseconds> { return std::nullopt; }; 70 -> std::optional<std::chrono::nanoseconds> { return std::nullopt; };
71 ev_lost = CreateEvent("_lost_event", empty_timed_callback); 71 ev_lost = CreateEvent("_lost_event", empty_timed_callback);
@@ -170,20 +170,12 @@ void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type,
170} 170}
171 171
172void CoreTiming::AddTicks(u64 ticks_to_add) { 172void CoreTiming::AddTicks(u64 ticks_to_add) {
173 ticks += ticks_to_add; 173 cpu_ticks += ticks_to_add;
174 downcount -= static_cast<s64>(ticks); 174 downcount -= static_cast<s64>(cpu_ticks);
175} 175}
176 176
177void CoreTiming::Idle() { 177void CoreTiming::Idle() {
178 if (!event_queue.empty()) { 178 cpu_ticks += 1000U;
179 const u64 next_event_time = event_queue.front().time;
180 const u64 next_ticks = Common::WallClock::NSToCNTPCT(next_event_time) + 10U;
181 if (next_ticks > ticks) {
182 ticks = next_ticks;
183 }
184 return;
185 }
186 ticks += 1000U;
187} 179}
188 180
189void CoreTiming::ResetTicks() { 181void CoreTiming::ResetTicks() {
@@ -194,14 +186,14 @@ u64 CoreTiming::GetClockTicks() const {
194 if (is_multicore) [[likely]] { 186 if (is_multicore) [[likely]] {
195 return clock->GetCNTPCT(); 187 return clock->GetCNTPCT();
196 } 188 }
197 return ticks; 189 return Common::WallClock::CPUTickToCNTPCT(cpu_ticks);
198} 190}
199 191
200u64 CoreTiming::GetGPUTicks() const { 192u64 CoreTiming::GetGPUTicks() const {
201 if (is_multicore) [[likely]] { 193 if (is_multicore) [[likely]] {
202 return clock->GetGPUTick(); 194 return clock->GetGPUTick();
203 } 195 }
204 return Common::WallClock::CNTPCTToGPUTick(ticks); 196 return Common::WallClock::CPUTickToGPUTick(cpu_ticks);
205} 197}
206 198
207std::optional<s64> CoreTiming::Advance() { 199std::optional<s64> CoreTiming::Advance() {
@@ -314,14 +306,14 @@ std::chrono::nanoseconds CoreTiming::GetGlobalTimeNs() const {
314 if (is_multicore) [[likely]] { 306 if (is_multicore) [[likely]] {
315 return clock->GetTimeNS(); 307 return clock->GetTimeNS();
316 } 308 }
317 return std::chrono::nanoseconds{Common::WallClock::CNTPCTToNS(ticks)}; 309 return std::chrono::nanoseconds{Common::WallClock::CPUTickToNS(cpu_ticks)};
318} 310}
319 311
320std::chrono::microseconds CoreTiming::GetGlobalTimeUs() const { 312std::chrono::microseconds CoreTiming::GetGlobalTimeUs() const {
321 if (is_multicore) [[likely]] { 313 if (is_multicore) [[likely]] {
322 return clock->GetTimeUS(); 314 return clock->GetTimeUS();
323 } 315 }
324 return std::chrono::microseconds{Common::WallClock::CNTPCTToUS(ticks)}; 316 return std::chrono::microseconds{Common::WallClock::CPUTickToUS(cpu_ticks)};
325} 317}
326 318
327} // namespace Core::Timing 319} // namespace Core::Timing
diff --git a/src/core/core_timing.h b/src/core/core_timing.h
index 1873852c4..10db1de55 100644
--- a/src/core/core_timing.h
+++ b/src/core/core_timing.h
@@ -167,7 +167,7 @@ private:
167 s64 pause_end_time{}; 167 s64 pause_end_time{};
168 168
169 /// Cycle timing 169 /// Cycle timing
170 u64 ticks{}; 170 u64 cpu_ticks{};
171 s64 downcount{}; 171 s64 downcount{};
172}; 172};
173 173
diff --git a/src/core/hle/kernel/svc/svc_tick.cpp b/src/core/hle/kernel/svc/svc_tick.cpp
index 561336482..7dd7c6e51 100644
--- a/src/core/hle/kernel/svc/svc_tick.cpp
+++ b/src/core/hle/kernel/svc/svc_tick.cpp
@@ -12,16 +12,8 @@ namespace Kernel::Svc {
12int64_t GetSystemTick(Core::System& system) { 12int64_t GetSystemTick(Core::System& system) {
13 LOG_TRACE(Kernel_SVC, "called"); 13 LOG_TRACE(Kernel_SVC, "called");
14 14
15 auto& core_timing = system.CoreTiming();
16
17 // Returns the value of cntpct_el0 (https://switchbrew.org/wiki/SVC#svcGetSystemTick) 15 // Returns the value of cntpct_el0 (https://switchbrew.org/wiki/SVC#svcGetSystemTick)
18 const u64 result{core_timing.GetClockTicks()}; 16 return static_cast<int64_t>(system.CoreTiming().GetClockTicks());
19
20 if (!system.Kernel().IsMulticore()) {
21 core_timing.AddTicks(400U);
22 }
23
24 return static_cast<int64_t>(result);
25} 17}
26 18
27int64_t GetSystemTick64(Core::System& system) { 19int64_t GetSystemTick64(Core::System& system) {