summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/wall_clock.cpp8
-rw-r--r--src/common/wall_clock.h20
-rw-r--r--src/common/x64/native_clock.cpp7
-rw-r--r--src/common/x64/native_clock.h3
-rw-r--r--src/core/core_timing.cpp7
-rw-r--r--src/core/core_timing.h3
-rw-r--r--src/video_core/gpu.cpp11
7 files changed, 47 insertions, 12 deletions
diff --git a/src/common/wall_clock.cpp b/src/common/wall_clock.cpp
index ad8db06b0..dc0dcbd68 100644
--- a/src/common/wall_clock.cpp
+++ b/src/common/wall_clock.cpp
@@ -32,6 +32,10 @@ public:
32 return GetHostTicksElapsed() * NsToCNTPCTRatio::num / NsToCNTPCTRatio::den; 32 return GetHostTicksElapsed() * NsToCNTPCTRatio::num / NsToCNTPCTRatio::den;
33 } 33 }
34 34
35 u64 GetGPUTick() const override {
36 return GetHostTicksElapsed() * NsToGPUTickRatio::num / NsToGPUTickRatio::den;
37 }
38
35 u64 GetHostTicksNow() const override { 39 u64 GetHostTicksNow() const override {
36 return static_cast<u64>(SteadyClock::Now().time_since_epoch().count()); 40 return static_cast<u64>(SteadyClock::Now().time_since_epoch().count());
37 } 41 }
@@ -52,12 +56,12 @@ std::unique_ptr<WallClock> CreateOptimalClock() {
52#ifdef ARCHITECTURE_x86_64 56#ifdef ARCHITECTURE_x86_64
53 const auto& caps = GetCPUCaps(); 57 const auto& caps = GetCPUCaps();
54 58
55 if (caps.invariant_tsc && caps.tsc_frequency >= WallClock::CNTFRQ) { 59 if (caps.invariant_tsc && caps.tsc_frequency >= WallClock::GPUTickFreq) {
56 return std::make_unique<X64::NativeClock>(caps.tsc_frequency); 60 return std::make_unique<X64::NativeClock>(caps.tsc_frequency);
57 } else { 61 } else {
58 // Fallback to StandardWallClock if the hardware TSC 62 // Fallback to StandardWallClock if the hardware TSC
59 // - Is not invariant 63 // - Is not invariant
60 // - Is not more precise than CNTFRQ 64 // - Is not more precise than GPUTickFreq
61 return std::make_unique<StandardWallClock>(); 65 return std::make_unique<StandardWallClock>();
62 } 66 }
63#else 67#else
diff --git a/src/common/wall_clock.h b/src/common/wall_clock.h
index 56c18ca25..fcfdd637c 100644
--- a/src/common/wall_clock.h
+++ b/src/common/wall_clock.h
@@ -13,7 +13,8 @@ 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 18
18 virtual ~WallClock() = default; 19 virtual ~WallClock() = default;
19 20
@@ -29,6 +30,9 @@ public:
29 /// @returns The guest CNTPCT ticks since the construction of this clock. 30 /// @returns The guest CNTPCT ticks since the construction of this clock.
30 virtual u64 GetCNTPCT() const = 0; 31 virtual u64 GetCNTPCT() const = 0;
31 32
33 /// @returns The guest GPU ticks since the construction of this clock.
34 virtual u64 GetGPUTick() const = 0;
35
32 /// @returns The raw host timer ticks since an indeterminate epoch. 36 /// @returns The raw host timer ticks since an indeterminate epoch.
33 virtual u64 GetHostTicksNow() const = 0; 37 virtual u64 GetHostTicksNow() const = 0;
34 38
@@ -46,6 +50,10 @@ public:
46 return us * UsToCNTPCTRatio::num / UsToCNTPCTRatio::den; 50 return us * UsToCNTPCTRatio::num / UsToCNTPCTRatio::den;
47 } 51 }
48 52
53 static inline u64 NSToGPUTick(u64 ns) {
54 return ns * NsToGPUTickRatio::num / NsToGPUTickRatio::den;
55 }
56
49 static inline u64 CNTPCTToNS(u64 cntpct) { 57 static inline u64 CNTPCTToNS(u64 cntpct) {
50 return cntpct * NsToCNTPCTRatio::den / NsToCNTPCTRatio::num; 58 return cntpct * NsToCNTPCTRatio::den / NsToCNTPCTRatio::num;
51 } 59 }
@@ -54,6 +62,14 @@ public:
54 return cntpct * UsToCNTPCTRatio::den / UsToCNTPCTRatio::num; 62 return cntpct * UsToCNTPCTRatio::den / UsToCNTPCTRatio::num;
55 } 63 }
56 64
65 static inline u64 GPUTickToNS(u64 gpu_tick) {
66 return gpu_tick * NsToGPUTickRatio::den / NsToGPUTickRatio::num;
67 }
68
69 static inline u64 CNTPCTToGPUTick(u64 cntpct) {
70 return cntpct * CNTPCTToGPUTickRatio::num / CNTPCTToGPUTickRatio::den;
71 }
72
57protected: 73protected:
58 using NsRatio = std::nano; 74 using NsRatio = std::nano;
59 using UsRatio = std::micro; 75 using UsRatio = std::micro;
@@ -63,6 +79,8 @@ protected:
63 using NsToMsRatio = std::ratio_divide<std::nano, std::milli>; 79 using NsToMsRatio = std::ratio_divide<std::nano, std::milli>;
64 using NsToCNTPCTRatio = std::ratio<CNTFRQ, std::nano::den>; 80 using NsToCNTPCTRatio = std::ratio<CNTFRQ, std::nano::den>;
65 using UsToCNTPCTRatio = std::ratio<CNTFRQ, std::micro::den>; 81 using UsToCNTPCTRatio = std::ratio<CNTFRQ, std::micro::den>;
82 using NsToGPUTickRatio = std::ratio<GPUTickFreq, std::nano::den>;
83 using CNTPCTToGPUTickRatio = std::ratio<GPUTickFreq, CNTFRQ>;
66}; 84};
67 85
68std::unique_ptr<WallClock> CreateOptimalClock(); 86std::unique_ptr<WallClock> CreateOptimalClock();
diff --git a/src/common/x64/native_clock.cpp b/src/common/x64/native_clock.cpp
index 5d1eb0590..7d2a26bd9 100644
--- a/src/common/x64/native_clock.cpp
+++ b/src/common/x64/native_clock.cpp
@@ -12,7 +12,8 @@ NativeClock::NativeClock(u64 rdtsc_frequency_)
12 ns_rdtsc_factor{GetFixedPoint64Factor(NsRatio::den, rdtsc_frequency)}, 12 ns_rdtsc_factor{GetFixedPoint64Factor(NsRatio::den, rdtsc_frequency)},
13 us_rdtsc_factor{GetFixedPoint64Factor(UsRatio::den, rdtsc_frequency)}, 13 us_rdtsc_factor{GetFixedPoint64Factor(UsRatio::den, rdtsc_frequency)},
14 ms_rdtsc_factor{GetFixedPoint64Factor(MsRatio::den, rdtsc_frequency)}, 14 ms_rdtsc_factor{GetFixedPoint64Factor(MsRatio::den, rdtsc_frequency)},
15 cntpct_rdtsc_factor{GetFixedPoint64Factor(CNTFRQ, rdtsc_frequency)} {} 15 cntpct_rdtsc_factor{GetFixedPoint64Factor(CNTFRQ, rdtsc_frequency)},
16 gputick_rdtsc_factor{GetFixedPoint64Factor(GPUTickFreq, rdtsc_frequency)} {}
16 17
17std::chrono::nanoseconds NativeClock::GetTimeNS() const { 18std::chrono::nanoseconds NativeClock::GetTimeNS() const {
18 return std::chrono::nanoseconds{MultiplyHigh(GetHostTicksElapsed(), ns_rdtsc_factor)}; 19 return std::chrono::nanoseconds{MultiplyHigh(GetHostTicksElapsed(), ns_rdtsc_factor)};
@@ -30,6 +31,10 @@ u64 NativeClock::GetCNTPCT() const {
30 return MultiplyHigh(GetHostTicksElapsed(), cntpct_rdtsc_factor); 31 return MultiplyHigh(GetHostTicksElapsed(), cntpct_rdtsc_factor);
31} 32}
32 33
34u64 NativeClock::GetGPUTick() const {
35 return MultiplyHigh(GetHostTicksElapsed(), gputick_rdtsc_factor);
36}
37
33u64 NativeClock::GetHostTicksNow() const { 38u64 NativeClock::GetHostTicksNow() const {
34 return FencedRDTSC(); 39 return FencedRDTSC();
35} 40}
diff --git a/src/common/x64/native_clock.h b/src/common/x64/native_clock.h
index d6f8626c1..334415eff 100644
--- a/src/common/x64/native_clock.h
+++ b/src/common/x64/native_clock.h
@@ -19,6 +19,8 @@ public:
19 19
20 u64 GetCNTPCT() const override; 20 u64 GetCNTPCT() const override;
21 21
22 u64 GetGPUTick() const override;
23
22 u64 GetHostTicksNow() const override; 24 u64 GetHostTicksNow() const override;
23 25
24 u64 GetHostTicksElapsed() const override; 26 u64 GetHostTicksElapsed() const override;
@@ -33,6 +35,7 @@ private:
33 u64 us_rdtsc_factor; 35 u64 us_rdtsc_factor;
34 u64 ms_rdtsc_factor; 36 u64 ms_rdtsc_factor;
35 u64 cntpct_rdtsc_factor; 37 u64 cntpct_rdtsc_factor;
38 u64 gputick_rdtsc_factor;
36}; 39};
37 40
38} // namespace Common::X64 41} // namespace Common::X64
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp
index 9a1d5a69a..e57bca70a 100644
--- a/src/core/core_timing.cpp
+++ b/src/core/core_timing.cpp
@@ -197,6 +197,13 @@ u64 CoreTiming::GetClockTicks() const {
197 return ticks; 197 return ticks;
198} 198}
199 199
200u64 CoreTiming::GetGPUTicks() const {
201 if (is_multicore) [[likely]] {
202 return clock->GetGPUTick();
203 }
204 return Common::WallClock::CNTPCTToGPUTick(ticks);
205}
206
200std::optional<s64> CoreTiming::Advance() { 207std::optional<s64> CoreTiming::Advance() {
201 std::scoped_lock lock{advance_lock, basic_lock}; 208 std::scoped_lock lock{advance_lock, basic_lock};
202 global_timer = GetGlobalTimeNs().count(); 209 global_timer = GetGlobalTimeNs().count();
diff --git a/src/core/core_timing.h b/src/core/core_timing.h
index fdacdd94a..1873852c4 100644
--- a/src/core/core_timing.h
+++ b/src/core/core_timing.h
@@ -119,6 +119,9 @@ public:
119 /// Returns the current CNTPCT tick value. 119 /// Returns the current CNTPCT tick value.
120 u64 GetClockTicks() const; 120 u64 GetClockTicks() const;
121 121
122 /// Returns the current GPU tick value.
123 u64 GetGPUTicks() const;
124
122 /// Returns current time in microseconds. 125 /// Returns current time in microseconds.
123 std::chrono::microseconds GetGlobalTimeUs() const; 126 std::chrono::microseconds GetGlobalTimeUs() const;
124 127
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp
index 70762c51a..db385076d 100644
--- a/src/video_core/gpu.cpp
+++ b/src/video_core/gpu.cpp
@@ -193,18 +193,13 @@ struct GPU::Impl {
193 } 193 }
194 194
195 [[nodiscard]] u64 GetTicks() const { 195 [[nodiscard]] u64 GetTicks() const {
196 // This values were reversed engineered by fincs from NVN 196 u64 gpu_tick = system.CoreTiming().GetGPUTicks();
197 // The GPU clock is 614.4 MHz
198 using NsToGPUTickRatio = std::ratio<614'400'000, std::nano::den>;
199 static_assert(NsToGPUTickRatio::num == 384 && NsToGPUTickRatio::den == 625);
200
201 u64 nanoseconds = system.CoreTiming().GetGlobalTimeNs().count();
202 197
203 if (Settings::values.use_fast_gpu_time.GetValue()) { 198 if (Settings::values.use_fast_gpu_time.GetValue()) {
204 nanoseconds /= 256; 199 gpu_tick /= 256;
205 } 200 }
206 201
207 return nanoseconds * NsToGPUTickRatio::num / NsToGPUTickRatio::den; 202 return gpu_tick;
208 } 203 }
209 204
210 [[nodiscard]] bool IsAsync() const { 205 [[nodiscard]] bool IsAsync() const {