summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/input.h2
-rw-r--r--src/common/ring_buffer.h2
-rw-r--r--src/common/scratch_buffer.h46
-rw-r--r--src/common/settings.h10
-rw-r--r--src/common/telemetry.cpp1
-rw-r--r--src/common/x64/cpu_detect.cpp1
-rw-r--r--src/common/x64/cpu_detect.h1
-rw-r--r--src/common/x64/cpu_wait.cpp52
8 files changed, 74 insertions, 41 deletions
diff --git a/src/common/input.h b/src/common/input.h
index ea30770ae..2c4ccea22 100644
--- a/src/common/input.h
+++ b/src/common/input.h
@@ -75,8 +75,10 @@ enum class DriverResult {
75 ErrorWritingData, 75 ErrorWritingData,
76 NoDeviceDetected, 76 NoDeviceDetected,
77 InvalidHandle, 77 InvalidHandle,
78 InvalidParameters,
78 NotSupported, 79 NotSupported,
79 Disabled, 80 Disabled,
81 Delayed,
80 Unknown, 82 Unknown,
81}; 83};
82 84
diff --git a/src/common/ring_buffer.h b/src/common/ring_buffer.h
index 416680d44..5c961b202 100644
--- a/src/common/ring_buffer.h
+++ b/src/common/ring_buffer.h
@@ -54,7 +54,7 @@ public:
54 return push_count; 54 return push_count;
55 } 55 }
56 56
57 std::size_t Push(const std::span<T> input) { 57 std::size_t Push(std::span<const T> input) {
58 return Push(input.data(), input.size()); 58 return Push(input.data(), input.size());
59 } 59 }
60 60
diff --git a/src/common/scratch_buffer.h b/src/common/scratch_buffer.h
index 6fe907953..d5961b020 100644
--- a/src/common/scratch_buffer.h
+++ b/src/common/scratch_buffer.h
@@ -5,7 +5,6 @@
5 5
6#include <iterator> 6#include <iterator>
7 7
8#include "common/concepts.h"
9#include "common/make_unique_for_overwrite.h" 8#include "common/make_unique_for_overwrite.h"
10 9
11namespace Common { 10namespace Common {
@@ -19,15 +18,22 @@ namespace Common {
19template <typename T> 18template <typename T>
20class ScratchBuffer { 19class ScratchBuffer {
21public: 20public:
22 using iterator = T*;
23 using const_iterator = const T*;
24 using value_type = T;
25 using element_type = T; 21 using element_type = T;
26 using iterator_category = std::contiguous_iterator_tag; 22 using value_type = T;
23 using size_type = size_t;
24 using difference_type = std::ptrdiff_t;
25 using pointer = T*;
26 using const_pointer = const T*;
27 using reference = T&;
28 using const_reference = const T&;
29 using iterator = pointer;
30 using const_iterator = const_pointer;
31 using iterator_category = std::random_access_iterator_tag;
32 using iterator_concept = std::contiguous_iterator_tag;
27 33
28 ScratchBuffer() = default; 34 ScratchBuffer() = default;
29 35
30 explicit ScratchBuffer(size_t initial_capacity) 36 explicit ScratchBuffer(size_type initial_capacity)
31 : last_requested_size{initial_capacity}, buffer_capacity{initial_capacity}, 37 : last_requested_size{initial_capacity}, buffer_capacity{initial_capacity},
32 buffer{Common::make_unique_for_overwrite<T[]>(initial_capacity)} {} 38 buffer{Common::make_unique_for_overwrite<T[]>(initial_capacity)} {}
33 39
@@ -39,7 +45,7 @@ public:
39 45
40 /// This will only grow the buffer's capacity if size is greater than the current capacity. 46 /// This will only grow the buffer's capacity if size is greater than the current capacity.
41 /// The previously held data will remain intact. 47 /// The previously held data will remain intact.
42 void resize(size_t size) { 48 void resize(size_type size) {
43 if (size > buffer_capacity) { 49 if (size > buffer_capacity) {
44 auto new_buffer = Common::make_unique_for_overwrite<T[]>(size); 50 auto new_buffer = Common::make_unique_for_overwrite<T[]>(size);
45 std::move(buffer.get(), buffer.get() + buffer_capacity, new_buffer.get()); 51 std::move(buffer.get(), buffer.get() + buffer_capacity, new_buffer.get());
@@ -51,7 +57,7 @@ public:
51 57
52 /// This will only grow the buffer's capacity if size is greater than the current capacity. 58 /// This will only grow the buffer's capacity if size is greater than the current capacity.
53 /// The previously held data will be destroyed if a reallocation occurs. 59 /// The previously held data will be destroyed if a reallocation occurs.
54 void resize_destructive(size_t size) { 60 void resize_destructive(size_type size) {
55 if (size > buffer_capacity) { 61 if (size > buffer_capacity) {
56 buffer_capacity = size; 62 buffer_capacity = size;
57 buffer = Common::make_unique_for_overwrite<T[]>(buffer_capacity); 63 buffer = Common::make_unique_for_overwrite<T[]>(buffer_capacity);
@@ -59,43 +65,43 @@ public:
59 last_requested_size = size; 65 last_requested_size = size;
60 } 66 }
61 67
62 [[nodiscard]] T* data() noexcept { 68 [[nodiscard]] pointer data() noexcept {
63 return buffer.get(); 69 return buffer.get();
64 } 70 }
65 71
66 [[nodiscard]] const T* data() const noexcept { 72 [[nodiscard]] const_pointer data() const noexcept {
67 return buffer.get(); 73 return buffer.get();
68 } 74 }
69 75
70 [[nodiscard]] T* begin() noexcept { 76 [[nodiscard]] iterator begin() noexcept {
71 return data(); 77 return data();
72 } 78 }
73 79
74 [[nodiscard]] const T* begin() const noexcept { 80 [[nodiscard]] const_iterator begin() const noexcept {
75 return data(); 81 return data();
76 } 82 }
77 83
78 [[nodiscard]] T* end() noexcept { 84 [[nodiscard]] iterator end() noexcept {
79 return data() + last_requested_size; 85 return data() + last_requested_size;
80 } 86 }
81 87
82 [[nodiscard]] const T* end() const noexcept { 88 [[nodiscard]] const_iterator end() const noexcept {
83 return data() + last_requested_size; 89 return data() + last_requested_size;
84 } 90 }
85 91
86 [[nodiscard]] T& operator[](size_t i) { 92 [[nodiscard]] reference operator[](size_type i) {
87 return buffer[i]; 93 return buffer[i];
88 } 94 }
89 95
90 [[nodiscard]] const T& operator[](size_t i) const { 96 [[nodiscard]] const_reference operator[](size_type i) const {
91 return buffer[i]; 97 return buffer[i];
92 } 98 }
93 99
94 [[nodiscard]] size_t size() const noexcept { 100 [[nodiscard]] size_type size() const noexcept {
95 return last_requested_size; 101 return last_requested_size;
96 } 102 }
97 103
98 [[nodiscard]] size_t capacity() const noexcept { 104 [[nodiscard]] size_type capacity() const noexcept {
99 return buffer_capacity; 105 return buffer_capacity;
100 } 106 }
101 107
@@ -106,8 +112,8 @@ public:
106 } 112 }
107 113
108private: 114private:
109 size_t last_requested_size{}; 115 size_type last_requested_size{};
110 size_t buffer_capacity{}; 116 size_type buffer_capacity{};
111 std::unique_ptr<T[]> buffer{}; 117 std::unique_ptr<T[]> buffer{};
112}; 118};
113 119
diff --git a/src/common/settings.h b/src/common/settings.h
index ae5ed93d8..59e96e74f 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -527,12 +527,10 @@ struct Values {
527 Setting<bool> mouse_panning{false, "mouse_panning"}; 527 Setting<bool> mouse_panning{false, "mouse_panning"};
528 Setting<u8, true> mouse_panning_x_sensitivity{50, 1, 100, "mouse_panning_x_sensitivity"}; 528 Setting<u8, true> mouse_panning_x_sensitivity{50, 1, 100, "mouse_panning_x_sensitivity"};
529 Setting<u8, true> mouse_panning_y_sensitivity{50, 1, 100, "mouse_panning_y_sensitivity"}; 529 Setting<u8, true> mouse_panning_y_sensitivity{50, 1, 100, "mouse_panning_y_sensitivity"};
530 Setting<u8, true> mouse_panning_deadzone_x_counterweight{ 530 Setting<u8, true> mouse_panning_deadzone_counterweight{20, 0, 100,
531 0, 0, 100, "mouse_panning_deadzone_x_counterweight"}; 531 "mouse_panning_deadzone_counterweight"};
532 Setting<u8, true> mouse_panning_deadzone_y_counterweight{ 532 Setting<u8, true> mouse_panning_decay_strength{18, 0, 100, "mouse_panning_decay_strength"};
533 0, 0, 100, "mouse_panning_deadzone_y_counterweight"}; 533 Setting<u8, true> mouse_panning_min_decay{6, 0, 100, "mouse_panning_min_decay"};
534 Setting<u8, true> mouse_panning_decay_strength{22, 0, 100, "mouse_panning_decay_strength"};
535 Setting<u8, true> mouse_panning_min_decay{5, 0, 100, "mouse_panning_min_decay"};
536 534
537 Setting<bool> mouse_enabled{false, "mouse_enabled"}; 535 Setting<bool> mouse_enabled{false, "mouse_enabled"};
538 Setting<bool> emulate_analog_keyboard{false, "emulate_analog_keyboard"}; 536 Setting<bool> emulate_analog_keyboard{false, "emulate_analog_keyboard"};
diff --git a/src/common/telemetry.cpp b/src/common/telemetry.cpp
index 91352912d..929ed67e4 100644
--- a/src/common/telemetry.cpp
+++ b/src/common/telemetry.cpp
@@ -93,6 +93,7 @@ void AppendCPUInfo(FieldCollection& fc) {
93 add_field("CPU_Extension_x64_GFNI", caps.gfni); 93 add_field("CPU_Extension_x64_GFNI", caps.gfni);
94 add_field("CPU_Extension_x64_INVARIANT_TSC", caps.invariant_tsc); 94 add_field("CPU_Extension_x64_INVARIANT_TSC", caps.invariant_tsc);
95 add_field("CPU_Extension_x64_LZCNT", caps.lzcnt); 95 add_field("CPU_Extension_x64_LZCNT", caps.lzcnt);
96 add_field("CPU_Extension_x64_MONITORX", caps.monitorx);
96 add_field("CPU_Extension_x64_MOVBE", caps.movbe); 97 add_field("CPU_Extension_x64_MOVBE", caps.movbe);
97 add_field("CPU_Extension_x64_PCLMULQDQ", caps.pclmulqdq); 98 add_field("CPU_Extension_x64_PCLMULQDQ", caps.pclmulqdq);
98 add_field("CPU_Extension_x64_POPCNT", caps.popcnt); 99 add_field("CPU_Extension_x64_POPCNT", caps.popcnt);
diff --git a/src/common/x64/cpu_detect.cpp b/src/common/x64/cpu_detect.cpp
index c998b1197..780120a5b 100644
--- a/src/common/x64/cpu_detect.cpp
+++ b/src/common/x64/cpu_detect.cpp
@@ -168,6 +168,7 @@ static CPUCaps Detect() {
168 __cpuid(cpu_id, 0x80000001); 168 __cpuid(cpu_id, 0x80000001);
169 caps.lzcnt = Common::Bit<5>(cpu_id[2]); 169 caps.lzcnt = Common::Bit<5>(cpu_id[2]);
170 caps.fma4 = Common::Bit<16>(cpu_id[2]); 170 caps.fma4 = Common::Bit<16>(cpu_id[2]);
171 caps.monitorx = Common::Bit<29>(cpu_id[2]);
171 } 172 }
172 173
173 if (max_ex_fn >= 0x80000007) { 174 if (max_ex_fn >= 0x80000007) {
diff --git a/src/common/x64/cpu_detect.h b/src/common/x64/cpu_detect.h
index 8253944d6..756459417 100644
--- a/src/common/x64/cpu_detect.h
+++ b/src/common/x64/cpu_detect.h
@@ -63,6 +63,7 @@ struct CPUCaps {
63 bool gfni : 1; 63 bool gfni : 1;
64 bool invariant_tsc : 1; 64 bool invariant_tsc : 1;
65 bool lzcnt : 1; 65 bool lzcnt : 1;
66 bool monitorx : 1;
66 bool movbe : 1; 67 bool movbe : 1;
67 bool pclmulqdq : 1; 68 bool pclmulqdq : 1;
68 bool popcnt : 1; 69 bool popcnt : 1;
diff --git a/src/common/x64/cpu_wait.cpp b/src/common/x64/cpu_wait.cpp
index c53dd4945..41d385f59 100644
--- a/src/common/x64/cpu_wait.cpp
+++ b/src/common/x64/cpu_wait.cpp
@@ -13,36 +13,60 @@
13 13
14namespace Common::X64 { 14namespace Common::X64 {
15 15
16namespace {
17
18// 100,000 cycles is a reasonable amount of time to wait to save on CPU resources.
19// For reference:
20// At 1 GHz, 100K cycles is 100us
21// At 2 GHz, 100K cycles is 50us
22// At 4 GHz, 100K cycles is 25us
23constexpr auto PauseCycles = 100'000U;
24
25} // Anonymous namespace
26
16#ifdef _MSC_VER 27#ifdef _MSC_VER
17__forceinline static void TPAUSE() { 28__forceinline static void TPAUSE() {
18 // 100,000 cycles is a reasonable amount of time to wait to save on CPU resources. 29 static constexpr auto RequestC02State = 0U;
19 // For reference: 30 _tpause(RequestC02State, FencedRDTSC() + PauseCycles);
20 // At 1 GHz, 100K cycles is 100us 31}
21 // At 2 GHz, 100K cycles is 50us 32
22 // At 4 GHz, 100K cycles is 25us 33__forceinline static void MWAITX() {
23 static constexpr auto PauseCycles = 100'000; 34 static constexpr auto EnableWaitTimeFlag = 1U << 1;
24 _tpause(0, FencedRDTSC() + PauseCycles); 35 static constexpr auto RequestC1State = 0U;
36
37 // monitor_var should be aligned to a cache line.
38 alignas(64) u64 monitor_var{};
39 _mm_monitorx(&monitor_var, 0, 0);
40 _mm_mwaitx(EnableWaitTimeFlag, RequestC1State, PauseCycles);
25} 41}
26#else 42#else
27static void TPAUSE() { 43static void TPAUSE() {
28 // 100,000 cycles is a reasonable amount of time to wait to save on CPU resources. 44 static constexpr auto RequestC02State = 0U;
29 // For reference:
30 // At 1 GHz, 100K cycles is 100us
31 // At 2 GHz, 100K cycles is 50us
32 // At 4 GHz, 100K cycles is 25us
33 static constexpr auto PauseCycles = 100'000;
34 const auto tsc = FencedRDTSC() + PauseCycles; 45 const auto tsc = FencedRDTSC() + PauseCycles;
35 const auto eax = static_cast<u32>(tsc & 0xFFFFFFFF); 46 const auto eax = static_cast<u32>(tsc & 0xFFFFFFFF);
36 const auto edx = static_cast<u32>(tsc >> 32); 47 const auto edx = static_cast<u32>(tsc >> 32);
37 asm volatile("tpause %0" : : "r"(0), "d"(edx), "a"(eax)); 48 asm volatile("tpause %0" : : "r"(RequestC02State), "d"(edx), "a"(eax));
49}
50
51static void MWAITX() {
52 static constexpr auto EnableWaitTimeFlag = 1U << 1;
53 static constexpr auto RequestC1State = 0U;
54
55 // monitor_var should be aligned to a cache line.
56 alignas(64) u64 monitor_var{};
57 asm volatile("monitorx" : : "a"(&monitor_var), "c"(0), "d"(0));
58 asm volatile("mwaitx" : : "a"(RequestC1State), "b"(PauseCycles), "c"(EnableWaitTimeFlag));
38} 59}
39#endif 60#endif
40 61
41void MicroSleep() { 62void MicroSleep() {
42 static const bool has_waitpkg = GetCPUCaps().waitpkg; 63 static const bool has_waitpkg = GetCPUCaps().waitpkg;
64 static const bool has_monitorx = GetCPUCaps().monitorx;
43 65
44 if (has_waitpkg) { 66 if (has_waitpkg) {
45 TPAUSE(); 67 TPAUSE();
68 } else if (has_monitorx) {
69 MWAITX();
46 } else { 70 } else {
47 std::this_thread::yield(); 71 std::this_thread::yield();
48 } 72 }