summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/CMakeLists.txt11
-rw-r--r--src/common/announce_multiplayer_room.h2
-rw-r--r--src/common/bit_cast.h20
-rw-r--r--src/common/fiber.cpp2
-rw-r--r--src/common/fixed_point.h2
-rw-r--r--src/common/host_memory.cpp4
-rw-r--r--src/common/input.h10
-rw-r--r--src/common/logging/filter.cpp2
-rw-r--r--src/common/logging/types.h202
-rw-r--r--src/common/overflow.h22
-rw-r--r--src/common/settings.h10
-rw-r--r--src/common/steady_clock.cpp81
-rw-r--r--src/common/steady_clock.h34
-rw-r--r--src/common/swap.h12
-rw-r--r--src/common/wall_clock.cpp39
-rw-r--r--src/common/wall_clock.h3
-rw-r--r--src/common/windows/timer_resolution.cpp109
-rw-r--r--src/common/windows/timer_resolution.h38
-rw-r--r--src/common/x64/native_clock.cpp51
-rw-r--r--src/common/x64/native_clock.h5
20 files changed, 494 insertions, 165 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 56b247ac4..61ab68864 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -91,6 +91,7 @@ add_library(common STATIC
91 multi_level_page_table.h 91 multi_level_page_table.h
92 nvidia_flags.cpp 92 nvidia_flags.cpp
93 nvidia_flags.h 93 nvidia_flags.h
94 overflow.h
94 page_table.cpp 95 page_table.cpp
95 page_table.h 96 page_table.h
96 param_package.cpp 97 param_package.cpp
@@ -113,6 +114,8 @@ add_library(common STATIC
113 socket_types.h 114 socket_types.h
114 spin_lock.cpp 115 spin_lock.cpp
115 spin_lock.h 116 spin_lock.h
117 steady_clock.cpp
118 steady_clock.h
116 stream.cpp 119 stream.cpp
117 stream.h 120 stream.h
118 string_util.cpp 121 string_util.cpp
@@ -142,6 +145,14 @@ add_library(common STATIC
142 zstd_compression.h 145 zstd_compression.h
143) 146)
144 147
148if (WIN32)
149 target_sources(common PRIVATE
150 windows/timer_resolution.cpp
151 windows/timer_resolution.h
152 )
153 target_link_libraries(common PRIVATE ntdll)
154endif()
155
145if(ARCHITECTURE_x86_64) 156if(ARCHITECTURE_x86_64)
146 target_sources(common 157 target_sources(common
147 PRIVATE 158 PRIVATE
diff --git a/src/common/announce_multiplayer_room.h b/src/common/announce_multiplayer_room.h
index 4a3100fa4..f32060196 100644
--- a/src/common/announce_multiplayer_room.h
+++ b/src/common/announce_multiplayer_room.h
@@ -66,7 +66,7 @@ public:
66 * @param description The room description 66 * @param description The room description
67 * @param port The port of the room 67 * @param port The port of the room
68 * @param net_version The version of the libNetwork that gets used 68 * @param net_version The version of the libNetwork that gets used
69 * @param has_password True if the room is passowrd protected 69 * @param has_password True if the room is password protected
70 * @param preferred_game The preferred game of the room 70 * @param preferred_game The preferred game of the room
71 * @param preferred_game_id The title id of the preferred game 71 * @param preferred_game_id The title id of the preferred game
72 */ 72 */
diff --git a/src/common/bit_cast.h b/src/common/bit_cast.h
index 535148b4d..c6110c542 100644
--- a/src/common/bit_cast.h
+++ b/src/common/bit_cast.h
@@ -3,19 +3,21 @@
3 3
4#pragma once 4#pragma once
5 5
6#include <cstring> 6#include <version>
7#include <type_traits> 7
8#ifdef __cpp_lib_bit_cast
9#include <bit>
10#endif
8 11
9namespace Common { 12namespace Common {
10 13
11template <typename To, typename From> 14template <typename To, typename From>
12[[nodiscard]] std::enable_if_t<sizeof(To) == sizeof(From) && std::is_trivially_copyable_v<From> && 15constexpr inline To BitCast(const From& from) {
13 std::is_trivially_copyable_v<To>, 16#ifdef __cpp_lib_bit_cast
14 To> 17 return std::bit_cast<To>(from);
15BitCast(const From& src) noexcept { 18#else
16 To dst; 19 return __builtin_bit_cast(To, from);
17 std::memcpy(&dst, &src, sizeof(To)); 20#endif
18 return dst;
19} 21}
20 22
21} // namespace Common 23} // namespace Common
diff --git a/src/common/fiber.cpp b/src/common/fiber.cpp
index bc92b360b..c991b7cf1 100644
--- a/src/common/fiber.cpp
+++ b/src/common/fiber.cpp
@@ -90,7 +90,7 @@ Fiber::~Fiber() {
90} 90}
91 91
92void Fiber::Exit() { 92void Fiber::Exit() {
93 ASSERT_MSG(impl->is_thread_fiber, "Exitting non main thread fiber"); 93 ASSERT_MSG(impl->is_thread_fiber, "Exiting non main thread fiber");
94 if (!impl->is_thread_fiber) { 94 if (!impl->is_thread_fiber) {
95 return; 95 return;
96 } 96 }
diff --git a/src/common/fixed_point.h b/src/common/fixed_point.h
index f899b0d54..b0f3ae2cc 100644
--- a/src/common/fixed_point.h
+++ b/src/common/fixed_point.h
@@ -22,7 +22,7 @@ class FixedPoint;
22namespace detail { 22namespace detail {
23 23
24// helper templates to make magic with types :) 24// helper templates to make magic with types :)
25// these allow us to determine resonable types from 25// these allow us to determine reasonable types from
26// a desired size, they also let us infer the next largest type 26// a desired size, they also let us infer the next largest type
27// from a type which is nice for the division op 27// from a type which is nice for the division op
28template <size_t T> 28template <size_t T>
diff --git a/src/common/host_memory.cpp b/src/common/host_memory.cpp
index 611c7d1a3..8e4f1f97a 100644
--- a/src/common/host_memory.cpp
+++ b/src/common/host_memory.cpp
@@ -322,7 +322,7 @@ private:
322 } 322 }
323 323
324 /// Return true when a given memory region is a "nieche" and the placeholders don't have to be 324 /// Return true when a given memory region is a "nieche" and the placeholders don't have to be
325 /// splitted. 325 /// split.
326 bool IsNiechePlaceholder(size_t virtual_offset, size_t length) const { 326 bool IsNiechePlaceholder(size_t virtual_offset, size_t length) const {
327 const auto it = placeholders.upper_bound({virtual_offset, virtual_offset + length}); 327 const auto it = placeholders.upper_bound({virtual_offset, virtual_offset + length});
328 if (it != placeholders.end() && it->lower() == virtual_offset + length) { 328 if (it != placeholders.end() && it->lower() == virtual_offset + length) {
@@ -484,7 +484,7 @@ class HostMemory::Impl {
484public: 484public:
485 explicit Impl(size_t /*backing_size */, size_t /* virtual_size */) { 485 explicit Impl(size_t /*backing_size */, size_t /* virtual_size */) {
486 // This is just a place holder. 486 // This is just a place holder.
487 // Please implement fastmem in a propper way on your platform. 487 // Please implement fastmem in a proper way on your platform.
488 throw std::bad_alloc{}; 488 throw std::bad_alloc{};
489 } 489 }
490 490
diff --git a/src/common/input.h b/src/common/input.h
index b5748a6c8..51b277c1f 100644
--- a/src/common/input.h
+++ b/src/common/input.h
@@ -15,7 +15,7 @@
15 15
16namespace Common::Input { 16namespace Common::Input {
17 17
18// Type of data that is expected to recieve or send 18// Type of data that is expected to receive or send
19enum class InputType { 19enum class InputType {
20 None, 20 None,
21 Battery, 21 Battery,
@@ -46,7 +46,7 @@ enum class PollingMode {
46 // Constant polling of buttons, analogs and motion data 46 // Constant polling of buttons, analogs and motion data
47 Active, 47 Active,
48 // Only update on button change, digital analogs 48 // Only update on button change, digital analogs
49 Pasive, 49 Passive,
50 // Enable near field communication polling 50 // Enable near field communication polling
51 NFC, 51 NFC,
52 // Enable infrared camera polling 52 // Enable infrared camera polling
@@ -103,7 +103,7 @@ enum class VibrationAmplificationType {
103struct AnalogProperties { 103struct AnalogProperties {
104 // Anything below this value will be detected as zero 104 // Anything below this value will be detected as zero
105 float deadzone{}; 105 float deadzone{};
106 // Anyting above this values will be detected as one 106 // Anything above this values will be detected as one
107 float range{1.0f}; 107 float range{1.0f};
108 // Minimum value to be detected as active 108 // Minimum value to be detected as active
109 float threshold{0.5f}; 109 float threshold{0.5f};
@@ -209,7 +209,7 @@ struct LedStatus {
209 bool led_4{}; 209 bool led_4{};
210}; 210};
211 211
212// Raw data fom camera 212// Raw data from camera
213struct CameraStatus { 213struct CameraStatus {
214 CameraFormat format{CameraFormat::None}; 214 CameraFormat format{CameraFormat::None};
215 std::vector<u8> data{}; 215 std::vector<u8> data{};
@@ -428,7 +428,7 @@ inline void UnregisterOutputFactory(const std::string& name) {
428} 428}
429 429
430/** 430/**
431 * Create an input device from given paramters. 431 * Create an input device from given parameters.
432 * @tparam InputDeviceType the type of input devices to create 432 * @tparam InputDeviceType the type of input devices to create
433 * @param params a serialized ParamPackage string that contains all parameters for creating the 433 * @param params a serialized ParamPackage string that contains all parameters for creating the
434 * device 434 * device
diff --git a/src/common/logging/filter.cpp b/src/common/logging/filter.cpp
index a959acb74..c95909561 100644
--- a/src/common/logging/filter.cpp
+++ b/src/common/logging/filter.cpp
@@ -119,7 +119,7 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
119 SUB(Service, NPNS) \ 119 SUB(Service, NPNS) \
120 SUB(Service, NS) \ 120 SUB(Service, NS) \
121 SUB(Service, NVDRV) \ 121 SUB(Service, NVDRV) \
122 SUB(Service, NVFlinger) \ 122 SUB(Service, Nvnflinger) \
123 SUB(Service, OLSC) \ 123 SUB(Service, OLSC) \
124 SUB(Service, PCIE) \ 124 SUB(Service, PCIE) \
125 SUB(Service, PCTL) \ 125 SUB(Service, PCTL) \
diff --git a/src/common/logging/types.h b/src/common/logging/types.h
index 595c15ada..8356e3183 100644
--- a/src/common/logging/types.h
+++ b/src/common/logging/types.h
@@ -29,107 +29,107 @@ enum class Level : u8 {
29 * filter.cpp. 29 * filter.cpp.
30 */ 30 */
31enum class Class : u8 { 31enum class Class : u8 {
32 Log, ///< Messages about the log system itself 32 Log, ///< Messages about the log system itself
33 Common, ///< Library routines 33 Common, ///< Library routines
34 Common_Filesystem, ///< Filesystem interface library 34 Common_Filesystem, ///< Filesystem interface library
35 Common_Memory, ///< Memory mapping and management functions 35 Common_Memory, ///< Memory mapping and management functions
36 Core, ///< LLE emulation core 36 Core, ///< LLE emulation core
37 Core_ARM, ///< ARM CPU core 37 Core_ARM, ///< ARM CPU core
38 Core_Timing, ///< CoreTiming functions 38 Core_Timing, ///< CoreTiming functions
39 Config, ///< Emulator configuration (including commandline) 39 Config, ///< Emulator configuration (including commandline)
40 Debug, ///< Debugging tools 40 Debug, ///< Debugging tools
41 Debug_Emulated, ///< Debug messages from the emulated programs 41 Debug_Emulated, ///< Debug messages from the emulated programs
42 Debug_GPU, ///< GPU debugging tools 42 Debug_GPU, ///< GPU debugging tools
43 Debug_Breakpoint, ///< Logging breakpoints and watchpoints 43 Debug_Breakpoint, ///< Logging breakpoints and watchpoints
44 Debug_GDBStub, ///< GDB Stub 44 Debug_GDBStub, ///< GDB Stub
45 Kernel, ///< The HLE implementation of the CTR kernel 45 Kernel, ///< The HLE implementation of the CTR kernel
46 Kernel_SVC, ///< Kernel system calls 46 Kernel_SVC, ///< Kernel system calls
47 Service, ///< HLE implementation of system services. Each major service 47 Service, ///< HLE implementation of system services. Each major service
48 ///< should have its own subclass. 48 ///< should have its own subclass.
49 Service_ACC, ///< The ACC (Accounts) service 49 Service_ACC, ///< The ACC (Accounts) service
50 Service_AM, ///< The AM (Applet manager) service 50 Service_AM, ///< The AM (Applet manager) service
51 Service_AOC, ///< The AOC (AddOn Content) service 51 Service_AOC, ///< The AOC (AddOn Content) service
52 Service_APM, ///< The APM (Performance) service 52 Service_APM, ///< The APM (Performance) service
53 Service_ARP, ///< The ARP service 53 Service_ARP, ///< The ARP service
54 Service_Audio, ///< The Audio (Audio control) service 54 Service_Audio, ///< The Audio (Audio control) service
55 Service_BCAT, ///< The BCAT service 55 Service_BCAT, ///< The BCAT service
56 Service_BGTC, ///< The BGTC (Background Task Controller) service 56 Service_BGTC, ///< The BGTC (Background Task Controller) service
57 Service_BPC, ///< The BPC service 57 Service_BPC, ///< The BPC service
58 Service_BTDRV, ///< The Bluetooth driver service 58 Service_BTDRV, ///< The Bluetooth driver service
59 Service_BTM, ///< The BTM service 59 Service_BTM, ///< The BTM service
60 Service_Capture, ///< The capture service 60 Service_Capture, ///< The capture service
61 Service_ERPT, ///< The error reporting service 61 Service_ERPT, ///< The error reporting service
62 Service_ETicket, ///< The ETicket service 62 Service_ETicket, ///< The ETicket service
63 Service_EUPLD, ///< The error upload service 63 Service_EUPLD, ///< The error upload service
64 Service_Fatal, ///< The Fatal service 64 Service_Fatal, ///< The Fatal service
65 Service_FGM, ///< The FGM service 65 Service_FGM, ///< The FGM service
66 Service_Friend, ///< The friend service 66 Service_Friend, ///< The friend service
67 Service_FS, ///< The FS (Filesystem) service 67 Service_FS, ///< The FS (Filesystem) service
68 Service_GRC, ///< The game recording service 68 Service_GRC, ///< The game recording service
69 Service_HID, ///< The HID (Human interface device) service 69 Service_HID, ///< The HID (Human interface device) service
70 Service_IRS, ///< The IRS service 70 Service_IRS, ///< The IRS service
71 Service_JIT, ///< The JIT service 71 Service_JIT, ///< The JIT service
72 Service_LBL, ///< The LBL (LCD backlight) service 72 Service_LBL, ///< The LBL (LCD backlight) service
73 Service_LDN, ///< The LDN (Local domain network) service 73 Service_LDN, ///< The LDN (Local domain network) service
74 Service_LDR, ///< The loader service 74 Service_LDR, ///< The loader service
75 Service_LM, ///< The LM (Logger) service 75 Service_LM, ///< The LM (Logger) service
76 Service_Migration, ///< The migration service 76 Service_Migration, ///< The migration service
77 Service_Mii, ///< The Mii service 77 Service_Mii, ///< The Mii service
78 Service_MM, ///< The MM (Multimedia) service 78 Service_MM, ///< The MM (Multimedia) service
79 Service_MNPP, ///< The MNPP service 79 Service_MNPP, ///< The MNPP service
80 Service_NCM, ///< The NCM service 80 Service_NCM, ///< The NCM service
81 Service_NFC, ///< The NFC (Near-field communication) service 81 Service_NFC, ///< The NFC (Near-field communication) service
82 Service_NFP, ///< The NFP service 82 Service_NFP, ///< The NFP service
83 Service_NGCT, ///< The NGCT (No Good Content for Terra) service 83 Service_NGCT, ///< The NGCT (No Good Content for Terra) service
84 Service_NIFM, ///< The NIFM (Network interface) service 84 Service_NIFM, ///< The NIFM (Network interface) service
85 Service_NIM, ///< The NIM service 85 Service_NIM, ///< The NIM service
86 Service_NOTIF, ///< The NOTIF (Notification) service 86 Service_NOTIF, ///< The NOTIF (Notification) service
87 Service_NPNS, ///< The NPNS service 87 Service_NPNS, ///< The NPNS service
88 Service_NS, ///< The NS services 88 Service_NS, ///< The NS services
89 Service_NVDRV, ///< The NVDRV (Nvidia driver) service 89 Service_NVDRV, ///< The NVDRV (Nvidia driver) service
90 Service_NVFlinger, ///< The NVFlinger service 90 Service_Nvnflinger, ///< The Nvnflinger service
91 Service_OLSC, ///< The OLSC service 91 Service_OLSC, ///< The OLSC service
92 Service_PCIE, ///< The PCIe service 92 Service_PCIE, ///< The PCIe service
93 Service_PCTL, ///< The PCTL (Parental control) service 93 Service_PCTL, ///< The PCTL (Parental control) service
94 Service_PCV, ///< The PCV service 94 Service_PCV, ///< The PCV service
95 Service_PM, ///< The PM service 95 Service_PM, ///< The PM service
96 Service_PREPO, ///< The PREPO (Play report) service 96 Service_PREPO, ///< The PREPO (Play report) service
97 Service_PSC, ///< The PSC service 97 Service_PSC, ///< The PSC service
98 Service_PTM, ///< The PTM service 98 Service_PTM, ///< The PTM service
99 Service_SET, ///< The SET (Settings) service 99 Service_SET, ///< The SET (Settings) service
100 Service_SM, ///< The SM (Service manager) service 100 Service_SM, ///< The SM (Service manager) service
101 Service_SPL, ///< The SPL service 101 Service_SPL, ///< The SPL service
102 Service_SSL, ///< The SSL service 102 Service_SSL, ///< The SSL service
103 Service_TCAP, ///< The TCAP service. 103 Service_TCAP, ///< The TCAP service.
104 Service_Time, ///< The time service 104 Service_Time, ///< The time service
105 Service_USB, ///< The USB (Universal Serial Bus) service 105 Service_USB, ///< The USB (Universal Serial Bus) service
106 Service_VI, ///< The VI (Video interface) service 106 Service_VI, ///< The VI (Video interface) service
107 Service_WLAN, ///< The WLAN (Wireless local area network) service 107 Service_WLAN, ///< The WLAN (Wireless local area network) service
108 HW, ///< Low-level hardware emulation 108 HW, ///< Low-level hardware emulation
109 HW_Memory, ///< Memory-map and address translation 109 HW_Memory, ///< Memory-map and address translation
110 HW_LCD, ///< LCD register emulation 110 HW_LCD, ///< LCD register emulation
111 HW_GPU, ///< GPU control emulation 111 HW_GPU, ///< GPU control emulation
112 HW_AES, ///< AES engine emulation 112 HW_AES, ///< AES engine emulation
113 IPC, ///< IPC interface 113 IPC, ///< IPC interface
114 Frontend, ///< Emulator UI 114 Frontend, ///< Emulator UI
115 Render, ///< Emulator video output and hardware acceleration 115 Render, ///< Emulator video output and hardware acceleration
116 Render_Software, ///< Software renderer backend 116 Render_Software, ///< Software renderer backend
117 Render_OpenGL, ///< OpenGL backend 117 Render_OpenGL, ///< OpenGL backend
118 Render_Vulkan, ///< Vulkan backend 118 Render_Vulkan, ///< Vulkan backend
119 Shader, ///< Shader recompiler 119 Shader, ///< Shader recompiler
120 Shader_SPIRV, ///< Shader SPIR-V code generation 120 Shader_SPIRV, ///< Shader SPIR-V code generation
121 Shader_GLASM, ///< Shader GLASM code generation 121 Shader_GLASM, ///< Shader GLASM code generation
122 Shader_GLSL, ///< Shader GLSL code generation 122 Shader_GLSL, ///< Shader GLSL code generation
123 Audio, ///< Audio emulation 123 Audio, ///< Audio emulation
124 Audio_DSP, ///< The HLE implementation of the DSP 124 Audio_DSP, ///< The HLE implementation of the DSP
125 Audio_Sink, ///< Emulator audio output backend 125 Audio_Sink, ///< Emulator audio output backend
126 Loader, ///< ROM loader 126 Loader, ///< ROM loader
127 CheatEngine, ///< Memory manipulation and engine VM functions 127 CheatEngine, ///< Memory manipulation and engine VM functions
128 Crypto, ///< Cryptographic engine/functions 128 Crypto, ///< Cryptographic engine/functions
129 Input, ///< Input emulation 129 Input, ///< Input emulation
130 Network, ///< Network emulation 130 Network, ///< Network emulation
131 WebService, ///< Interface to yuzu Web Services 131 WebService, ///< Interface to yuzu Web Services
132 Count ///< Total number of logging classes 132 Count ///< Total number of logging classes
133}; 133};
134 134
135} // namespace Common::Log 135} // namespace Common::Log
diff --git a/src/common/overflow.h b/src/common/overflow.h
new file mode 100644
index 000000000..44d8e7e73
--- /dev/null
+++ b/src/common/overflow.h
@@ -0,0 +1,22 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <type_traits>
7#include "bit_cast.h"
8
9namespace Common {
10
11template <typename T>
12 requires(std::is_integral_v<T> && std::is_signed_v<T>)
13inline T WrappingAdd(T lhs, T rhs) {
14 using U = std::make_unsigned_t<T>;
15
16 U lhs_u = BitCast<U>(lhs);
17 U rhs_u = BitCast<U>(rhs);
18
19 return BitCast<T>(lhs_u + rhs_u);
20}
21
22} // namespace Common
diff --git a/src/common/settings.h b/src/common/settings.h
index 512ecff69..b77a1580a 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -128,7 +128,7 @@ public:
128 /** 128 /**
129 * Sets a default value, label, and setting value. 129 * Sets a default value, label, and setting value.
130 * 130 *
131 * @param default_val Intial value of the setting, and default value of the setting 131 * @param default_val Initial value of the setting, and default value of the setting
132 * @param name Label for the setting 132 * @param name Label for the setting
133 */ 133 */
134 explicit Setting(const Type& default_val, const std::string& name) 134 explicit Setting(const Type& default_val, const std::string& name)
@@ -139,7 +139,7 @@ public:
139 /** 139 /**
140 * Sets a default value, minimum value, maximum value, and label. 140 * Sets a default value, minimum value, maximum value, and label.
141 * 141 *
142 * @param default_val Intial value of the setting, and default value of the setting 142 * @param default_val Initial value of the setting, and default value of the setting
143 * @param min_val Sets the minimum allowed value of the setting 143 * @param min_val Sets the minimum allowed value of the setting
144 * @param max_val Sets the maximum allowed value of the setting 144 * @param max_val Sets the maximum allowed value of the setting
145 * @param name Label for the setting 145 * @param name Label for the setting
@@ -231,7 +231,7 @@ public:
231 /** 231 /**
232 * Sets a default value, label, and setting value. 232 * Sets a default value, label, and setting value.
233 * 233 *
234 * @param default_val Intial value of the setting, and default value of the setting 234 * @param default_val Initial value of the setting, and default value of the setting
235 * @param name Label for the setting 235 * @param name Label for the setting
236 */ 236 */
237 explicit SwitchableSetting(const Type& default_val, const std::string& name) 237 explicit SwitchableSetting(const Type& default_val, const std::string& name)
@@ -242,7 +242,7 @@ public:
242 /** 242 /**
243 * Sets a default value, minimum value, maximum value, and label. 243 * Sets a default value, minimum value, maximum value, and label.
244 * 244 *
245 * @param default_val Intial value of the setting, and default value of the setting 245 * @param default_val Initial value of the setting, and default value of the setting
246 * @param min_val Sets the minimum allowed value of the setting 246 * @param min_val Sets the minimum allowed value of the setting
247 * @param max_val Sets the maximum allowed value of the setting 247 * @param max_val Sets the maximum allowed value of the setting
248 * @param name Label for the setting 248 * @param name Label for the setting
@@ -503,7 +503,7 @@ struct Values {
503 Setting<bool> tas_loop{false, "tas_loop"}; 503 Setting<bool> tas_loop{false, "tas_loop"};
504 504
505 Setting<bool> mouse_panning{false, "mouse_panning"}; 505 Setting<bool> mouse_panning{false, "mouse_panning"};
506 Setting<u8, true> mouse_panning_sensitivity{10, 1, 100, "mouse_panning_sensitivity"}; 506 Setting<u8, true> mouse_panning_sensitivity{50, 1, 100, "mouse_panning_sensitivity"};
507 Setting<bool> mouse_enabled{false, "mouse_enabled"}; 507 Setting<bool> mouse_enabled{false, "mouse_enabled"};
508 508
509 Setting<bool> emulate_analog_keyboard{false, "emulate_analog_keyboard"}; 509 Setting<bool> emulate_analog_keyboard{false, "emulate_analog_keyboard"};
diff --git a/src/common/steady_clock.cpp b/src/common/steady_clock.cpp
new file mode 100644
index 000000000..782859196
--- /dev/null
+++ b/src/common/steady_clock.cpp
@@ -0,0 +1,81 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#if defined(_WIN32)
5#include <windows.h>
6#else
7#include <time.h>
8#endif
9
10#include "common/steady_clock.h"
11
12namespace Common {
13
14#ifdef _WIN32
15static s64 WindowsQueryPerformanceFrequency() {
16 LARGE_INTEGER frequency;
17 QueryPerformanceFrequency(&frequency);
18 return frequency.QuadPart;
19}
20
21static s64 WindowsQueryPerformanceCounter() {
22 LARGE_INTEGER counter;
23 QueryPerformanceCounter(&counter);
24 return counter.QuadPart;
25}
26
27static s64 GetSystemTimeNS() {
28 // GetSystemTimePreciseAsFileTime returns the file time in 100ns units.
29 static constexpr s64 Multiplier = 100;
30 // Convert Windows epoch to Unix epoch.
31 static constexpr s64 WindowsEpochToUnixEpochNS = 0x19DB1DED53E8000LL;
32
33 FILETIME filetime;
34 GetSystemTimePreciseAsFileTime(&filetime);
35 return Multiplier * ((static_cast<s64>(filetime.dwHighDateTime) << 32) +
36 static_cast<s64>(filetime.dwLowDateTime)) -
37 WindowsEpochToUnixEpochNS;
38}
39#endif
40
41SteadyClock::time_point SteadyClock::Now() noexcept {
42#if defined(_WIN32)
43 static const auto freq = WindowsQueryPerformanceFrequency();
44 const auto counter = WindowsQueryPerformanceCounter();
45
46 // 10 MHz is a very common QPC frequency on modern PCs.
47 // Optimizing for this specific frequency can double the performance of
48 // this function by avoiding the expensive frequency conversion path.
49 static constexpr s64 TenMHz = 10'000'000;
50
51 if (freq == TenMHz) [[likely]] {
52 static_assert(period::den % TenMHz == 0);
53 static constexpr s64 Multiplier = period::den / TenMHz;
54 return time_point{duration{counter * Multiplier}};
55 }
56
57 const auto whole = (counter / freq) * period::den;
58 const auto part = (counter % freq) * period::den / freq;
59 return time_point{duration{whole + part}};
60#elif defined(__APPLE__)
61 return time_point{duration{clock_gettime_nsec_np(CLOCK_MONOTONIC_RAW)}};
62#else
63 timespec ts;
64 clock_gettime(CLOCK_MONOTONIC, &ts);
65 return time_point{std::chrono::seconds{ts.tv_sec} + std::chrono::nanoseconds{ts.tv_nsec}};
66#endif
67}
68
69RealTimeClock::time_point RealTimeClock::Now() noexcept {
70#if defined(_WIN32)
71 return time_point{duration{GetSystemTimeNS()}};
72#elif defined(__APPLE__)
73 return time_point{duration{clock_gettime_nsec_np(CLOCK_REALTIME)}};
74#else
75 timespec ts;
76 clock_gettime(CLOCK_REALTIME, &ts);
77 return time_point{std::chrono::seconds{ts.tv_sec} + std::chrono::nanoseconds{ts.tv_nsec}};
78#endif
79}
80
81}; // namespace Common
diff --git a/src/common/steady_clock.h b/src/common/steady_clock.h
new file mode 100644
index 000000000..dbd0e2513
--- /dev/null
+++ b/src/common/steady_clock.h
@@ -0,0 +1,34 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <chrono>
7
8#include "common/common_types.h"
9
10namespace Common {
11
12struct SteadyClock {
13 using rep = s64;
14 using period = std::nano;
15 using duration = std::chrono::nanoseconds;
16 using time_point = std::chrono::time_point<SteadyClock>;
17
18 static constexpr bool is_steady = true;
19
20 [[nodiscard]] static time_point Now() noexcept;
21};
22
23struct RealTimeClock {
24 using rep = s64;
25 using period = std::nano;
26 using duration = std::chrono::nanoseconds;
27 using time_point = std::chrono::time_point<RealTimeClock>;
28
29 static constexpr bool is_steady = false;
30
31 [[nodiscard]] static time_point Now() noexcept;
32};
33
34} // namespace Common
diff --git a/src/common/swap.h b/src/common/swap.h
index 037b82781..085baaf9a 100644
--- a/src/common/swap.h
+++ b/src/common/swap.h
@@ -229,7 +229,7 @@ public:
229 value = swap(swap() - 1); 229 value = swap(swap() - 1);
230 return old; 230 return old;
231 } 231 }
232 // Comparaison 232 // Comparison
233 // v == i 233 // v == i
234 bool operator==(const swapped_t& i) const { 234 bool operator==(const swapped_t& i) const {
235 return swap() == i.swap(); 235 return swap() == i.swap();
@@ -368,7 +368,7 @@ public:
368 // Member 368 // Member
369 /** todo **/ 369 /** todo **/
370 370
371 // Arithmetics 371 // Arithmetic
372 template <typename S, typename T2, typename F2> 372 template <typename S, typename T2, typename F2>
373 friend S operator+(const S& p, const swapped_t v); 373 friend S operator+(const S& p, const swapped_t v);
374 374
@@ -384,7 +384,7 @@ public:
384 template <typename S, typename T2, typename F2> 384 template <typename S, typename T2, typename F2>
385 friend S operator%(const S& p, const swapped_t v); 385 friend S operator%(const S& p, const swapped_t v);
386 386
387 // Arithmetics + assignments 387 // Arithmetic + assignments
388 template <typename S, typename T2, typename F2> 388 template <typename S, typename T2, typename F2>
389 friend S operator+=(const S& p, const swapped_t v); 389 friend S operator+=(const S& p, const swapped_t v);
390 390
@@ -415,7 +415,7 @@ public:
415 friend bool operator==(const S& p, const swapped_t v); 415 friend bool operator==(const S& p, const swapped_t v);
416}; 416};
417 417
418// Arithmetics 418// Arithmetic
419template <typename S, typename T, typename F> 419template <typename S, typename T, typename F>
420S operator+(const S& i, const swap_struct_t<T, F> v) { 420S operator+(const S& i, const swap_struct_t<T, F> v) {
421 return i + v.swap(); 421 return i + v.swap();
@@ -441,7 +441,7 @@ S operator%(const S& i, const swap_struct_t<T, F> v) {
441 return i % v.swap(); 441 return i % v.swap();
442} 442}
443 443
444// Arithmetics + assignments 444// Arithmetic + assignments
445template <typename S, typename T, typename F> 445template <typename S, typename T, typename F>
446S& operator+=(S& i, const swap_struct_t<T, F> v) { 446S& operator+=(S& i, const swap_struct_t<T, F> v) {
447 i += v.swap(); 447 i += v.swap();
@@ -465,7 +465,7 @@ S operator&(const swap_struct_t<T, F> v, const S& i) {
465 return static_cast<S>(v.swap() & i); 465 return static_cast<S>(v.swap() & i);
466} 466}
467 467
468// Comparaison 468// Comparison
469template <typename S, typename T, typename F> 469template <typename S, typename T, typename F>
470bool operator<(const S& p, const swap_struct_t<T, F> v) { 470bool operator<(const S& p, const swap_struct_t<T, F> v) {
471 return p < v.swap(); 471 return p < v.swap();
diff --git a/src/common/wall_clock.cpp b/src/common/wall_clock.cpp
index ae07f2811..817e71d52 100644
--- a/src/common/wall_clock.cpp
+++ b/src/common/wall_clock.cpp
@@ -1,6 +1,7 @@
1// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
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/uint128.h" 5#include "common/uint128.h"
5#include "common/wall_clock.h" 6#include "common/wall_clock.h"
6 7
@@ -11,45 +12,32 @@
11 12
12namespace Common { 13namespace Common {
13 14
14using base_timer = std::chrono::steady_clock;
15using base_time_point = std::chrono::time_point<base_timer>;
16
17class StandardWallClock final : public WallClock { 15class StandardWallClock final : public WallClock {
18public: 16public:
19 explicit StandardWallClock(u64 emulated_cpu_frequency_, u64 emulated_clock_frequency_) 17 explicit StandardWallClock(u64 emulated_cpu_frequency_, u64 emulated_clock_frequency_)
20 : WallClock(emulated_cpu_frequency_, emulated_clock_frequency_, false) { 18 : WallClock{emulated_cpu_frequency_, emulated_clock_frequency_, false},
21 start_time = base_timer::now(); 19 start_time{SteadyClock::Now()} {}
22 }
23 20
24 std::chrono::nanoseconds GetTimeNS() override { 21 std::chrono::nanoseconds GetTimeNS() override {
25 base_time_point current = base_timer::now(); 22 return SteadyClock::Now() - start_time;
26 auto elapsed = current - start_time;
27 return std::chrono::duration_cast<std::chrono::nanoseconds>(elapsed);
28 } 23 }
29 24
30 std::chrono::microseconds GetTimeUS() override { 25 std::chrono::microseconds GetTimeUS() override {
31 base_time_point current = base_timer::now(); 26 return std::chrono::duration_cast<std::chrono::microseconds>(GetTimeNS());
32 auto elapsed = current - start_time;
33 return std::chrono::duration_cast<std::chrono::microseconds>(elapsed);
34 } 27 }
35 28
36 std::chrono::milliseconds GetTimeMS() override { 29 std::chrono::milliseconds GetTimeMS() override {
37 base_time_point current = base_timer::now(); 30 return std::chrono::duration_cast<std::chrono::milliseconds>(GetTimeNS());
38 auto elapsed = current - start_time;
39 return std::chrono::duration_cast<std::chrono::milliseconds>(elapsed);
40 } 31 }
41 32
42 u64 GetClockCycles() override { 33 u64 GetClockCycles() override {
43 std::chrono::nanoseconds time_now = GetTimeNS(); 34 const u128 temp = Common::Multiply64Into128(GetTimeNS().count(), emulated_clock_frequency);
44 const u128 temporary = 35 return Common::Divide128On32(temp, NS_RATIO).first;
45 Common::Multiply64Into128(time_now.count(), emulated_clock_frequency);
46 return Common::Divide128On32(temporary, 1000000000).first;
47 } 36 }
48 37
49 u64 GetCPUCycles() override { 38 u64 GetCPUCycles() override {
50 std::chrono::nanoseconds time_now = GetTimeNS(); 39 const u128 temp = Common::Multiply64Into128(GetTimeNS().count(), emulated_cpu_frequency);
51 const u128 temporary = Common::Multiply64Into128(time_now.count(), emulated_cpu_frequency); 40 return Common::Divide128On32(temp, NS_RATIO).first;
52 return Common::Divide128On32(temporary, 1000000000).first;
53 } 41 }
54 42
55 void Pause([[maybe_unused]] bool is_paused) override { 43 void Pause([[maybe_unused]] bool is_paused) override {
@@ -57,7 +45,7 @@ public:
57 } 45 }
58 46
59private: 47private:
60 base_time_point start_time; 48 SteadyClock::time_point start_time;
61}; 49};
62 50
63#ifdef ARCHITECTURE_x86_64 51#ifdef ARCHITECTURE_x86_64
@@ -93,4 +81,9 @@ std::unique_ptr<WallClock> CreateBestMatchingClock(u64 emulated_cpu_frequency,
93 81
94#endif 82#endif
95 83
84std::unique_ptr<WallClock> CreateStandardWallClock(u64 emulated_cpu_frequency,
85 u64 emulated_clock_frequency) {
86 return std::make_unique<StandardWallClock>(emulated_cpu_frequency, emulated_clock_frequency);
87}
88
96} // namespace Common 89} // namespace Common
diff --git a/src/common/wall_clock.h b/src/common/wall_clock.h
index 828a523a8..157ec5eae 100644
--- a/src/common/wall_clock.h
+++ b/src/common/wall_clock.h
@@ -55,4 +55,7 @@ private:
55[[nodiscard]] std::unique_ptr<WallClock> CreateBestMatchingClock(u64 emulated_cpu_frequency, 55[[nodiscard]] std::unique_ptr<WallClock> CreateBestMatchingClock(u64 emulated_cpu_frequency,
56 u64 emulated_clock_frequency); 56 u64 emulated_clock_frequency);
57 57
58[[nodiscard]] std::unique_ptr<WallClock> CreateStandardWallClock(u64 emulated_cpu_frequency,
59 u64 emulated_clock_frequency);
60
58} // namespace Common 61} // namespace Common
diff --git a/src/common/windows/timer_resolution.cpp b/src/common/windows/timer_resolution.cpp
new file mode 100644
index 000000000..29c6e5c7e
--- /dev/null
+++ b/src/common/windows/timer_resolution.cpp
@@ -0,0 +1,109 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include <windows.h>
5
6#include "common/windows/timer_resolution.h"
7
8extern "C" {
9// http://undocumented.ntinternals.net/index.html?page=UserMode%2FUndocumented%20Functions%2FTime%2FNtQueryTimerResolution.html
10NTSYSAPI LONG NTAPI NtQueryTimerResolution(PULONG MinimumResolution, PULONG MaximumResolution,
11 PULONG CurrentResolution);
12
13// http://undocumented.ntinternals.net/index.html?page=UserMode%2FUndocumented%20Functions%2FTime%2FNtSetTimerResolution.html
14NTSYSAPI LONG NTAPI NtSetTimerResolution(ULONG DesiredResolution, BOOLEAN SetResolution,
15 PULONG CurrentResolution);
16
17// http://undocumented.ntinternals.net/index.html?page=UserMode%2FUndocumented%20Functions%2FNT%20Objects%2FThread%2FNtDelayExecution.html
18NTSYSAPI LONG NTAPI NtDelayExecution(BOOLEAN Alertable, PLARGE_INTEGER DelayInterval);
19}
20
21// Defines for compatibility with older Windows 10 SDKs.
22
23#ifndef PROCESS_POWER_THROTTLING_EXECUTION_SPEED
24#define PROCESS_POWER_THROTTLING_EXECUTION_SPEED 0x1
25#endif
26#ifndef PROCESS_POWER_THROTTLING_IGNORE_TIMER_RESOLUTION
27#define PROCESS_POWER_THROTTLING_IGNORE_TIMER_RESOLUTION 0x4
28#endif
29
30namespace Common::Windows {
31
32namespace {
33
34using namespace std::chrono;
35
36constexpr nanoseconds ToNS(ULONG hundred_ns) {
37 return nanoseconds{hundred_ns * 100};
38}
39
40constexpr ULONG ToHundredNS(nanoseconds ns) {
41 return static_cast<ULONG>(ns.count()) / 100;
42}
43
44struct TimerResolution {
45 std::chrono::nanoseconds minimum;
46 std::chrono::nanoseconds maximum;
47 std::chrono::nanoseconds current;
48};
49
50TimerResolution GetTimerResolution() {
51 ULONG MinimumTimerResolution;
52 ULONG MaximumTimerResolution;
53 ULONG CurrentTimerResolution;
54 NtQueryTimerResolution(&MinimumTimerResolution, &MaximumTimerResolution,
55 &CurrentTimerResolution);
56 return {
57 .minimum{ToNS(MinimumTimerResolution)},
58 .maximum{ToNS(MaximumTimerResolution)},
59 .current{ToNS(CurrentTimerResolution)},
60 };
61}
62
63void SetHighQoS() {
64 // https://learn.microsoft.com/en-us/windows/win32/procthread/quality-of-service
65 PROCESS_POWER_THROTTLING_STATE PowerThrottling{
66 .Version{PROCESS_POWER_THROTTLING_CURRENT_VERSION},
67 .ControlMask{PROCESS_POWER_THROTTLING_EXECUTION_SPEED |
68 PROCESS_POWER_THROTTLING_IGNORE_TIMER_RESOLUTION},
69 .StateMask{},
70 };
71 SetProcessInformation(GetCurrentProcess(), ProcessPowerThrottling, &PowerThrottling,
72 sizeof(PROCESS_POWER_THROTTLING_STATE));
73}
74
75} // Anonymous namespace
76
77nanoseconds GetMinimumTimerResolution() {
78 return GetTimerResolution().minimum;
79}
80
81nanoseconds GetMaximumTimerResolution() {
82 return GetTimerResolution().maximum;
83}
84
85nanoseconds GetCurrentTimerResolution() {
86 return GetTimerResolution().current;
87}
88
89nanoseconds SetCurrentTimerResolution(nanoseconds timer_resolution) {
90 // Set the timer resolution, and return the current timer resolution.
91 const auto DesiredTimerResolution = ToHundredNS(timer_resolution);
92 ULONG CurrentTimerResolution;
93 NtSetTimerResolution(DesiredTimerResolution, TRUE, &CurrentTimerResolution);
94 return ToNS(CurrentTimerResolution);
95}
96
97nanoseconds SetCurrentTimerResolutionToMaximum() {
98 SetHighQoS();
99 return SetCurrentTimerResolution(GetMaximumTimerResolution());
100}
101
102void SleepForOneTick() {
103 LARGE_INTEGER DelayInterval{
104 .QuadPart{-1},
105 };
106 NtDelayExecution(FALSE, &DelayInterval);
107}
108
109} // namespace Common::Windows
diff --git a/src/common/windows/timer_resolution.h b/src/common/windows/timer_resolution.h
new file mode 100644
index 000000000..e1e50a62d
--- /dev/null
+++ b/src/common/windows/timer_resolution.h
@@ -0,0 +1,38 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <chrono>
7
8namespace Common::Windows {
9
10/// Returns the minimum (least precise) supported timer resolution in nanoseconds.
11std::chrono::nanoseconds GetMinimumTimerResolution();
12
13/// Returns the maximum (most precise) supported timer resolution in nanoseconds.
14std::chrono::nanoseconds GetMaximumTimerResolution();
15
16/// Returns the current timer resolution in nanoseconds.
17std::chrono::nanoseconds GetCurrentTimerResolution();
18
19/**
20 * Sets the current timer resolution.
21 *
22 * @param timer_resolution Timer resolution in nanoseconds.
23 *
24 * @returns The current timer resolution.
25 */
26std::chrono::nanoseconds SetCurrentTimerResolution(std::chrono::nanoseconds timer_resolution);
27
28/**
29 * Sets the current timer resolution to the maximum supported timer resolution.
30 *
31 * @returns The current timer resolution.
32 */
33std::chrono::nanoseconds SetCurrentTimerResolutionToMaximum();
34
35/// Sleep for one tick of the current timer resolution.
36void SleepForOneTick();
37
38} // namespace Common::Windows
diff --git a/src/common/x64/native_clock.cpp b/src/common/x64/native_clock.cpp
index 8b08332ab..76c66e7ee 100644
--- a/src/common/x64/native_clock.cpp
+++ b/src/common/x64/native_clock.cpp
@@ -6,6 +6,7 @@
6#include <thread> 6#include <thread>
7 7
8#include "common/atomic_ops.h" 8#include "common/atomic_ops.h"
9#include "common/steady_clock.h"
9#include "common/uint128.h" 10#include "common/uint128.h"
10#include "common/x64/native_clock.h" 11#include "common/x64/native_clock.h"
11 12
@@ -39,6 +40,12 @@ static u64 FencedRDTSC() {
39} 40}
40#endif 41#endif
41 42
43template <u64 Nearest>
44static u64 RoundToNearest(u64 value) {
45 const auto mod = value % Nearest;
46 return mod >= (Nearest / 2) ? (value - mod + Nearest) : (value - mod);
47}
48
42u64 EstimateRDTSCFrequency() { 49u64 EstimateRDTSCFrequency() {
43 // Discard the first result measuring the rdtsc. 50 // Discard the first result measuring the rdtsc.
44 FencedRDTSC(); 51 FencedRDTSC();
@@ -46,18 +53,18 @@ u64 EstimateRDTSCFrequency() {
46 FencedRDTSC(); 53 FencedRDTSC();
47 54
48 // Get the current time. 55 // Get the current time.
49 const auto start_time = std::chrono::steady_clock::now(); 56 const auto start_time = Common::RealTimeClock::Now();
50 const u64 tsc_start = FencedRDTSC(); 57 const u64 tsc_start = FencedRDTSC();
51 // Wait for 200 milliseconds. 58 // Wait for 250 milliseconds.
52 std::this_thread::sleep_for(std::chrono::milliseconds{200}); 59 std::this_thread::sleep_for(std::chrono::milliseconds{250});
53 const auto end_time = std::chrono::steady_clock::now(); 60 const auto end_time = Common::RealTimeClock::Now();
54 const u64 tsc_end = FencedRDTSC(); 61 const u64 tsc_end = FencedRDTSC();
55 // Calculate differences. 62 // Calculate differences.
56 const u64 timer_diff = static_cast<u64>( 63 const u64 timer_diff = static_cast<u64>(
57 std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - start_time).count()); 64 std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - start_time).count());
58 const u64 tsc_diff = tsc_end - tsc_start; 65 const u64 tsc_diff = tsc_end - tsc_start;
59 const u64 tsc_freq = MultiplyAndDivide64(tsc_diff, 1000000000ULL, timer_diff); 66 const u64 tsc_freq = MultiplyAndDivide64(tsc_diff, 1000000000ULL, timer_diff);
60 return tsc_freq; 67 return RoundToNearest<1000>(tsc_freq);
61} 68}
62 69
63namespace X64 { 70namespace X64 {
@@ -65,13 +72,29 @@ NativeClock::NativeClock(u64 emulated_cpu_frequency_, u64 emulated_clock_frequen
65 u64 rtsc_frequency_) 72 u64 rtsc_frequency_)
66 : WallClock(emulated_cpu_frequency_, emulated_clock_frequency_, true), rtsc_frequency{ 73 : WallClock(emulated_cpu_frequency_, emulated_clock_frequency_, true), rtsc_frequency{
67 rtsc_frequency_} { 74 rtsc_frequency_} {
75 // Thread to re-adjust the RDTSC frequency after 10 seconds has elapsed.
76 time_sync_thread = std::jthread{[this](std::stop_token token) {
77 // Get the current time.
78 const auto start_time = Common::RealTimeClock::Now();
79 const u64 tsc_start = FencedRDTSC();
80 // Wait for 10 seconds.
81 if (!Common::StoppableTimedWait(token, std::chrono::seconds{10})) {
82 return;
83 }
84 const auto end_time = Common::RealTimeClock::Now();
85 const u64 tsc_end = FencedRDTSC();
86 // Calculate differences.
87 const u64 timer_diff = static_cast<u64>(
88 std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - start_time).count());
89 const u64 tsc_diff = tsc_end - tsc_start;
90 const u64 tsc_freq = MultiplyAndDivide64(tsc_diff, 1000000000ULL, timer_diff);
91 rtsc_frequency = tsc_freq;
92 CalculateAndSetFactors();
93 }};
94
68 time_point.inner.last_measure = FencedRDTSC(); 95 time_point.inner.last_measure = FencedRDTSC();
69 time_point.inner.accumulated_ticks = 0U; 96 time_point.inner.accumulated_ticks = 0U;
70 ns_rtsc_factor = GetFixedPoint64Factor(NS_RATIO, rtsc_frequency); 97 CalculateAndSetFactors();
71 us_rtsc_factor = GetFixedPoint64Factor(US_RATIO, rtsc_frequency);
72 ms_rtsc_factor = GetFixedPoint64Factor(MS_RATIO, rtsc_frequency);
73 clock_rtsc_factor = GetFixedPoint64Factor(emulated_clock_frequency, rtsc_frequency);
74 cpu_rtsc_factor = GetFixedPoint64Factor(emulated_cpu_frequency, rtsc_frequency);
75} 98}
76 99
77u64 NativeClock::GetRTSC() { 100u64 NativeClock::GetRTSC() {
@@ -131,6 +154,14 @@ u64 NativeClock::GetCPUCycles() {
131 return MultiplyHigh(rtsc_value, cpu_rtsc_factor); 154 return MultiplyHigh(rtsc_value, cpu_rtsc_factor);
132} 155}
133 156
157void NativeClock::CalculateAndSetFactors() {
158 ns_rtsc_factor = GetFixedPoint64Factor(NS_RATIO, rtsc_frequency);
159 us_rtsc_factor = GetFixedPoint64Factor(US_RATIO, rtsc_frequency);
160 ms_rtsc_factor = GetFixedPoint64Factor(MS_RATIO, rtsc_frequency);
161 clock_rtsc_factor = GetFixedPoint64Factor(emulated_clock_frequency, rtsc_frequency);
162 cpu_rtsc_factor = GetFixedPoint64Factor(emulated_cpu_frequency, rtsc_frequency);
163}
164
134} // namespace X64 165} // namespace X64
135 166
136} // namespace Common 167} // namespace Common
diff --git a/src/common/x64/native_clock.h b/src/common/x64/native_clock.h
index 38ae7a462..03ca291d8 100644
--- a/src/common/x64/native_clock.h
+++ b/src/common/x64/native_clock.h
@@ -3,6 +3,7 @@
3 3
4#pragma once 4#pragma once
5 5
6#include "common/polyfill_thread.h"
6#include "common/wall_clock.h" 7#include "common/wall_clock.h"
7 8
8namespace Common { 9namespace Common {
@@ -28,6 +29,8 @@ public:
28private: 29private:
29 u64 GetRTSC(); 30 u64 GetRTSC();
30 31
32 void CalculateAndSetFactors();
33
31 union alignas(16) TimePoint { 34 union alignas(16) TimePoint {
32 TimePoint() : pack{} {} 35 TimePoint() : pack{} {}
33 u128 pack{}; 36 u128 pack{};
@@ -47,6 +50,8 @@ private:
47 u64 ms_rtsc_factor{}; 50 u64 ms_rtsc_factor{};
48 51
49 u64 rtsc_frequency; 52 u64 rtsc_frequency;
53
54 std::jthread time_sync_thread;
50}; 55};
51} // namespace X64 56} // namespace X64
52 57