summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/CMakeLists.txt1
-rw-r--r--src/common/bit_cast.h20
-rw-r--r--src/common/input.h2
-rw-r--r--src/common/overflow.h22
-rw-r--r--src/common/settings.h2
-rw-r--r--src/common/steady_clock.cpp25
-rw-r--r--src/common/steady_clock.h11
-rw-r--r--src/common/x64/native_clock.cpp38
-rw-r--r--src/common/x64/native_clock.h5
9 files changed, 108 insertions, 18 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 58ff5f2f3..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
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/input.h b/src/common/input.h
index b5748a6c8..98e934685 100644
--- a/src/common/input.h
+++ b/src/common/input.h
@@ -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
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 1ae28ce93..b77a1580a 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -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
index 0d5908aa7..782859196 100644
--- a/src/common/steady_clock.cpp
+++ b/src/common/steady_clock.cpp
@@ -23,6 +23,19 @@ static s64 WindowsQueryPerformanceCounter() {
23 QueryPerformanceCounter(&counter); 23 QueryPerformanceCounter(&counter);
24 return counter.QuadPart; 24 return counter.QuadPart;
25} 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}
26#endif 39#endif
27 40
28SteadyClock::time_point SteadyClock::Now() noexcept { 41SteadyClock::time_point SteadyClock::Now() noexcept {
@@ -53,4 +66,16 @@ SteadyClock::time_point SteadyClock::Now() noexcept {
53#endif 66#endif
54} 67}
55 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
56}; // namespace Common 81}; // namespace Common
diff --git a/src/common/steady_clock.h b/src/common/steady_clock.h
index 9497cf865..dbd0e2513 100644
--- a/src/common/steady_clock.h
+++ b/src/common/steady_clock.h
@@ -20,4 +20,15 @@ struct SteadyClock {
20 [[nodiscard]] static time_point Now() noexcept; 20 [[nodiscard]] static time_point Now() noexcept;
21}; 21};
22 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
23} // namespace Common 34} // namespace Common
diff --git a/src/common/x64/native_clock.cpp b/src/common/x64/native_clock.cpp
index bc1a973b0..76c66e7ee 100644
--- a/src/common/x64/native_clock.cpp
+++ b/src/common/x64/native_clock.cpp
@@ -53,11 +53,11 @@ u64 EstimateRDTSCFrequency() {
53 FencedRDTSC(); 53 FencedRDTSC();
54 54
55 // Get the current time. 55 // Get the current time.
56 const auto start_time = Common::SteadyClock::Now(); 56 const auto start_time = Common::RealTimeClock::Now();
57 const u64 tsc_start = FencedRDTSC(); 57 const u64 tsc_start = FencedRDTSC();
58 // Wait for 250 milliseconds. 58 // Wait for 250 milliseconds.
59 std::this_thread::sleep_for(std::chrono::milliseconds{250}); 59 std::this_thread::sleep_for(std::chrono::milliseconds{250});
60 const auto end_time = Common::SteadyClock::Now(); 60 const auto end_time = Common::RealTimeClock::Now();
61 const u64 tsc_end = FencedRDTSC(); 61 const u64 tsc_end = FencedRDTSC();
62 // Calculate differences. 62 // Calculate differences.
63 const u64 timer_diff = static_cast<u64>( 63 const u64 timer_diff = static_cast<u64>(
@@ -72,13 +72,29 @@ NativeClock::NativeClock(u64 emulated_cpu_frequency_, u64 emulated_clock_frequen
72 u64 rtsc_frequency_) 72 u64 rtsc_frequency_)
73 : WallClock(emulated_cpu_frequency_, emulated_clock_frequency_, true), rtsc_frequency{ 73 : WallClock(emulated_cpu_frequency_, emulated_clock_frequency_, true), rtsc_frequency{
74 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
75 time_point.inner.last_measure = FencedRDTSC(); 95 time_point.inner.last_measure = FencedRDTSC();
76 time_point.inner.accumulated_ticks = 0U; 96 time_point.inner.accumulated_ticks = 0U;
77 ns_rtsc_factor = GetFixedPoint64Factor(NS_RATIO, rtsc_frequency); 97 CalculateAndSetFactors();
78 us_rtsc_factor = GetFixedPoint64Factor(US_RATIO, rtsc_frequency);
79 ms_rtsc_factor = GetFixedPoint64Factor(MS_RATIO, rtsc_frequency);
80 clock_rtsc_factor = GetFixedPoint64Factor(emulated_clock_frequency, rtsc_frequency);
81 cpu_rtsc_factor = GetFixedPoint64Factor(emulated_cpu_frequency, rtsc_frequency);
82} 98}
83 99
84u64 NativeClock::GetRTSC() { 100u64 NativeClock::GetRTSC() {
@@ -138,6 +154,14 @@ u64 NativeClock::GetCPUCycles() {
138 return MultiplyHigh(rtsc_value, cpu_rtsc_factor); 154 return MultiplyHigh(rtsc_value, cpu_rtsc_factor);
139} 155}
140 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
141} // namespace X64 165} // namespace X64
142 166
143} // 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