summaryrefslogtreecommitdiff
path: root/src/common/wall_clock.cpp
diff options
context:
space:
mode:
authorGravatar Morph2023-04-22 23:08:28 -0400
committerGravatar Morph2023-06-07 21:44:42 -0400
commit1492a65454d6a03f641b136cc61e68870be00218 (patch)
tree5442ef0505fb075ee329a1a3cbb1be831987295e /src/common/wall_clock.cpp
parentx64: Deduplicate RDTSC usage (diff)
downloadyuzu-1492a65454d6a03f641b136cc61e68870be00218.tar.gz
yuzu-1492a65454d6a03f641b136cc61e68870be00218.tar.xz
yuzu-1492a65454d6a03f641b136cc61e68870be00218.zip
(wall, native)_clock: Rework NativeClock
Diffstat (limited to 'src/common/wall_clock.cpp')
-rw-r--r--src/common/wall_clock.cpp73
1 files changed, 28 insertions, 45 deletions
diff --git a/src/common/wall_clock.cpp b/src/common/wall_clock.cpp
index 817e71d52..ad8db06b0 100644
--- a/src/common/wall_clock.cpp
+++ b/src/common/wall_clock.cpp
@@ -2,88 +2,71 @@
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include "common/steady_clock.h" 4#include "common/steady_clock.h"
5#include "common/uint128.h"
6#include "common/wall_clock.h" 5#include "common/wall_clock.h"
7 6
8#ifdef ARCHITECTURE_x86_64 7#ifdef ARCHITECTURE_x86_64
9#include "common/x64/cpu_detect.h" 8#include "common/x64/cpu_detect.h"
10#include "common/x64/native_clock.h" 9#include "common/x64/native_clock.h"
10#include "common/x64/rdtsc.h"
11#endif 11#endif
12 12
13namespace Common { 13namespace Common {
14 14
15class StandardWallClock final : public WallClock { 15class StandardWallClock final : public WallClock {
16public: 16public:
17 explicit StandardWallClock(u64 emulated_cpu_frequency_, u64 emulated_clock_frequency_) 17 explicit StandardWallClock() : start_time{SteadyClock::Now()} {}
18 : WallClock{emulated_cpu_frequency_, emulated_clock_frequency_, false},
19 start_time{SteadyClock::Now()} {}
20 18
21 std::chrono::nanoseconds GetTimeNS() override { 19 std::chrono::nanoseconds GetTimeNS() const override {
22 return SteadyClock::Now() - start_time; 20 return SteadyClock::Now() - start_time;
23 } 21 }
24 22
25 std::chrono::microseconds GetTimeUS() override { 23 std::chrono::microseconds GetTimeUS() const override {
26 return std::chrono::duration_cast<std::chrono::microseconds>(GetTimeNS()); 24 return static_cast<std::chrono::microseconds>(GetHostTicksElapsed() / NsToUsRatio::den);
27 } 25 }
28 26
29 std::chrono::milliseconds GetTimeMS() override { 27 std::chrono::milliseconds GetTimeMS() const override {
30 return std::chrono::duration_cast<std::chrono::milliseconds>(GetTimeNS()); 28 return static_cast<std::chrono::milliseconds>(GetHostTicksElapsed() / NsToMsRatio::den);
31 } 29 }
32 30
33 u64 GetClockCycles() override { 31 u64 GetCNTPCT() const override {
34 const u128 temp = Common::Multiply64Into128(GetTimeNS().count(), emulated_clock_frequency); 32 return GetHostTicksElapsed() * NsToCNTPCTRatio::num / NsToCNTPCTRatio::den;
35 return Common::Divide128On32(temp, NS_RATIO).first;
36 } 33 }
37 34
38 u64 GetCPUCycles() override { 35 u64 GetHostTicksNow() const override {
39 const u128 temp = Common::Multiply64Into128(GetTimeNS().count(), emulated_cpu_frequency); 36 return static_cast<u64>(SteadyClock::Now().time_since_epoch().count());
40 return Common::Divide128On32(temp, NS_RATIO).first;
41 } 37 }
42 38
43 void Pause([[maybe_unused]] bool is_paused) override { 39 u64 GetHostTicksElapsed() const override {
44 // Do nothing in this clock type. 40 return static_cast<u64>(GetTimeNS().count());
41 }
42
43 bool IsNative() const override {
44 return false;
45 } 45 }
46 46
47private: 47private:
48 SteadyClock::time_point start_time; 48 SteadyClock::time_point start_time;
49}; 49};
50 50
51std::unique_ptr<WallClock> CreateOptimalClock() {
51#ifdef ARCHITECTURE_x86_64 52#ifdef ARCHITECTURE_x86_64
52
53std::unique_ptr<WallClock> CreateBestMatchingClock(u64 emulated_cpu_frequency,
54 u64 emulated_clock_frequency) {
55 const auto& caps = GetCPUCaps(); 53 const auto& caps = GetCPUCaps();
56 u64 rtsc_frequency = 0;
57 if (caps.invariant_tsc) {
58 rtsc_frequency = caps.tsc_frequency ? caps.tsc_frequency : EstimateRDTSCFrequency();
59 }
60 54
61 // Fallback to StandardWallClock if the hardware TSC does not have the precision greater than: 55 if (caps.invariant_tsc && caps.tsc_frequency >= WallClock::CNTFRQ) {
62 // - A nanosecond 56 return std::make_unique<X64::NativeClock>(caps.tsc_frequency);
63 // - The emulated CPU frequency
64 // - The emulated clock counter frequency (CNTFRQ)
65 if (rtsc_frequency <= WallClock::NS_RATIO || rtsc_frequency <= emulated_cpu_frequency ||
66 rtsc_frequency <= emulated_clock_frequency) {
67 return std::make_unique<StandardWallClock>(emulated_cpu_frequency,
68 emulated_clock_frequency);
69 } else { 57 } else {
70 return std::make_unique<X64::NativeClock>(emulated_cpu_frequency, emulated_clock_frequency, 58 // Fallback to StandardWallClock if the hardware TSC
71 rtsc_frequency); 59 // - Is not invariant
60 // - Is not more precise than CNTFRQ
61 return std::make_unique<StandardWallClock>();
72 } 62 }
73}
74
75#else 63#else
76 64 return std::make_unique<StandardWallClock>();
77std::unique_ptr<WallClock> CreateBestMatchingClock(u64 emulated_cpu_frequency,
78 u64 emulated_clock_frequency) {
79 return std::make_unique<StandardWallClock>(emulated_cpu_frequency, emulated_clock_frequency);
80}
81
82#endif 65#endif
66}
83 67
84std::unique_ptr<WallClock> CreateStandardWallClock(u64 emulated_cpu_frequency, 68std::unique_ptr<WallClock> CreateStandardWallClock() {
85 u64 emulated_clock_frequency) { 69 return std::make_unique<StandardWallClock>();
86 return std::make_unique<StandardWallClock>(emulated_cpu_frequency, emulated_clock_frequency);
87} 70}
88 71
89} // namespace Common 72} // namespace Common