summaryrefslogtreecommitdiffstats
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/common/atomic_ops.h95
-rw-r--r--src/common/bit_field.h1
-rw-r--r--src/common/bit_util.h7
-rw-r--r--src/common/dynamic_library.cpp1
-rw-r--r--src/common/fiber.cpp5
-rw-r--r--src/common/fs/file.cpp1
-rw-r--r--src/common/fs/file.h2
-rw-r--r--src/common/fs/fs_types.h1
-rw-r--r--src/common/fs/fs_util.h1
-rw-r--r--src/common/hex_util.h1
-rw-r--r--src/common/host_memory.cpp6
-rw-r--r--src/common/intrusive_red_black_tree.h390
-rw-r--r--src/common/logging/backend.cpp4
-rw-r--r--src/common/logging/backend.h1
-rw-r--r--src/common/logging/filter.cpp2
-rw-r--r--src/common/logging/filter.h1
-rw-r--r--src/common/logging/text_formatter.cpp2
-rw-r--r--src/common/logging/text_formatter.h1
-rw-r--r--src/common/logging/types.h2
-rw-r--r--src/common/math_util.h50
-rw-r--r--src/common/memory_detect.cpp2
-rw-r--r--src/common/nvidia_flags.cpp1
-rw-r--r--src/common/page_table.h1
-rw-r--r--src/common/parent_of_member.h1
-rw-r--r--src/common/ring_buffer.h1
-rw-r--r--src/common/settings.h6
-rw-r--r--src/common/settings_input.h1
-rw-r--r--src/common/string_util.cpp2
-rw-r--r--src/common/telemetry.cpp61
-rw-r--r--src/common/telemetry.h6
-rw-r--r--src/common/thread.h2
-rw-r--r--src/common/threadsafe_queue.h4
-rw-r--r--src/common/tree.h625
-rw-r--r--src/common/uint128.h2
-rw-r--r--src/common/uuid.h1
-rw-r--r--src/common/virtual_buffer.h1
-rw-r--r--src/common/wall_clock.cpp2
-rw-r--r--src/common/x64/cpu_detect.cpp123
-rw-r--r--src/common/x64/cpu_detect.h79
-rw-r--r--src/common/x64/native_clock.cpp61
-rw-r--r--src/common/x64/native_clock.h2
41 files changed, 922 insertions, 636 deletions
diff --git a/src/common/atomic_ops.h b/src/common/atomic_ops.h
index 2b1f515e8..69fde8421 100644
--- a/src/common/atomic_ops.h
+++ b/src/common/atomic_ops.h
@@ -4,13 +4,12 @@
#pragma once
-#include <cstring>
-#include <memory>
-
#include "common/common_types.h"
#if _MSC_VER
#include <intrin.h>
+#else
+#include <cstring>
#endif
namespace Common {
@@ -47,6 +46,50 @@ namespace Common {
reinterpret_cast<__int64*>(expected.data())) != 0;
}
+[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u8* pointer, u8 value, u8 expected,
+ u8& actual) {
+ actual =
+ _InterlockedCompareExchange8(reinterpret_cast<volatile char*>(pointer), value, expected);
+ return actual == expected;
+}
+
+[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u16* pointer, u16 value, u16 expected,
+ u16& actual) {
+ actual =
+ _InterlockedCompareExchange16(reinterpret_cast<volatile short*>(pointer), value, expected);
+ return actual == expected;
+}
+
+[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u32* pointer, u32 value, u32 expected,
+ u32& actual) {
+ actual =
+ _InterlockedCompareExchange(reinterpret_cast<volatile long*>(pointer), value, expected);
+ return actual == expected;
+}
+
+[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u64 value, u64 expected,
+ u64& actual) {
+ actual = _InterlockedCompareExchange64(reinterpret_cast<volatile __int64*>(pointer), value,
+ expected);
+ return actual == expected;
+}
+
+[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u128 value, u128 expected,
+ u128& actual) {
+ const bool result =
+ _InterlockedCompareExchange128(reinterpret_cast<volatile __int64*>(pointer), value[1],
+ value[0], reinterpret_cast<__int64*>(expected.data())) != 0;
+ actual = expected;
+ return result;
+}
+
+[[nodiscard]] inline u128 AtomicLoad128(volatile u64* pointer) {
+ u128 result{};
+ _InterlockedCompareExchange128(reinterpret_cast<volatile __int64*>(pointer), result[1],
+ result[0], reinterpret_cast<__int64*>(result.data()));
+ return result;
+}
+
#else
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u8* pointer, u8 value, u8 expected) {
@@ -73,6 +116,52 @@ namespace Common {
return __sync_bool_compare_and_swap((unsigned __int128*)pointer, expected_a, value_a);
}
+[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u8* pointer, u8 value, u8 expected,
+ u8& actual) {
+ actual = __sync_val_compare_and_swap(pointer, expected, value);
+ return actual == expected;
+}
+
+[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u16* pointer, u16 value, u16 expected,
+ u16& actual) {
+ actual = __sync_val_compare_and_swap(pointer, expected, value);
+ return actual == expected;
+}
+
+[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u32* pointer, u32 value, u32 expected,
+ u32& actual) {
+ actual = __sync_val_compare_and_swap(pointer, expected, value);
+ return actual == expected;
+}
+
+[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u64 value, u64 expected,
+ u64& actual) {
+ actual = __sync_val_compare_and_swap(pointer, expected, value);
+ return actual == expected;
+}
+
+[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u128 value, u128 expected,
+ u128& actual) {
+ unsigned __int128 value_a;
+ unsigned __int128 expected_a;
+ unsigned __int128 actual_a;
+ std::memcpy(&value_a, value.data(), sizeof(u128));
+ std::memcpy(&expected_a, expected.data(), sizeof(u128));
+ actual_a = __sync_val_compare_and_swap((unsigned __int128*)pointer, expected_a, value_a);
+ std::memcpy(actual.data(), &actual_a, sizeof(u128));
+ return actual_a == expected_a;
+}
+
+[[nodiscard]] inline u128 AtomicLoad128(volatile u64* pointer) {
+ unsigned __int128 zeros_a = 0;
+ unsigned __int128 result_a =
+ __sync_val_compare_and_swap((unsigned __int128*)pointer, zeros_a, zeros_a);
+
+ u128 result;
+ std::memcpy(result.data(), &result_a, sizeof(u128));
+ return result;
+}
+
#endif
} // namespace Common
diff --git a/src/common/bit_field.h b/src/common/bit_field.h
index 0f0661172..7f8620e7d 100644
--- a/src/common/bit_field.h
+++ b/src/common/bit_field.h
@@ -33,7 +33,6 @@
#include <cstddef>
#include <limits>
#include <type_traits>
-#include "common/common_funcs.h"
#include "common/swap.h"
/*
diff --git a/src/common/bit_util.h b/src/common/bit_util.h
index f50d3308a..f37538e06 100644
--- a/src/common/bit_util.h
+++ b/src/common/bit_util.h
@@ -57,4 +57,11 @@ requires std::is_integral_v<T>
return static_cast<T>(1ULL << ((8U * sizeof(T)) - std::countl_zero(value - 1U)));
}
+template <size_t bit_index, typename T>
+requires std::is_integral_v<T>
+[[nodiscard]] constexpr bool Bit(const T value) {
+ static_assert(bit_index < BitSize<T>(), "bit_index must be smaller than size of T");
+ return ((value >> bit_index) & T(1)) == T(1);
+}
+
} // namespace Common
diff --git a/src/common/dynamic_library.cpp b/src/common/dynamic_library.cpp
index 7f0a10521..11003e1d6 100644
--- a/src/common/dynamic_library.cpp
+++ b/src/common/dynamic_library.cpp
@@ -2,7 +2,6 @@
// Licensed under GPLv2+
// Refer to the license.txt file included.
-#include <cstring>
#include <string>
#include <utility>
diff --git a/src/common/fiber.cpp b/src/common/fiber.cpp
index 81b212e4b..177a74deb 100644
--- a/src/common/fiber.cpp
+++ b/src/common/fiber.cpp
@@ -2,9 +2,10 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include <mutex>
+
#include "common/assert.h"
#include "common/fiber.h"
-#include "common/spin_lock.h"
#include "common/virtual_buffer.h"
#include <boost/context/detail/fcontext.hpp>
@@ -19,7 +20,7 @@ struct Fiber::FiberImpl {
VirtualBuffer<u8> stack;
VirtualBuffer<u8> rewind_stack;
- SpinLock guard{};
+ std::mutex guard;
std::function<void(void*)> entry_point;
std::function<void(void*)> rewind_point;
void* rewind_parameter{};
diff --git a/src/common/fs/file.cpp b/src/common/fs/file.cpp
index 274f57659..5d71275ef 100644
--- a/src/common/fs/file.cpp
+++ b/src/common/fs/file.cpp
@@ -4,7 +4,6 @@
#include "common/fs/file.h"
#include "common/fs/fs.h"
-#include "common/fs/path_util.h"
#include "common/logging/log.h"
#ifdef _WIN32
diff --git a/src/common/fs/file.h b/src/common/fs/file.h
index a4f7944cd..8a2cab0af 100644
--- a/src/common/fs/file.h
+++ b/src/common/fs/file.h
@@ -6,10 +6,8 @@
#include <cstdio>
#include <filesystem>
-#include <fstream>
#include <span>
#include <type_traits>
-#include <vector>
#include "common/concepts.h"
#include "common/fs/fs_types.h"
diff --git a/src/common/fs/fs_types.h b/src/common/fs/fs_types.h
index 089980aee..f5853f624 100644
--- a/src/common/fs/fs_types.h
+++ b/src/common/fs/fs_types.h
@@ -7,7 +7,6 @@
#include <functional>
#include "common/common_funcs.h"
-#include "common/common_types.h"
namespace Common::FS {
diff --git a/src/common/fs/fs_util.h b/src/common/fs/fs_util.h
index 1620d38c9..392af89f7 100644
--- a/src/common/fs/fs_util.h
+++ b/src/common/fs/fs_util.h
@@ -8,7 +8,6 @@
#include <filesystem>
#include <span>
#include <string>
-#include <string_view>
#include "common/common_types.h"
diff --git a/src/common/hex_util.h b/src/common/hex_util.h
index 5e9b6ef8b..323c8fb33 100644
--- a/src/common/hex_util.h
+++ b/src/common/hex_util.h
@@ -7,7 +7,6 @@
#include <array>
#include <cstddef>
#include <string>
-#include <type_traits>
#include <vector>
#include <fmt/format.h>
#include "common/common_types.h"
diff --git a/src/common/host_memory.cpp b/src/common/host_memory.cpp
index c465cfc14..802943eb7 100644
--- a/src/common/host_memory.cpp
+++ b/src/common/host_memory.cpp
@@ -18,6 +18,7 @@
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
+#include "common/scope_exit.h"
#endif // ^^^ Linux ^^^
@@ -27,7 +28,6 @@
#include "common/assert.h"
#include "common/host_memory.h"
#include "common/logging/log.h"
-#include "common/scope_exit.h"
namespace Common {
@@ -149,7 +149,7 @@ public:
}
void Unmap(size_t virtual_offset, size_t length) {
- std::lock_guard lock{placeholder_mutex};
+ std::scoped_lock lock{placeholder_mutex};
// Unmap until there are no more placeholders
while (UnmapOnePlaceholder(virtual_offset, length)) {
@@ -169,7 +169,7 @@ public:
}
const size_t virtual_end = virtual_offset + length;
- std::lock_guard lock{placeholder_mutex};
+ std::scoped_lock lock{placeholder_mutex};
auto [it, end] = placeholders.equal_range({virtual_offset, virtual_end});
while (it != end) {
const size_t offset = std::max(it->lower(), virtual_offset);
diff --git a/src/common/intrusive_red_black_tree.h b/src/common/intrusive_red_black_tree.h
index 3173cc449..eaf5675e3 100644
--- a/src/common/intrusive_red_black_tree.h
+++ b/src/common/intrusive_red_black_tree.h
@@ -4,6 +4,7 @@
#pragma once
+#include "common/common_funcs.h"
#include "common/parent_of_member.h"
#include "common/tree.h"
@@ -15,32 +16,33 @@ class IntrusiveRedBlackTreeImpl;
}
+#pragma pack(push, 4)
struct IntrusiveRedBlackTreeNode {
+ YUZU_NON_COPYABLE(IntrusiveRedBlackTreeNode);
+
public:
- using EntryType = RBEntry<IntrusiveRedBlackTreeNode>;
+ using RBEntry = freebsd::RBEntry<IntrusiveRedBlackTreeNode>;
- constexpr IntrusiveRedBlackTreeNode() = default;
+private:
+ RBEntry m_entry;
- void SetEntry(const EntryType& new_entry) {
- entry = new_entry;
- }
+public:
+ explicit IntrusiveRedBlackTreeNode() = default;
- [[nodiscard]] EntryType& GetEntry() {
- return entry;
+ [[nodiscard]] constexpr RBEntry& GetRBEntry() {
+ return m_entry;
}
-
- [[nodiscard]] const EntryType& GetEntry() const {
- return entry;
+ [[nodiscard]] constexpr const RBEntry& GetRBEntry() const {
+ return m_entry;
}
-private:
- EntryType entry{};
-
- friend class impl::IntrusiveRedBlackTreeImpl;
-
- template <class, class, class>
- friend class IntrusiveRedBlackTree;
+ constexpr void SetRBEntry(const RBEntry& entry) {
+ m_entry = entry;
+ }
};
+static_assert(sizeof(IntrusiveRedBlackTreeNode) ==
+ 3 * sizeof(void*) + std::max<size_t>(sizeof(freebsd::RBColor), 4));
+#pragma pack(pop)
template <class T, class Traits, class Comparator>
class IntrusiveRedBlackTree;
@@ -48,12 +50,17 @@ class IntrusiveRedBlackTree;
namespace impl {
class IntrusiveRedBlackTreeImpl {
+ YUZU_NON_COPYABLE(IntrusiveRedBlackTreeImpl);
+
private:
template <class, class, class>
friend class ::Common::IntrusiveRedBlackTree;
- using RootType = RBHead<IntrusiveRedBlackTreeNode>;
- RootType root;
+private:
+ using RootType = freebsd::RBHead<IntrusiveRedBlackTreeNode>;
+
+private:
+ RootType m_root;
public:
template <bool Const>
@@ -81,149 +88,150 @@ public:
IntrusiveRedBlackTreeImpl::reference>;
private:
- pointer node;
+ pointer m_node;
public:
- explicit Iterator(pointer n) : node(n) {}
+ constexpr explicit Iterator(pointer n) : m_node(n) {}
- bool operator==(const Iterator& rhs) const {
- return this->node == rhs.node;
+ constexpr bool operator==(const Iterator& rhs) const {
+ return m_node == rhs.m_node;
}
- bool operator!=(const Iterator& rhs) const {
+ constexpr bool operator!=(const Iterator& rhs) const {
return !(*this == rhs);
}
- pointer operator->() const {
- return this->node;
+ constexpr pointer operator->() const {
+ return m_node;
}
- reference operator*() const {
- return *this->node;
+ constexpr reference operator*() const {
+ return *m_node;
}
- Iterator& operator++() {
- this->node = GetNext(this->node);
+ constexpr Iterator& operator++() {
+ m_node = GetNext(m_node);
return *this;
}
- Iterator& operator--() {
- this->node = GetPrev(this->node);
+ constexpr Iterator& operator--() {
+ m_node = GetPrev(m_node);
return *this;
}
- Iterator operator++(int) {
+ constexpr Iterator operator++(int) {
const Iterator it{*this};
++(*this);
return it;
}
- Iterator operator--(int) {
+ constexpr Iterator operator--(int) {
const Iterator it{*this};
--(*this);
return it;
}
- operator Iterator<true>() const {
- return Iterator<true>(this->node);
+ constexpr operator Iterator<true>() const {
+ return Iterator<true>(m_node);
}
};
private:
- // Define accessors using RB_* functions.
- bool EmptyImpl() const {
- return root.IsEmpty();
+ constexpr bool EmptyImpl() const {
+ return m_root.IsEmpty();
}
- IntrusiveRedBlackTreeNode* GetMinImpl() const {
- return RB_MIN(const_cast<RootType*>(&root));
+ constexpr IntrusiveRedBlackTreeNode* GetMinImpl() const {
+ return freebsd::RB_MIN(const_cast<RootType&>(m_root));
}
- IntrusiveRedBlackTreeNode* GetMaxImpl() const {
- return RB_MAX(const_cast<RootType*>(&root));
+ constexpr IntrusiveRedBlackTreeNode* GetMaxImpl() const {
+ return freebsd::RB_MAX(const_cast<RootType&>(m_root));
}
- IntrusiveRedBlackTreeNode* RemoveImpl(IntrusiveRedBlackTreeNode* node) {
- return RB_REMOVE(&root, node);
+ constexpr IntrusiveRedBlackTreeNode* RemoveImpl(IntrusiveRedBlackTreeNode* node) {
+ return freebsd::RB_REMOVE(m_root, node);
}
public:
- static IntrusiveRedBlackTreeNode* GetNext(IntrusiveRedBlackTreeNode* node) {
- return RB_NEXT(node);
+ static constexpr IntrusiveRedBlackTreeNode* GetNext(IntrusiveRedBlackTreeNode* node) {
+ return freebsd::RB_NEXT(node);
}
- static IntrusiveRedBlackTreeNode* GetPrev(IntrusiveRedBlackTreeNode* node) {
- return RB_PREV(node);
+ static constexpr IntrusiveRedBlackTreeNode* GetPrev(IntrusiveRedBlackTreeNode* node) {
+ return freebsd::RB_PREV(node);
}
- static const IntrusiveRedBlackTreeNode* GetNext(const IntrusiveRedBlackTreeNode* node) {
+ static constexpr IntrusiveRedBlackTreeNode const* GetNext(
+ IntrusiveRedBlackTreeNode const* node) {
return static_cast<const IntrusiveRedBlackTreeNode*>(
GetNext(const_cast<IntrusiveRedBlackTreeNode*>(node)));
}
- static const IntrusiveRedBlackTreeNode* GetPrev(const IntrusiveRedBlackTreeNode* node) {
+ static constexpr IntrusiveRedBlackTreeNode const* GetPrev(
+ IntrusiveRedBlackTreeNode const* node) {
return static_cast<const IntrusiveRedBlackTreeNode*>(
GetPrev(const_cast<IntrusiveRedBlackTreeNode*>(node)));
}
public:
- constexpr IntrusiveRedBlackTreeImpl() {}
+ constexpr IntrusiveRedBlackTreeImpl() = default;
// Iterator accessors.
- iterator begin() {
+ constexpr iterator begin() {
return iterator(this->GetMinImpl());
}
- const_iterator begin() const {
+ constexpr const_iterator begin() const {
return const_iterator(this->GetMinImpl());
}
- iterator end() {
+ constexpr iterator end() {
return iterator(static_cast<IntrusiveRedBlackTreeNode*>(nullptr));
}
- const_iterator end() const {
+ constexpr const_iterator end() const {
return const_iterator(static_cast<const IntrusiveRedBlackTreeNode*>(nullptr));
}
- const_iterator cbegin() const {
+ constexpr const_iterator cbegin() const {
return this->begin();
}
- const_iterator cend() const {
+ constexpr const_iterator cend() const {
return this->end();
}
- iterator iterator_to(reference ref) {
- return iterator(&ref);
+ constexpr iterator iterator_to(reference ref) {
+ return iterator(std::addressof(ref));
}
- const_iterator iterator_to(const_reference ref) const {
- return const_iterator(&ref);
+ constexpr const_iterator iterator_to(const_reference ref) const {
+ return const_iterator(std::addressof(ref));
}
// Content management.
- bool empty() const {
+ constexpr bool empty() const {
return this->EmptyImpl();
}
- reference back() {
+ constexpr reference back() {
return *this->GetMaxImpl();
}
- const_reference back() const {
+ constexpr const_reference back() const {
return *this->GetMaxImpl();
}
- reference front() {
+ constexpr reference front() {
return *this->GetMinImpl();
}
- const_reference front() const {
+ constexpr const_reference front() const {
return *this->GetMinImpl();
}
- iterator erase(iterator it) {
+ constexpr iterator erase(iterator it) {
auto cur = std::addressof(*it);
auto next = GetNext(cur);
this->RemoveImpl(cur);
@@ -234,16 +242,16 @@ public:
} // namespace impl
template <typename T>
-concept HasLightCompareType = requires {
- { std::is_same<typename T::LightCompareType, void>::value } -> std::convertible_to<bool>;
+concept HasRedBlackKeyType = requires {
+ { std::is_same<typename T::RedBlackKeyType, void>::value } -> std::convertible_to<bool>;
};
namespace impl {
template <typename T, typename Default>
- consteval auto* GetLightCompareType() {
- if constexpr (HasLightCompareType<T>) {
- return static_cast<typename T::LightCompareType*>(nullptr);
+ consteval auto* GetRedBlackKeyType() {
+ if constexpr (HasRedBlackKeyType<T>) {
+ return static_cast<typename T::RedBlackKeyType*>(nullptr);
} else {
return static_cast<Default*>(nullptr);
}
@@ -252,16 +260,17 @@ namespace impl {
} // namespace impl
template <typename T, typename Default>
-using LightCompareType = std::remove_pointer_t<decltype(impl::GetLightCompareType<T, Default>())>;
+using RedBlackKeyType = std::remove_pointer_t<decltype(impl::GetRedBlackKeyType<T, Default>())>;
template <class T, class Traits, class Comparator>
class IntrusiveRedBlackTree {
+ YUZU_NON_COPYABLE(IntrusiveRedBlackTree);
public:
using ImplType = impl::IntrusiveRedBlackTreeImpl;
private:
- ImplType impl{};
+ ImplType m_impl;
public:
template <bool Const>
@@ -277,9 +286,9 @@ public:
using iterator = Iterator<false>;
using const_iterator = Iterator<true>;
- using light_value_type = LightCompareType<Comparator, value_type>;
- using const_light_pointer = const light_value_type*;
- using const_light_reference = const light_value_type&;
+ using key_type = RedBlackKeyType<Comparator, value_type>;
+ using const_key_pointer = const key_type*;
+ using const_key_reference = const key_type&;
template <bool Const>
class Iterator {
@@ -298,183 +307,201 @@ public:
IntrusiveRedBlackTree::reference>;
private:
- ImplIterator iterator;
+ ImplIterator m_impl;
private:
- explicit Iterator(ImplIterator it) : iterator(it) {}
+ constexpr explicit Iterator(ImplIterator it) : m_impl(it) {}
- explicit Iterator(typename std::conditional<Const, ImplType::const_iterator,
- ImplType::iterator>::type::pointer ptr)
- : iterator(ptr) {}
+ constexpr explicit Iterator(typename ImplIterator::pointer p) : m_impl(p) {}
- ImplIterator GetImplIterator() const {
- return this->iterator;
+ constexpr ImplIterator GetImplIterator() const {
+ return m_impl;
}
public:
- bool operator==(const Iterator& rhs) const {
- return this->iterator == rhs.iterator;
+ constexpr bool operator==(const Iterator& rhs) const {
+ return m_impl == rhs.m_impl;
}
- bool operator!=(const Iterator& rhs) const {
+ constexpr bool operator!=(const Iterator& rhs) const {
return !(*this == rhs);
}
- pointer operator->() const {
- return Traits::GetParent(std::addressof(*this->iterator));
+ constexpr pointer operator->() const {
+ return Traits::GetParent(std::addressof(*m_impl));
}
- reference operator*() const {
- return *Traits::GetParent(std::addressof(*this->iterator));
+ constexpr reference operator*() const {
+ return *Traits::GetParent(std::addressof(*m_impl));
}
- Iterator& operator++() {
- ++this->iterator;
+ constexpr Iterator& operator++() {
+ ++m_impl;
return *this;
}
- Iterator& operator--() {
- --this->iterator;
+ constexpr Iterator& operator--() {
+ --m_impl;
return *this;
}
- Iterator operator++(int) {
+ constexpr Iterator operator++(int) {
const Iterator it{*this};
- ++this->iterator;
+ ++m_impl;
return it;
}
- Iterator operator--(int) {
+ constexpr Iterator operator--(int) {
const Iterator it{*this};
- --this->iterator;
+ --m_impl;
return it;
}
- operator Iterator<true>() const {
- return Iterator<true>(this->iterator);
+ constexpr operator Iterator<true>() const {
+ return Iterator<true>(m_impl);
}
};
private:
- static int CompareImpl(const IntrusiveRedBlackTreeNode* lhs,
- const IntrusiveRedBlackTreeNode* rhs) {
+ static constexpr int CompareImpl(const IntrusiveRedBlackTreeNode* lhs,
+ const IntrusiveRedBlackTreeNode* rhs) {
return Comparator::Compare(*Traits::GetParent(lhs), *Traits::GetParent(rhs));
}
- static int LightCompareImpl(const void* elm, const IntrusiveRedBlackTreeNode* rhs) {
- return Comparator::Compare(*static_cast<const_light_pointer>(elm), *Traits::GetParent(rhs));
+ static constexpr int CompareKeyImpl(const_key_reference key,
+ const IntrusiveRedBlackTreeNode* rhs) {
+ return Comparator::Compare(key, *Traits::GetParent(rhs));
}
// Define accessors using RB_* functions.
- IntrusiveRedBlackTreeNode* InsertImpl(IntrusiveRedBlackTreeNode* node) {
- return RB_INSERT(&impl.root, node, CompareImpl);
+ constexpr IntrusiveRedBlackTreeNode* InsertImpl(IntrusiveRedBlackTreeNode* node) {
+ return freebsd::RB_INSERT(m_impl.m_root, node, CompareImpl);
}
- IntrusiveRedBlackTreeNode* FindImpl(const IntrusiveRedBlackTreeNode* node) const {
- return RB_FIND(const_cast<ImplType::RootType*>(&impl.root),
- const_cast<IntrusiveRedBlackTreeNode*>(node), CompareImpl);
+ constexpr IntrusiveRedBlackTreeNode* FindImpl(IntrusiveRedBlackTreeNode const* node) const {
+ return freebsd::RB_FIND(const_cast<ImplType::RootType&>(m_impl.m_root),
+ const_cast<IntrusiveRedBlackTreeNode*>(node), CompareImpl);
}
- IntrusiveRedBlackTreeNode* NFindImpl(const IntrusiveRedBlackTreeNode* node) const {
- return RB_NFIND(const_cast<ImplType::RootType*>(&impl.root),
- const_cast<IntrusiveRedBlackTreeNode*>(node), CompareImpl);
+ constexpr IntrusiveRedBlackTreeNode* NFindImpl(IntrusiveRedBlackTreeNode const* node) const {
+ return freebsd::RB_NFIND(const_cast<ImplType::RootType&>(m_impl.m_root),
+ const_cast<IntrusiveRedBlackTreeNode*>(node), CompareImpl);
}
- IntrusiveRedBlackTreeNode* FindLightImpl(const_light_pointer lelm) const {
- return RB_FIND_LIGHT(const_cast<ImplType::RootType*>(&impl.root),
- static_cast<const void*>(lelm), LightCompareImpl);
+ constexpr IntrusiveRedBlackTreeNode* FindKeyImpl(const_key_reference key) const {
+ return freebsd::RB_FIND_KEY(const_cast<ImplType::RootType&>(m_impl.m_root), key,
+ CompareKeyImpl);
}
- IntrusiveRedBlackTreeNode* NFindLightImpl(const_light_pointer lelm) const {
- return RB_NFIND_LIGHT(const_cast<ImplType::RootType*>(&impl.root),
- static_cast<const void*>(lelm), LightCompareImpl);
+ constexpr IntrusiveRedBlackTreeNode* NFindKeyImpl(const_key_reference key) const {
+ return freebsd::RB_NFIND_KEY(const_cast<ImplType::RootType&>(m_impl.m_root), key,
+ CompareKeyImpl);
+ }
+
+ constexpr IntrusiveRedBlackTreeNode* FindExistingImpl(
+ IntrusiveRedBlackTreeNode const* node) const {
+ return freebsd::RB_FIND_EXISTING(const_cast<ImplType::RootType&>(m_impl.m_root),
+ const_cast<IntrusiveRedBlackTreeNode*>(node), CompareImpl);
+ }
+
+ constexpr IntrusiveRedBlackTreeNode* FindExistingKeyImpl(const_key_reference key) const {
+ return freebsd::RB_FIND_EXISTING_KEY(const_cast<ImplType::RootType&>(m_impl.m_root), key,
+ CompareKeyImpl);
}
public:
constexpr IntrusiveRedBlackTree() = default;
// Iterator accessors.
- iterator begin() {
- return iterator(this->impl.begin());
+ constexpr iterator begin() {
+ return iterator(m_impl.begin());
}
- const_iterator begin() const {
- return const_iterator(this->impl.begin());
+ constexpr const_iterator begin() const {
+ return const_iterator(m_impl.begin());
}
- iterator end() {
- return iterator(this->impl.end());
+ constexpr iterator end() {
+ return iterator(m_impl.end());
}
- const_iterator end() const {
- return const_iterator(this->impl.end());
+ constexpr const_iterator end() const {
+ return const_iterator(m_impl.end());
}
- const_iterator cbegin() const {
+ constexpr const_iterator cbegin() const {
return this->begin();
}
- const_iterator cend() const {
+ constexpr const_iterator cend() const {
return this->end();
}
- iterator iterator_to(reference ref) {
- return iterator(this->impl.iterator_to(*Traits::GetNode(std::addressof(ref))));
+ constexpr iterator iterator_to(reference ref) {
+ return iterator(m_impl.iterator_to(*Traits::GetNode(std::addressof(ref))));
}
- const_iterator iterator_to(const_reference ref) const {
- return const_iterator(this->impl.iterator_to(*Traits::GetNode(std::addressof(ref))));
+ constexpr const_iterator iterator_to(const_reference ref) const {
+ return const_iterator(m_impl.iterator_to(*Traits::GetNode(std::addressof(ref))));
}
// Content management.
- bool empty() const {
- return this->impl.empty();
+ constexpr bool empty() const {
+ return m_impl.empty();
}
- reference back() {
- return *Traits::GetParent(std::addressof(this->impl.back()));
+ constexpr reference back() {
+ return *Traits::GetParent(std::addressof(m_impl.back()));
}
- const_reference back() const {
- return *Traits::GetParent(std::addressof(this->impl.back()));
+ constexpr const_reference back() const {
+ return *Traits::GetParent(std::addressof(m_impl.back()));
}
- reference front() {
- return *Traits::GetParent(std::addressof(this->impl.front()));
+ constexpr reference front() {
+ return *Traits::GetParent(std::addressof(m_impl.front()));
}
- const_reference front() const {
- return *Traits::GetParent(std::addressof(this->impl.front()));
+ constexpr const_reference front() const {
+ return *Traits::GetParent(std::addressof(m_impl.front()));
}
- iterator erase(iterator it) {
- return iterator(this->impl.erase(it.GetImplIterator()));
+ constexpr iterator erase(iterator it) {
+ return iterator(m_impl.erase(it.GetImplIterator()));
}
- iterator insert(reference ref) {
+ constexpr iterator insert(reference ref) {
ImplType::pointer node = Traits::GetNode(std::addressof(ref));
this->InsertImpl(node);
return iterator(node);
}
- iterator find(const_reference ref) const {
+ constexpr iterator find(const_reference ref) const {
return iterator(this->FindImpl(Traits::GetNode(std::addressof(ref))));
}
- iterator nfind(const_reference ref) const {
+ constexpr iterator nfind(const_reference ref) const {
return iterator(this->NFindImpl(Traits::GetNode(std::addressof(ref))));
}
- iterator find_light(const_light_reference ref) const {
- return iterator(this->FindLightImpl(std::addressof(ref)));
+ constexpr iterator find_key(const_key_reference ref) const {
+ return iterator(this->FindKeyImpl(ref));
+ }
+
+ constexpr iterator nfind_key(const_key_reference ref) const {
+ return iterator(this->NFindKeyImpl(ref));
+ }
+
+ constexpr iterator find_existing(const_reference ref) const {
+ return iterator(this->FindExistingImpl(Traits::GetNode(std::addressof(ref))));
}
- iterator nfind_light(const_light_reference ref) const {
- return iterator(this->NFindLightImpl(std::addressof(ref)));
+ constexpr iterator find_existing_key(const_key_reference ref) const {
+ return iterator(this->FindExistingKeyImpl(ref));
}
};
-template <auto T, class Derived = impl::GetParentType<T>>
+template <auto T, class Derived = Common::impl::GetParentType<T>>
class IntrusiveRedBlackTreeMemberTraits;
template <class Parent, IntrusiveRedBlackTreeNode Parent::*Member, class Derived>
@@ -498,19 +525,16 @@ private:
return std::addressof(parent->*Member);
}
- static constexpr Derived* GetParent(IntrusiveRedBlackTreeNode* node) {
- return GetParentPointer<Member, Derived>(node);
+ static Derived* GetParent(IntrusiveRedBlackTreeNode* node) {
+ return Common::GetParentPointer<Member, Derived>(node);
}
- static constexpr Derived const* GetParent(const IntrusiveRedBlackTreeNode* node) {
- return GetParentPointer<Member, Derived>(node);
+ static Derived const* GetParent(IntrusiveRedBlackTreeNode const* node) {
+ return Common::GetParentPointer<Member, Derived>(node);
}
-
-private:
- static constexpr TypedStorage<Derived> DerivedStorage = {};
};
-template <auto T, class Derived = impl::GetParentType<T>>
+template <auto T, class Derived = Common::impl::GetParentType<T>>
class IntrusiveRedBlackTreeMemberTraitsDeferredAssert;
template <class Parent, IntrusiveRedBlackTreeNode Parent::*Member, class Derived>
@@ -521,11 +545,6 @@ public:
IntrusiveRedBlackTree<Derived, IntrusiveRedBlackTreeMemberTraitsDeferredAssert, Comparator>;
using TreeTypeImpl = impl::IntrusiveRedBlackTreeImpl;
- static constexpr bool IsValid() {
- TypedStorage<Derived> DerivedStorage = {};
- return GetParent(GetNode(GetPointer(DerivedStorage))) == GetPointer(DerivedStorage);
- }
-
private:
template <class, class, class>
friend class IntrusiveRedBlackTree;
@@ -540,30 +559,36 @@ private:
return std::addressof(parent->*Member);
}
- static constexpr Derived* GetParent(IntrusiveRedBlackTreeNode* node) {
- return GetParentPointer<Member, Derived>(node);
+ static Derived* GetParent(IntrusiveRedBlackTreeNode* node) {
+ return Common::GetParentPointer<Member, Derived>(node);
}
- static constexpr Derived const* GetParent(const IntrusiveRedBlackTreeNode* node) {
- return GetParentPointer<Member, Derived>(node);
+ static Derived const* GetParent(IntrusiveRedBlackTreeNode const* node) {
+ return Common::GetParentPointer<Member, Derived>(node);
}
};
template <class Derived>
-class IntrusiveRedBlackTreeBaseNode : public IntrusiveRedBlackTreeNode {
+class alignas(void*) IntrusiveRedBlackTreeBaseNode : public IntrusiveRedBlackTreeNode {
public:
+ using IntrusiveRedBlackTreeNode::IntrusiveRedBlackTreeNode;
+
constexpr Derived* GetPrev() {
- return static_cast<Derived*>(impl::IntrusiveRedBlackTreeImpl::GetPrev(this));
+ return static_cast<Derived*>(static_cast<IntrusiveRedBlackTreeBaseNode*>(
+ impl::IntrusiveRedBlackTreeImpl::GetPrev(this)));
}
constexpr const Derived* GetPrev() const {
- return static_cast<const Derived*>(impl::IntrusiveRedBlackTreeImpl::GetPrev(this));
+ return static_cast<const Derived*>(static_cast<const IntrusiveRedBlackTreeBaseNode*>(
+ impl::IntrusiveRedBlackTreeImpl::GetPrev(this)));
}
constexpr Derived* GetNext() {
- return static_cast<Derived*>(impl::IntrusiveRedBlackTreeImpl::GetNext(this));
+ return static_cast<Derived*>(static_cast<IntrusiveRedBlackTreeBaseNode*>(
+ impl::IntrusiveRedBlackTreeImpl::GetNext(this)));
}
constexpr const Derived* GetNext() const {
- return static_cast<const Derived*>(impl::IntrusiveRedBlackTreeImpl::GetNext(this));
+ return static_cast<const Derived*>(static_cast<const IntrusiveRedBlackTreeBaseNode*>(
+ impl::IntrusiveRedBlackTreeImpl::GetNext(this)));
}
};
@@ -581,19 +606,22 @@ private:
friend class impl::IntrusiveRedBlackTreeImpl;
static constexpr IntrusiveRedBlackTreeNode* GetNode(Derived* parent) {
- return static_cast<IntrusiveRedBlackTreeNode*>(parent);
+ return static_cast<IntrusiveRedBlackTreeNode*>(
+ static_cast<IntrusiveRedBlackTreeBaseNode<Derived>*>(parent));
}
static constexpr IntrusiveRedBlackTreeNode const* GetNode(Derived const* parent) {
- return static_cast<const IntrusiveRedBlackTreeNode*>(parent);
+ return static_cast<const IntrusiveRedBlackTreeNode*>(
+ static_cast<const IntrusiveRedBlackTreeBaseNode<Derived>*>(parent));
}
static constexpr Derived* GetParent(IntrusiveRedBlackTreeNode* node) {
- return static_cast<Derived*>(node);
+ return static_cast<Derived*>(static_cast<IntrusiveRedBlackTreeBaseNode<Derived>*>(node));
}
- static constexpr Derived const* GetParent(const IntrusiveRedBlackTreeNode* node) {
- return static_cast<const Derived*>(node);
+ static constexpr Derived const* GetParent(IntrusiveRedBlackTreeNode const* node) {
+ return static_cast<const Derived*>(
+ static_cast<const IntrusiveRedBlackTreeBaseNode<Derived>*>(node));
}
};
diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp
index f1c9ed6c4..b3793106d 100644
--- a/src/common/logging/backend.cpp
+++ b/src/common/logging/backend.cpp
@@ -5,10 +5,8 @@
#include <atomic>
#include <chrono>
#include <climits>
-#include <exception>
#include <stop_token>
#include <thread>
-#include <vector>
#include <fmt/format.h>
@@ -276,9 +274,9 @@ private:
ColorConsoleBackend color_console_backend{};
FileBackend file_backend;
- std::jthread backend_thread;
MPSCQueue<Entry, true> message_queue{};
std::chrono::steady_clock::time_point time_origin{std::chrono::steady_clock::now()};
+ std::jthread backend_thread;
};
} // namespace
diff --git a/src/common/logging/backend.h b/src/common/logging/backend.h
index bf785f402..a0e80fe3c 100644
--- a/src/common/logging/backend.h
+++ b/src/common/logging/backend.h
@@ -4,7 +4,6 @@
#pragma once
-#include <filesystem>
#include "common/logging/filter.h"
namespace Common::Log {
diff --git a/src/common/logging/filter.cpp b/src/common/logging/filter.cpp
index 4afc1369a..4acbff649 100644
--- a/src/common/logging/filter.cpp
+++ b/src/common/logging/filter.cpp
@@ -101,6 +101,7 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
SUB(Service, GRC) \
SUB(Service, HID) \
SUB(Service, IRS) \
+ SUB(Service, JIT) \
SUB(Service, LBL) \
SUB(Service, LDN) \
SUB(Service, LDR) \
@@ -119,6 +120,7 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
SUB(Service, NPNS) \
SUB(Service, NS) \
SUB(Service, NVDRV) \
+ SUB(Service, NVFlinger) \
SUB(Service, OLSC) \
SUB(Service, PCIE) \
SUB(Service, PCTL) \
diff --git a/src/common/logging/filter.h b/src/common/logging/filter.h
index 1a3074e04..29419f051 100644
--- a/src/common/logging/filter.h
+++ b/src/common/logging/filter.h
@@ -7,7 +7,6 @@
#include <array>
#include <chrono>
#include <cstddef>
-#include <string_view>
#include "common/logging/log.h"
namespace Common::Log {
diff --git a/src/common/logging/text_formatter.cpp b/src/common/logging/text_formatter.cpp
index 10b2281db..b2cad58d8 100644
--- a/src/common/logging/text_formatter.cpp
+++ b/src/common/logging/text_formatter.cpp
@@ -10,12 +10,10 @@
#endif
#include "common/assert.h"
-#include "common/common_funcs.h"
#include "common/logging/filter.h"
#include "common/logging/log.h"
#include "common/logging/log_entry.h"
#include "common/logging/text_formatter.h"
-#include "common/string_util.h"
namespace Common::Log {
diff --git a/src/common/logging/text_formatter.h b/src/common/logging/text_formatter.h
index 171e74cfe..92c0bf0c5 100644
--- a/src/common/logging/text_formatter.h
+++ b/src/common/logging/text_formatter.h
@@ -4,7 +4,6 @@
#pragma once
-#include <cstddef>
#include <string>
namespace Common::Log {
diff --git a/src/common/logging/types.h b/src/common/logging/types.h
index 2b6e4daa7..99c15fa96 100644
--- a/src/common/logging/types.h
+++ b/src/common/logging/types.h
@@ -69,6 +69,7 @@ enum class Class : u8 {
Service_GRC, ///< The game recording service
Service_HID, ///< The HID (Human interface device) service
Service_IRS, ///< The IRS service
+ Service_JIT, ///< The JIT service
Service_LBL, ///< The LBL (LCD backlight) service
Service_LDN, ///< The LDN (Local domain network) service
Service_LDR, ///< The loader service
@@ -87,6 +88,7 @@ enum class Class : u8 {
Service_NPNS, ///< The NPNS service
Service_NS, ///< The NS services
Service_NVDRV, ///< The NVDRV (Nvidia driver) service
+ Service_NVFlinger, ///< The NVFlinger service
Service_OLSC, ///< The OLSC service
Service_PCIE, ///< The PCIe service
Service_PCTL, ///< The PCTL (Parental control) service
diff --git a/src/common/math_util.h b/src/common/math_util.h
index 510c4e56d..54485bf53 100644
--- a/src/common/math_util.h
+++ b/src/common/math_util.h
@@ -4,6 +4,7 @@
#pragma once
+#include <algorithm>
#include <cstdlib>
#include <type_traits>
@@ -20,10 +21,32 @@ struct Rectangle {
constexpr Rectangle() = default;
+ constexpr Rectangle(T width, T height) : right(width), bottom(height) {}
+
constexpr Rectangle(T left_, T top_, T right_, T bottom_)
: left(left_), top(top_), right(right_), bottom(bottom_) {}
- [[nodiscard]] T GetWidth() const {
+ [[nodiscard]] constexpr T Left() const {
+ return left;
+ }
+
+ [[nodiscard]] constexpr T Top() const {
+ return top;
+ }
+
+ [[nodiscard]] constexpr T Right() const {
+ return right;
+ }
+
+ [[nodiscard]] constexpr T Bottom() const {
+ return bottom;
+ }
+
+ [[nodiscard]] constexpr bool IsEmpty() const {
+ return (GetWidth() <= 0) || (GetHeight() <= 0);
+ }
+
+ [[nodiscard]] constexpr T GetWidth() const {
if constexpr (std::is_floating_point_v<T>) {
return std::abs(right - left);
} else {
@@ -31,7 +54,7 @@ struct Rectangle {
}
}
- [[nodiscard]] T GetHeight() const {
+ [[nodiscard]] constexpr T GetHeight() const {
if constexpr (std::is_floating_point_v<T>) {
return std::abs(bottom - top);
} else {
@@ -39,18 +62,35 @@ struct Rectangle {
}
}
- [[nodiscard]] Rectangle<T> TranslateX(const T x) const {
+ [[nodiscard]] constexpr Rectangle<T> TranslateX(const T x) const {
return Rectangle{left + x, top, right + x, bottom};
}
- [[nodiscard]] Rectangle<T> TranslateY(const T y) const {
+ [[nodiscard]] constexpr Rectangle<T> TranslateY(const T y) const {
return Rectangle{left, top + y, right, bottom + y};
}
- [[nodiscard]] Rectangle<T> Scale(const float s) const {
+ [[nodiscard]] constexpr Rectangle<T> Scale(const float s) const {
return Rectangle{left, top, static_cast<T>(static_cast<float>(left + GetWidth()) * s),
static_cast<T>(static_cast<float>(top + GetHeight()) * s)};
}
+
+ [[nodiscard]] constexpr bool operator==(const Rectangle<T>& rhs) const {
+ return (left == rhs.left) && (top == rhs.top) && (right == rhs.right) &&
+ (bottom == rhs.bottom);
+ }
+
+ [[nodiscard]] constexpr bool operator!=(const Rectangle<T>& rhs) const {
+ return !operator==(rhs);
+ }
+
+ [[nodiscard]] constexpr bool Intersect(const Rectangle<T>& with, Rectangle<T>* result) const {
+ result->left = std::max(left, with.left);
+ result->top = std::max(top, with.top);
+ result->right = std::min(right, with.right);
+ result->bottom = std::min(bottom, with.bottom);
+ return !result->IsEmpty();
+ }
};
template <typename T>
diff --git a/src/common/memory_detect.cpp b/src/common/memory_detect.cpp
index 8cff6ec37..7a75a5ff4 100644
--- a/src/common/memory_detect.cpp
+++ b/src/common/memory_detect.cpp
@@ -70,4 +70,4 @@ const MemoryInfo& GetMemInfo() {
return mem_info;
}
-} // namespace Common \ No newline at end of file
+} // namespace Common
diff --git a/src/common/nvidia_flags.cpp b/src/common/nvidia_flags.cpp
index d1afd1f1d..c732c233e 100644
--- a/src/common/nvidia_flags.cpp
+++ b/src/common/nvidia_flags.cpp
@@ -6,7 +6,6 @@
#include <fmt/format.h>
-#include "common/fs/file.h"
#include "common/fs/fs.h"
#include "common/fs/path_util.h"
#include "common/nvidia_flags.h"
diff --git a/src/common/page_table.h b/src/common/page_table.h
index 82d91e9f3..13f4b44c0 100644
--- a/src/common/page_table.h
+++ b/src/common/page_table.h
@@ -5,7 +5,6 @@
#pragma once
#include <atomic>
-#include <tuple>
#include "common/common_types.h"
#include "common/virtual_buffer.h"
diff --git a/src/common/parent_of_member.h b/src/common/parent_of_member.h
index 58c70b0e7..ad075615b 100644
--- a/src/common/parent_of_member.h
+++ b/src/common/parent_of_member.h
@@ -7,7 +7,6 @@
#include <type_traits>
#include "common/assert.h"
-#include "common/common_types.h"
namespace Common {
namespace detail {
diff --git a/src/common/ring_buffer.h b/src/common/ring_buffer.h
index 4a8d09806..db6aa6b95 100644
--- a/src/common/ring_buffer.h
+++ b/src/common/ring_buffer.h
@@ -12,7 +12,6 @@
#include <new>
#include <type_traits>
#include <vector>
-#include "common/common_types.h"
namespace Common {
diff --git a/src/common/settings.h b/src/common/settings.h
index a37d83fb3..3b7be63b3 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -38,6 +38,7 @@ enum class CPUAccuracy : u32 {
Auto = 0,
Accurate = 1,
Unsafe = 2,
+ Paranoid = 3,
};
enum class FullscreenMode : u32 {
@@ -470,7 +471,7 @@ struct Values {
// Cpu
RangedSetting<CPUAccuracy> cpu_accuracy{CPUAccuracy::Auto, CPUAccuracy::Auto,
- CPUAccuracy::Unsafe, "cpu_accuracy"};
+ CPUAccuracy::Paranoid, "cpu_accuracy"};
// TODO: remove cpu_accuracy_first_time, migration setting added 8 July 2021
BasicSetting<bool> cpu_accuracy_first_time{true, "cpu_accuracy_first_time"};
BasicSetting<bool> cpu_debug_mode{false, "cpu_debug_mode"};
@@ -589,6 +590,9 @@ struct Values {
BasicSetting<int> touch_from_button_map_index{0, "touch_from_button_map"};
std::vector<TouchFromButtonMap> touch_from_button_maps;
+ BasicSetting<bool> enable_ring_controller{true, "enable_ring_controller"};
+ RingconRaw ringcon_analogs;
+
// Data Storage
BasicSetting<bool> use_virtual_sd{true, "use_virtual_sd"};
BasicSetting<bool> gamecard_inserted{false, "gamecard_inserted"};
diff --git a/src/common/settings_input.h b/src/common/settings_input.h
index 4ff37e186..6f42346bc 100644
--- a/src/common/settings_input.h
+++ b/src/common/settings_input.h
@@ -357,6 +357,7 @@ constexpr int NUM_KEYBOARD_MODS_HID = NumKeyboardMods;
using AnalogsRaw = std::array<std::string, NativeAnalog::NumAnalogs>;
using ButtonsRaw = std::array<std::string, NativeButton::NumButtons>;
using MotionsRaw = std::array<std::string, NativeMotion::NumMotions>;
+using RingconRaw = std::string;
constexpr u32 JOYCON_BODY_NEON_RED = 0xFF3C28;
constexpr u32 JOYCON_BUTTONS_NEON_RED = 0x1E0A0A;
diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp
index 662171138..3695dae4d 100644
--- a/src/common/string_util.cpp
+++ b/src/common/string_util.cpp
@@ -5,11 +5,9 @@
#include <algorithm>
#include <cctype>
#include <codecvt>
-#include <cstdlib>
#include <locale>
#include <sstream>
-#include "common/logging/log.h"
#include "common/string_util.h"
#ifdef _WIN32
diff --git a/src/common/telemetry.cpp b/src/common/telemetry.cpp
index 6241d08b3..67261c55b 100644
--- a/src/common/telemetry.cpp
+++ b/src/common/telemetry.cpp
@@ -4,7 +4,6 @@
#include <algorithm>
#include <cstring>
-#include "common/assert.h"
#include "common/scm_rev.h"
#include "common/telemetry.h"
@@ -55,22 +54,50 @@ void AppendBuildInfo(FieldCollection& fc) {
void AppendCPUInfo(FieldCollection& fc) {
#ifdef ARCHITECTURE_x86_64
- fc.AddField(FieldType::UserSystem, "CPU_Model", Common::GetCPUCaps().cpu_string);
- fc.AddField(FieldType::UserSystem, "CPU_BrandString", Common::GetCPUCaps().brand_string);
- fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_AES", Common::GetCPUCaps().aes);
- fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_AVX", Common::GetCPUCaps().avx);
- fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_AVX2", Common::GetCPUCaps().avx2);
- fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_AVX512", Common::GetCPUCaps().avx512);
- fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_BMI1", Common::GetCPUCaps().bmi1);
- fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_BMI2", Common::GetCPUCaps().bmi2);
- fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_FMA", Common::GetCPUCaps().fma);
- fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_FMA4", Common::GetCPUCaps().fma4);
- fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_SSE", Common::GetCPUCaps().sse);
- fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_SSE2", Common::GetCPUCaps().sse2);
- fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_SSE3", Common::GetCPUCaps().sse3);
- fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_SSSE3", Common::GetCPUCaps().ssse3);
- fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_SSE41", Common::GetCPUCaps().sse4_1);
- fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_SSE42", Common::GetCPUCaps().sse4_2);
+
+ const auto& caps = Common::GetCPUCaps();
+ const auto add_field = [&fc](std::string_view field_name, const auto& field_value) {
+ fc.AddField(FieldType::UserSystem, field_name, field_value);
+ };
+ add_field("CPU_Model", caps.cpu_string);
+ add_field("CPU_BrandString", caps.brand_string);
+
+ add_field("CPU_Extension_x64_SSE", caps.sse);
+ add_field("CPU_Extension_x64_SSE2", caps.sse2);
+ add_field("CPU_Extension_x64_SSE3", caps.sse3);
+ add_field("CPU_Extension_x64_SSSE3", caps.ssse3);
+ add_field("CPU_Extension_x64_SSE41", caps.sse4_1);
+ add_field("CPU_Extension_x64_SSE42", caps.sse4_2);
+
+ add_field("CPU_Extension_x64_AVX", caps.avx);
+ add_field("CPU_Extension_x64_AVX_VNNI", caps.avx_vnni);
+ add_field("CPU_Extension_x64_AVX2", caps.avx2);
+
+ // Skylake-X/SP level AVX512, for compatibility with the previous telemetry field
+ add_field("CPU_Extension_x64_AVX512",
+ caps.avx512f && caps.avx512cd && caps.avx512vl && caps.avx512dq && caps.avx512bw);
+
+ add_field("CPU_Extension_x64_AVX512F", caps.avx512f);
+ add_field("CPU_Extension_x64_AVX512CD", caps.avx512cd);
+ add_field("CPU_Extension_x64_AVX512VL", caps.avx512vl);
+ add_field("CPU_Extension_x64_AVX512DQ", caps.avx512dq);
+ add_field("CPU_Extension_x64_AVX512BW", caps.avx512bw);
+ add_field("CPU_Extension_x64_AVX512BITALG", caps.avx512bitalg);
+ add_field("CPU_Extension_x64_AVX512VBMI", caps.avx512vbmi);
+
+ add_field("CPU_Extension_x64_AES", caps.aes);
+ add_field("CPU_Extension_x64_BMI1", caps.bmi1);
+ add_field("CPU_Extension_x64_BMI2", caps.bmi2);
+ add_field("CPU_Extension_x64_F16C", caps.f16c);
+ add_field("CPU_Extension_x64_FMA", caps.fma);
+ add_field("CPU_Extension_x64_FMA4", caps.fma4);
+ add_field("CPU_Extension_x64_GFNI", caps.gfni);
+ add_field("CPU_Extension_x64_INVARIANT_TSC", caps.invariant_tsc);
+ add_field("CPU_Extension_x64_LZCNT", caps.lzcnt);
+ add_field("CPU_Extension_x64_MOVBE", caps.movbe);
+ add_field("CPU_Extension_x64_PCLMULQDQ", caps.pclmulqdq);
+ add_field("CPU_Extension_x64_POPCNT", caps.popcnt);
+ add_field("CPU_Extension_x64_SHA", caps.sha);
#else
fc.AddField(FieldType::UserSystem, "CPU_Model", "Other");
#endif
diff --git a/src/common/telemetry.h b/src/common/telemetry.h
index 4d632f7eb..f9a824a7d 100644
--- a/src/common/telemetry.h
+++ b/src/common/telemetry.h
@@ -55,8 +55,8 @@ class Field : public FieldInterface {
public:
YUZU_NON_COPYABLE(Field);
- Field(FieldType type_, std::string name_, T value_)
- : name(std::move(name_)), type(type_), value(std::move(value_)) {}
+ Field(FieldType type_, std::string_view name_, T value_)
+ : name(name_), type(type_), value(std::move(value_)) {}
~Field() override = default;
@@ -123,7 +123,7 @@ public:
* @param value Value for the field to add.
*/
template <typename T>
- void AddField(FieldType type, const char* name, T value) {
+ void AddField(FieldType type, std::string_view name, T value) {
return AddField(std::make_unique<Field<T>>(type, name, std::move(value)));
}
diff --git a/src/common/thread.h b/src/common/thread.h
index a8c17c71a..626609372 100644
--- a/src/common/thread.h
+++ b/src/common/thread.h
@@ -17,7 +17,7 @@ namespace Common {
class Event {
public:
void Set() {
- std::lock_guard lk{mutex};
+ std::scoped_lock lk{mutex};
if (!is_set) {
is_set = true;
condvar.notify_one();
diff --git a/src/common/threadsafe_queue.h b/src/common/threadsafe_queue.h
index 2c8c2b90e..7272ac6e8 100644
--- a/src/common/threadsafe_queue.h
+++ b/src/common/threadsafe_queue.h
@@ -52,7 +52,7 @@ public:
// line before cv.wait
// TODO(bunnei): This can be replaced with C++20 waitable atomics when properly supported.
// See discussion on https://github.com/yuzu-emu/yuzu/pull/3173 for details.
- std::lock_guard lock{cv_mutex};
+ std::scoped_lock lock{cv_mutex};
cv.notify_one();
}
@@ -159,7 +159,7 @@ public:
template <typename Arg>
void Push(Arg&& t) {
- std::lock_guard lock{write_lock};
+ std::scoped_lock lock{write_lock};
spsc_queue.Push(t);
}
diff --git a/src/common/tree.h b/src/common/tree.h
index 18faa4a48..28370e343 100644
--- a/src/common/tree.h
+++ b/src/common/tree.h
@@ -43,294 +43,265 @@
* The maximum height of a red-black tree is 2lg (n+1).
*/
-#include "common/assert.h"
+namespace Common::freebsd {
-namespace Common {
+enum class RBColor {
+ RB_BLACK = 0,
+ RB_RED = 1,
+};
+
+#pragma pack(push, 4)
template <typename T>
-class RBHead {
+class RBEntry {
public:
- [[nodiscard]] T* Root() {
- return rbh_root;
- }
+ constexpr RBEntry() = default;
- [[nodiscard]] const T* Root() const {
- return rbh_root;
+ [[nodiscard]] constexpr T* Left() {
+ return m_rbe_left;
}
-
- void SetRoot(T* root) {
- rbh_root = root;
+ [[nodiscard]] constexpr const T* Left() const {
+ return m_rbe_left;
}
- [[nodiscard]] bool IsEmpty() const {
- return Root() == nullptr;
+ constexpr void SetLeft(T* e) {
+ m_rbe_left = e;
}
-private:
- T* rbh_root = nullptr;
-};
-
-enum class EntryColor {
- Black,
- Red,
-};
-
-template <typename T>
-class RBEntry {
-public:
- [[nodiscard]] T* Left() {
- return rbe_left;
+ [[nodiscard]] constexpr T* Right() {
+ return m_rbe_right;
}
-
- [[nodiscard]] const T* Left() const {
- return rbe_left;
+ [[nodiscard]] constexpr const T* Right() const {
+ return m_rbe_right;
}
- void SetLeft(T* left) {
- rbe_left = left;
+ constexpr void SetRight(T* e) {
+ m_rbe_right = e;
}
- [[nodiscard]] T* Right() {
- return rbe_right;
+ [[nodiscard]] constexpr T* Parent() {
+ return m_rbe_parent;
}
-
- [[nodiscard]] const T* Right() const {
- return rbe_right;
+ [[nodiscard]] constexpr const T* Parent() const {
+ return m_rbe_parent;
}
- void SetRight(T* right) {
- rbe_right = right;
+ constexpr void SetParent(T* e) {
+ m_rbe_parent = e;
}
- [[nodiscard]] T* Parent() {
- return rbe_parent;
+ [[nodiscard]] constexpr bool IsBlack() const {
+ return m_rbe_color == RBColor::RB_BLACK;
}
-
- [[nodiscard]] const T* Parent() const {
- return rbe_parent;
+ [[nodiscard]] constexpr bool IsRed() const {
+ return m_rbe_color == RBColor::RB_RED;
}
-
- void SetParent(T* parent) {
- rbe_parent = parent;
+ [[nodiscard]] constexpr RBColor Color() const {
+ return m_rbe_color;
}
- [[nodiscard]] bool IsBlack() const {
- return rbe_color == EntryColor::Black;
+ constexpr void SetColor(RBColor c) {
+ m_rbe_color = c;
}
- [[nodiscard]] bool IsRed() const {
- return rbe_color == EntryColor::Red;
- }
+private:
+ T* m_rbe_left{};
+ T* m_rbe_right{};
+ T* m_rbe_parent{};
+ RBColor m_rbe_color{RBColor::RB_BLACK};
+};
+#pragma pack(pop)
- [[nodiscard]] EntryColor Color() const {
- return rbe_color;
- }
+template <typename T>
+struct CheckRBEntry {
+ static constexpr bool value = false;
+};
+template <typename T>
+struct CheckRBEntry<RBEntry<T>> {
+ static constexpr bool value = true;
+};
- void SetColor(EntryColor color) {
- rbe_color = color;
- }
+template <typename T>
+concept IsRBEntry = CheckRBEntry<T>::value;
+template <typename T>
+concept HasRBEntry = requires(T& t, const T& ct) {
+ { t.GetRBEntry() } -> std::same_as<RBEntry<T>&>;
+ { ct.GetRBEntry() } -> std::same_as<const RBEntry<T>&>;
+};
+
+template <typename T>
+requires HasRBEntry<T>
+class RBHead {
private:
- T* rbe_left = nullptr;
- T* rbe_right = nullptr;
- T* rbe_parent = nullptr;
- EntryColor rbe_color{};
+ T* m_rbh_root = nullptr;
+
+public:
+ [[nodiscard]] constexpr T* Root() {
+ return m_rbh_root;
+ }
+ [[nodiscard]] constexpr const T* Root() const {
+ return m_rbh_root;
+ }
+ constexpr void SetRoot(T* root) {
+ m_rbh_root = root;
+ }
+
+ [[nodiscard]] constexpr bool IsEmpty() const {
+ return this->Root() == nullptr;
+ }
};
-template <typename Node>
-[[nodiscard]] RBEntry<Node>& RB_ENTRY(Node* node) {
- return node->GetEntry();
+template <typename T>
+requires HasRBEntry<T>
+[[nodiscard]] constexpr RBEntry<T>& RB_ENTRY(T* t) {
+ return t->GetRBEntry();
}
-
-template <typename Node>
-[[nodiscard]] const RBEntry<Node>& RB_ENTRY(const Node* node) {
- return node->GetEntry();
+template <typename T>
+requires HasRBEntry<T>
+[[nodiscard]] constexpr const RBEntry<T>& RB_ENTRY(const T* t) {
+ return t->GetRBEntry();
}
-template <typename Node>
-[[nodiscard]] Node* RB_PARENT(Node* node) {
- return RB_ENTRY(node).Parent();
+template <typename T>
+requires HasRBEntry<T>
+[[nodiscard]] constexpr T* RB_LEFT(T* t) {
+ return RB_ENTRY(t).Left();
}
-
-template <typename Node>
-[[nodiscard]] const Node* RB_PARENT(const Node* node) {
- return RB_ENTRY(node).Parent();
+template <typename T>
+requires HasRBEntry<T>
+[[nodiscard]] constexpr const T* RB_LEFT(const T* t) {
+ return RB_ENTRY(t).Left();
}
-template <typename Node>
-void RB_SET_PARENT(Node* node, Node* parent) {
- return RB_ENTRY(node).SetParent(parent);
+template <typename T>
+requires HasRBEntry<T>
+[[nodiscard]] constexpr T* RB_RIGHT(T* t) {
+ return RB_ENTRY(t).Right();
}
-
-template <typename Node>
-[[nodiscard]] Node* RB_LEFT(Node* node) {
- return RB_ENTRY(node).Left();
+template <typename T>
+requires HasRBEntry<T>
+[[nodiscard]] constexpr const T* RB_RIGHT(const T* t) {
+ return RB_ENTRY(t).Right();
}
-template <typename Node>
-[[nodiscard]] const Node* RB_LEFT(const Node* node) {
- return RB_ENTRY(node).Left();
+template <typename T>
+requires HasRBEntry<T>
+[[nodiscard]] constexpr T* RB_PARENT(T* t) {
+ return RB_ENTRY(t).Parent();
}
-
-template <typename Node>
-void RB_SET_LEFT(Node* node, Node* left) {
- return RB_ENTRY(node).SetLeft(left);
+template <typename T>
+requires HasRBEntry<T>
+[[nodiscard]] constexpr const T* RB_PARENT(const T* t) {
+ return RB_ENTRY(t).Parent();
}
-template <typename Node>
-[[nodiscard]] Node* RB_RIGHT(Node* node) {
- return RB_ENTRY(node).Right();
+template <typename T>
+requires HasRBEntry<T>
+constexpr void RB_SET_LEFT(T* t, T* e) {
+ RB_ENTRY(t).SetLeft(e);
}
-
-template <typename Node>
-[[nodiscard]] const Node* RB_RIGHT(const Node* node) {
- return RB_ENTRY(node).Right();
+template <typename T>
+requires HasRBEntry<T>
+constexpr void RB_SET_RIGHT(T* t, T* e) {
+ RB_ENTRY(t).SetRight(e);
}
-
-template <typename Node>
-void RB_SET_RIGHT(Node* node, Node* right) {
- return RB_ENTRY(node).SetRight(right);
+template <typename T>
+requires HasRBEntry<T>
+constexpr void RB_SET_PARENT(T* t, T* e) {
+ RB_ENTRY(t).SetParent(e);
}
-template <typename Node>
-[[nodiscard]] bool RB_IS_BLACK(const Node* node) {
- return RB_ENTRY(node).IsBlack();
+template <typename T>
+requires HasRBEntry<T>
+[[nodiscard]] constexpr bool RB_IS_BLACK(const T* t) {
+ return RB_ENTRY(t).IsBlack();
}
-
-template <typename Node>
-[[nodiscard]] bool RB_IS_RED(const Node* node) {
- return RB_ENTRY(node).IsRed();
+template <typename T>
+requires HasRBEntry<T>
+[[nodiscard]] constexpr bool RB_IS_RED(const T* t) {
+ return RB_ENTRY(t).IsRed();
}
-template <typename Node>
-[[nodiscard]] EntryColor RB_COLOR(const Node* node) {
- return RB_ENTRY(node).Color();
+template <typename T>
+requires HasRBEntry<T>
+[[nodiscard]] constexpr RBColor RB_COLOR(const T* t) {
+ return RB_ENTRY(t).Color();
}
-template <typename Node>
-void RB_SET_COLOR(Node* node, EntryColor color) {
- return RB_ENTRY(node).SetColor(color);
+template <typename T>
+requires HasRBEntry<T>
+constexpr void RB_SET_COLOR(T* t, RBColor c) {
+ RB_ENTRY(t).SetColor(c);
}
-template <typename Node>
-void RB_SET(Node* node, Node* parent) {
- auto& entry = RB_ENTRY(node);
- entry.SetParent(parent);
- entry.SetLeft(nullptr);
- entry.SetRight(nullptr);
- entry.SetColor(EntryColor::Red);
+template <typename T>
+requires HasRBEntry<T>
+constexpr void RB_SET(T* elm, T* parent) {
+ auto& rb_entry = RB_ENTRY(elm);
+ rb_entry.SetParent(parent);
+ rb_entry.SetLeft(nullptr);
+ rb_entry.SetRight(nullptr);
+ rb_entry.SetColor(RBColor::RB_RED);
}
-template <typename Node>
-void RB_SET_BLACKRED(Node* black, Node* red) {
- RB_SET_COLOR(black, EntryColor::Black);
- RB_SET_COLOR(red, EntryColor::Red);
+template <typename T>
+requires HasRBEntry<T>
+constexpr void RB_SET_BLACKRED(T* black, T* red) {
+ RB_SET_COLOR(black, RBColor::RB_BLACK);
+ RB_SET_COLOR(red, RBColor::RB_RED);
}
-template <typename Node>
-void RB_ROTATE_LEFT(RBHead<Node>* head, Node* elm, Node*& tmp) {
+template <typename T>
+requires HasRBEntry<T>
+constexpr void RB_ROTATE_LEFT(RBHead<T>& head, T* elm, T*& tmp) {
tmp = RB_RIGHT(elm);
- RB_SET_RIGHT(elm, RB_LEFT(tmp));
- if (RB_RIGHT(elm) != nullptr) {
+ if (RB_SET_RIGHT(elm, RB_LEFT(tmp)); RB_RIGHT(elm) != nullptr) {
RB_SET_PARENT(RB_LEFT(tmp), elm);
}
- RB_SET_PARENT(tmp, RB_PARENT(elm));
- if (RB_PARENT(tmp) != nullptr) {
+ if (RB_SET_PARENT(tmp, RB_PARENT(elm)); RB_PARENT(tmp) != nullptr) {
if (elm == RB_LEFT(RB_PARENT(elm))) {
RB_SET_LEFT(RB_PARENT(elm), tmp);
} else {
RB_SET_RIGHT(RB_PARENT(elm), tmp);
}
} else {
- head->SetRoot(tmp);
+ head.SetRoot(tmp);
}
RB_SET_LEFT(tmp, elm);
RB_SET_PARENT(elm, tmp);
}
-template <typename Node>
-void RB_ROTATE_RIGHT(RBHead<Node>* head, Node* elm, Node*& tmp) {
+template <typename T>
+requires HasRBEntry<T>
+constexpr void RB_ROTATE_RIGHT(RBHead<T>& head, T* elm, T*& tmp) {
tmp = RB_LEFT(elm);
- RB_SET_LEFT(elm, RB_RIGHT(tmp));
- if (RB_LEFT(elm) != nullptr) {
+ if (RB_SET_LEFT(elm, RB_RIGHT(tmp)); RB_LEFT(elm) != nullptr) {
RB_SET_PARENT(RB_RIGHT(tmp), elm);
}
- RB_SET_PARENT(tmp, RB_PARENT(elm));
- if (RB_PARENT(tmp) != nullptr) {
+ if (RB_SET_PARENT(tmp, RB_PARENT(elm)); RB_PARENT(tmp) != nullptr) {
if (elm == RB_LEFT(RB_PARENT(elm))) {
RB_SET_LEFT(RB_PARENT(elm), tmp);
} else {
RB_SET_RIGHT(RB_PARENT(elm), tmp);
}
} else {
- head->SetRoot(tmp);
+ head.SetRoot(tmp);
}
RB_SET_RIGHT(tmp, elm);
RB_SET_PARENT(elm, tmp);
}
-template <typename Node>
-void RB_INSERT_COLOR(RBHead<Node>* head, Node* elm) {
- Node* parent = nullptr;
- Node* tmp = nullptr;
-
- while ((parent = RB_PARENT(elm)) != nullptr && RB_IS_RED(parent)) {
- Node* gparent = RB_PARENT(parent);
- if (parent == RB_LEFT(gparent)) {
- tmp = RB_RIGHT(gparent);
- if (tmp && RB_IS_RED(tmp)) {
- RB_SET_COLOR(tmp, EntryColor::Black);
- RB_SET_BLACKRED(parent, gparent);
- elm = gparent;
- continue;
- }
-
- if (RB_RIGHT(parent) == elm) {
- RB_ROTATE_LEFT(head, parent, tmp);
- tmp = parent;
- parent = elm;
- elm = tmp;
- }
-
- RB_SET_BLACKRED(parent, gparent);
- RB_ROTATE_RIGHT(head, gparent, tmp);
- } else {
- tmp = RB_LEFT(gparent);
- if (tmp && RB_IS_RED(tmp)) {
- RB_SET_COLOR(tmp, EntryColor::Black);
- RB_SET_BLACKRED(parent, gparent);
- elm = gparent;
- continue;
- }
-
- if (RB_LEFT(parent) == elm) {
- RB_ROTATE_RIGHT(head, parent, tmp);
- tmp = parent;
- parent = elm;
- elm = tmp;
- }
-
- RB_SET_BLACKRED(parent, gparent);
- RB_ROTATE_LEFT(head, gparent, tmp);
- }
- }
-
- RB_SET_COLOR(head->Root(), EntryColor::Black);
-}
-
-template <typename Node>
-void RB_REMOVE_COLOR(RBHead<Node>* head, Node* parent, Node* elm) {
- Node* tmp;
- while ((elm == nullptr || RB_IS_BLACK(elm)) && elm != head->Root() && parent != nullptr) {
+template <typename T>
+requires HasRBEntry<T>
+constexpr void RB_REMOVE_COLOR(RBHead<T>& head, T* parent, T* elm) {
+ T* tmp;
+ while ((elm == nullptr || RB_IS_BLACK(elm)) && elm != head.Root()) {
if (RB_LEFT(parent) == elm) {
tmp = RB_RIGHT(parent);
- if (!tmp) {
- ASSERT_MSG(false, "tmp is invalid!");
- break;
- }
if (RB_IS_RED(tmp)) {
RB_SET_BLACKRED(tmp, parent);
RB_ROTATE_LEFT(head, parent, tmp);
@@ -339,29 +310,29 @@ void RB_REMOVE_COLOR(RBHead<Node>* head, Node* parent, Node* elm) {
if ((RB_LEFT(tmp) == nullptr || RB_IS_BLACK(RB_LEFT(tmp))) &&
(RB_RIGHT(tmp) == nullptr || RB_IS_BLACK(RB_RIGHT(tmp)))) {
- RB_SET_COLOR(tmp, EntryColor::Red);
+ RB_SET_COLOR(tmp, RBColor::RB_RED);
elm = parent;
parent = RB_PARENT(elm);
} else {
if (RB_RIGHT(tmp) == nullptr || RB_IS_BLACK(RB_RIGHT(tmp))) {
- Node* oleft;
+ T* oleft;
if ((oleft = RB_LEFT(tmp)) != nullptr) {
- RB_SET_COLOR(oleft, EntryColor::Black);
+ RB_SET_COLOR(oleft, RBColor::RB_BLACK);
}
- RB_SET_COLOR(tmp, EntryColor::Red);
+ RB_SET_COLOR(tmp, RBColor::RB_RED);
RB_ROTATE_RIGHT(head, tmp, oleft);
tmp = RB_RIGHT(parent);
}
RB_SET_COLOR(tmp, RB_COLOR(parent));
- RB_SET_COLOR(parent, EntryColor::Black);
+ RB_SET_COLOR(parent, RBColor::RB_BLACK);
if (RB_RIGHT(tmp)) {
- RB_SET_COLOR(RB_RIGHT(tmp), EntryColor::Black);
+ RB_SET_COLOR(RB_RIGHT(tmp), RBColor::RB_BLACK);
}
RB_ROTATE_LEFT(head, parent, tmp);
- elm = head->Root();
+ elm = head.Root();
break;
}
} else {
@@ -372,68 +343,56 @@ void RB_REMOVE_COLOR(RBHead<Node>* head, Node* parent, Node* elm) {
tmp = RB_LEFT(parent);
}
- if (!tmp) {
- ASSERT_MSG(false, "tmp is invalid!");
- break;
- }
-
if ((RB_LEFT(tmp) == nullptr || RB_IS_BLACK(RB_LEFT(tmp))) &&
(RB_RIGHT(tmp) == nullptr || RB_IS_BLACK(RB_RIGHT(tmp)))) {
- RB_SET_COLOR(tmp, EntryColor::Red);
+ RB_SET_COLOR(tmp, RBColor::RB_RED);
elm = parent;
parent = RB_PARENT(elm);
} else {
if (RB_LEFT(tmp) == nullptr || RB_IS_BLACK(RB_LEFT(tmp))) {
- Node* oright;
+ T* oright;
if ((oright = RB_RIGHT(tmp)) != nullptr) {
- RB_SET_COLOR(oright, EntryColor::Black);
+ RB_SET_COLOR(oright, RBColor::RB_BLACK);
}
- RB_SET_COLOR(tmp, EntryColor::Red);
+ RB_SET_COLOR(tmp, RBColor::RB_RED);
RB_ROTATE_LEFT(head, tmp, oright);
tmp = RB_LEFT(parent);
}
RB_SET_COLOR(tmp, RB_COLOR(parent));
- RB_SET_COLOR(parent, EntryColor::Black);
+ RB_SET_COLOR(parent, RBColor::RB_BLACK);
if (RB_LEFT(tmp)) {
- RB_SET_COLOR(RB_LEFT(tmp), EntryColor::Black);
+ RB_SET_COLOR(RB_LEFT(tmp), RBColor::RB_BLACK);
}
RB_ROTATE_RIGHT(head, parent, tmp);
- elm = head->Root();
+ elm = head.Root();
break;
}
}
}
if (elm) {
- RB_SET_COLOR(elm, EntryColor::Black);
+ RB_SET_COLOR(elm, RBColor::RB_BLACK);
}
}
-template <typename Node>
-Node* RB_REMOVE(RBHead<Node>* head, Node* elm) {
- Node* child = nullptr;
- Node* parent = nullptr;
- Node* old = elm;
- EntryColor color{};
-
- const auto finalize = [&] {
- if (color == EntryColor::Black) {
- RB_REMOVE_COLOR(head, parent, child);
- }
-
- return old;
- };
+template <typename T>
+requires HasRBEntry<T>
+constexpr T* RB_REMOVE(RBHead<T>& head, T* elm) {
+ T* child = nullptr;
+ T* parent = nullptr;
+ T* old = elm;
+ RBColor color = RBColor::RB_BLACK;
if (RB_LEFT(elm) == nullptr) {
child = RB_RIGHT(elm);
} else if (RB_RIGHT(elm) == nullptr) {
child = RB_LEFT(elm);
} else {
- Node* left;
+ T* left;
elm = RB_RIGHT(elm);
while ((left = RB_LEFT(elm)) != nullptr) {
elm = left;
@@ -446,6 +405,7 @@ Node* RB_REMOVE(RBHead<Node>* head, Node* elm) {
if (child) {
RB_SET_PARENT(child, parent);
}
+
if (parent) {
if (RB_LEFT(parent) == elm) {
RB_SET_LEFT(parent, child);
@@ -453,14 +413,14 @@ Node* RB_REMOVE(RBHead<Node>* head, Node* elm) {
RB_SET_RIGHT(parent, child);
}
} else {
- head->SetRoot(child);
+ head.SetRoot(child);
}
if (RB_PARENT(elm) == old) {
parent = elm;
}
- elm->SetEntry(old->GetEntry());
+ elm->SetRBEntry(old->GetRBEntry());
if (RB_PARENT(old)) {
if (RB_LEFT(RB_PARENT(old)) == old) {
@@ -469,17 +429,24 @@ Node* RB_REMOVE(RBHead<Node>* head, Node* elm) {
RB_SET_RIGHT(RB_PARENT(old), elm);
}
} else {
- head->SetRoot(elm);
+ head.SetRoot(elm);
}
+
RB_SET_PARENT(RB_LEFT(old), elm);
+
if (RB_RIGHT(old)) {
RB_SET_PARENT(RB_RIGHT(old), elm);
}
+
if (parent) {
left = parent;
}
- return finalize();
+ if (color == RBColor::RB_BLACK) {
+ RB_REMOVE_COLOR(head, parent, child);
+ }
+
+ return old;
}
parent = RB_PARENT(elm);
@@ -495,17 +462,69 @@ Node* RB_REMOVE(RBHead<Node>* head, Node* elm) {
RB_SET_RIGHT(parent, child);
}
} else {
- head->SetRoot(child);
+ head.SetRoot(child);
+ }
+
+ if (color == RBColor::RB_BLACK) {
+ RB_REMOVE_COLOR(head, parent, child);
+ }
+
+ return old;
+}
+
+template <typename T>
+requires HasRBEntry<T>
+constexpr void RB_INSERT_COLOR(RBHead<T>& head, T* elm) {
+ T *parent = nullptr, *tmp = nullptr;
+ while ((parent = RB_PARENT(elm)) != nullptr && RB_IS_RED(parent)) {
+ T* gparent = RB_PARENT(parent);
+ if (parent == RB_LEFT(gparent)) {
+ tmp = RB_RIGHT(gparent);
+ if (tmp && RB_IS_RED(tmp)) {
+ RB_SET_COLOR(tmp, RBColor::RB_BLACK);
+ RB_SET_BLACKRED(parent, gparent);
+ elm = gparent;
+ continue;
+ }
+
+ if (RB_RIGHT(parent) == elm) {
+ RB_ROTATE_LEFT(head, parent, tmp);
+ tmp = parent;
+ parent = elm;
+ elm = tmp;
+ }
+
+ RB_SET_BLACKRED(parent, gparent);
+ RB_ROTATE_RIGHT(head, gparent, tmp);
+ } else {
+ tmp = RB_LEFT(gparent);
+ if (tmp && RB_IS_RED(tmp)) {
+ RB_SET_COLOR(tmp, RBColor::RB_BLACK);
+ RB_SET_BLACKRED(parent, gparent);
+ elm = gparent;
+ continue;
+ }
+
+ if (RB_LEFT(parent) == elm) {
+ RB_ROTATE_RIGHT(head, parent, tmp);
+ tmp = parent;
+ parent = elm;
+ elm = tmp;
+ }
+
+ RB_SET_BLACKRED(parent, gparent);
+ RB_ROTATE_LEFT(head, gparent, tmp);
+ }
}
- return finalize();
+ RB_SET_COLOR(head.Root(), RBColor::RB_BLACK);
}
-// Inserts a node into the RB tree
-template <typename Node, typename CompareFunction>
-Node* RB_INSERT(RBHead<Node>* head, Node* elm, CompareFunction cmp) {
- Node* parent = nullptr;
- Node* tmp = head->Root();
+template <typename T, typename Compare>
+requires HasRBEntry<T>
+constexpr T* RB_INSERT(RBHead<T>& head, T* elm, Compare cmp) {
+ T* parent = nullptr;
+ T* tmp = head.Root();
int comp = 0;
while (tmp) {
@@ -529,17 +548,17 @@ Node* RB_INSERT(RBHead<Node>* head, Node* elm, CompareFunction cmp) {
RB_SET_RIGHT(parent, elm);
}
} else {
- head->SetRoot(elm);
+ head.SetRoot(elm);
}
RB_INSERT_COLOR(head, elm);
return nullptr;
}
-// Finds the node with the same key as elm
-template <typename Node, typename CompareFunction>
-Node* RB_FIND(RBHead<Node>* head, Node* elm, CompareFunction cmp) {
- Node* tmp = head->Root();
+template <typename T, typename Compare>
+requires HasRBEntry<T>
+constexpr T* RB_FIND(RBHead<T>& head, T* elm, Compare cmp) {
+ T* tmp = head.Root();
while (tmp) {
const int comp = cmp(elm, tmp);
@@ -555,11 +574,11 @@ Node* RB_FIND(RBHead<Node>* head, Node* elm, CompareFunction cmp) {
return nullptr;
}
-// Finds the first node greater than or equal to the search key
-template <typename Node, typename CompareFunction>
-Node* RB_NFIND(RBHead<Node>* head, Node* elm, CompareFunction cmp) {
- Node* tmp = head->Root();
- Node* res = nullptr;
+template <typename T, typename Compare>
+requires HasRBEntry<T>
+constexpr T* RB_NFIND(RBHead<T>& head, T* elm, Compare cmp) {
+ T* tmp = head.Root();
+ T* res = nullptr;
while (tmp) {
const int comp = cmp(elm, tmp);
@@ -576,13 +595,13 @@ Node* RB_NFIND(RBHead<Node>* head, Node* elm, CompareFunction cmp) {
return res;
}
-// Finds the node with the same key as lelm
-template <typename Node, typename CompareFunction>
-Node* RB_FIND_LIGHT(RBHead<Node>* head, const void* lelm, CompareFunction lcmp) {
- Node* tmp = head->Root();
+template <typename T, typename U, typename Compare>
+requires HasRBEntry<T>
+constexpr T* RB_FIND_KEY(RBHead<T>& head, const U& key, Compare cmp) {
+ T* tmp = head.Root();
while (tmp) {
- const int comp = lcmp(lelm, tmp);
+ const int comp = cmp(key, tmp);
if (comp < 0) {
tmp = RB_LEFT(tmp);
} else if (comp > 0) {
@@ -595,14 +614,14 @@ Node* RB_FIND_LIGHT(RBHead<Node>* head, const void* lelm, CompareFunction lcmp)
return nullptr;
}
-// Finds the first node greater than or equal to the search key
-template <typename Node, typename CompareFunction>
-Node* RB_NFIND_LIGHT(RBHead<Node>* head, const void* lelm, CompareFunction lcmp) {
- Node* tmp = head->Root();
- Node* res = nullptr;
+template <typename T, typename U, typename Compare>
+requires HasRBEntry<T>
+constexpr T* RB_NFIND_KEY(RBHead<T>& head, const U& key, Compare cmp) {
+ T* tmp = head.Root();
+ T* res = nullptr;
while (tmp) {
- const int comp = lcmp(lelm, tmp);
+ const int comp = cmp(key, tmp);
if (comp < 0) {
res = tmp;
tmp = RB_LEFT(tmp);
@@ -616,8 +635,43 @@ Node* RB_NFIND_LIGHT(RBHead<Node>* head, const void* lelm, CompareFunction lcmp)
return res;
}
-template <typename Node>
-Node* RB_NEXT(Node* elm) {
+template <typename T, typename Compare>
+requires HasRBEntry<T>
+constexpr T* RB_FIND_EXISTING(RBHead<T>& head, T* elm, Compare cmp) {
+ T* tmp = head.Root();
+
+ while (true) {
+ const int comp = cmp(elm, tmp);
+ if (comp < 0) {
+ tmp = RB_LEFT(tmp);
+ } else if (comp > 0) {
+ tmp = RB_RIGHT(tmp);
+ } else {
+ return tmp;
+ }
+ }
+}
+
+template <typename T, typename U, typename Compare>
+requires HasRBEntry<T>
+constexpr T* RB_FIND_EXISTING_KEY(RBHead<T>& head, const U& key, Compare cmp) {
+ T* tmp = head.Root();
+
+ while (true) {
+ const int comp = cmp(key, tmp);
+ if (comp < 0) {
+ tmp = RB_LEFT(tmp);
+ } else if (comp > 0) {
+ tmp = RB_RIGHT(tmp);
+ } else {
+ return tmp;
+ }
+ }
+}
+
+template <typename T>
+requires HasRBEntry<T>
+constexpr T* RB_NEXT(T* elm) {
if (RB_RIGHT(elm)) {
elm = RB_RIGHT(elm);
while (RB_LEFT(elm)) {
@@ -636,8 +690,9 @@ Node* RB_NEXT(Node* elm) {
return elm;
}
-template <typename Node>
-Node* RB_PREV(Node* elm) {
+template <typename T>
+requires HasRBEntry<T>
+constexpr T* RB_PREV(T* elm) {
if (RB_LEFT(elm)) {
elm = RB_LEFT(elm);
while (RB_RIGHT(elm)) {
@@ -656,30 +711,32 @@ Node* RB_PREV(Node* elm) {
return elm;
}
-template <typename Node>
-Node* RB_MINMAX(RBHead<Node>* head, bool is_min) {
- Node* tmp = head->Root();
- Node* parent = nullptr;
+template <typename T>
+requires HasRBEntry<T>
+constexpr T* RB_MIN(RBHead<T>& head) {
+ T* tmp = head.Root();
+ T* parent = nullptr;
while (tmp) {
parent = tmp;
- if (is_min) {
- tmp = RB_LEFT(tmp);
- } else {
- tmp = RB_RIGHT(tmp);
- }
+ tmp = RB_LEFT(tmp);
}
return parent;
}
-template <typename Node>
-Node* RB_MIN(RBHead<Node>* head) {
- return RB_MINMAX(head, true);
-}
+template <typename T>
+requires HasRBEntry<T>
+constexpr T* RB_MAX(RBHead<T>& head) {
+ T* tmp = head.Root();
+ T* parent = nullptr;
-template <typename Node>
-Node* RB_MAX(RBHead<Node>* head) {
- return RB_MINMAX(head, false);
+ while (tmp) {
+ parent = tmp;
+ tmp = RB_RIGHT(tmp);
+ }
+
+ return parent;
}
-} // namespace Common
+
+} // namespace Common::freebsd
diff --git a/src/common/uint128.h b/src/common/uint128.h
index 4780b2f9d..ad1b90414 100644
--- a/src/common/uint128.h
+++ b/src/common/uint128.h
@@ -4,7 +4,6 @@
#pragma once
-#include <cstring>
#include <utility>
#ifdef _MSC_VER
@@ -13,6 +12,7 @@
#pragma intrinsic(_umul128)
#pragma intrinsic(_udiv128)
#else
+#include <cstring>
#include <x86intrin.h>
#endif
diff --git a/src/common/uuid.h b/src/common/uuid.h
index fe31e64e6..c450d9e20 100644
--- a/src/common/uuid.h
+++ b/src/common/uuid.h
@@ -7,7 +7,6 @@
#include <array>
#include <functional>
#include <string>
-#include <string_view>
#include "common/common_types.h"
diff --git a/src/common/virtual_buffer.h b/src/common/virtual_buffer.h
index fb1a6f81f..cac4f4895 100644
--- a/src/common/virtual_buffer.h
+++ b/src/common/virtual_buffer.h
@@ -4,7 +4,6 @@
#pragma once
-#include <type_traits>
#include <utility>
namespace Common {
diff --git a/src/common/wall_clock.cpp b/src/common/wall_clock.cpp
index 9acf7551e..f30d91692 100644
--- a/src/common/wall_clock.cpp
+++ b/src/common/wall_clock.cpp
@@ -2,8 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include <cstdint>
-
#include "common/uint128.h"
#include "common/wall_clock.h"
diff --git a/src/common/x64/cpu_detect.cpp b/src/common/x64/cpu_detect.cpp
index fbeacc7e2..f5296b32a 100644
--- a/src/common/x64/cpu_detect.cpp
+++ b/src/common/x64/cpu_detect.cpp
@@ -1,8 +1,11 @@
-// Copyright 2013 Dolphin Emulator Project / 2015 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
+// Copyright 2013 Dolphin Emulator Project / 2015 Citra Emulator Project / 2022 Yuzu Emulator
+// Project Licensed under GPLv2 or any later version Refer to the license.txt file included.
+#include <array>
#include <cstring>
+#include <iterator>
+#include <string_view>
+#include "common/bit_util.h"
#include "common/common_types.h"
#include "common/x64/cpu_detect.h"
@@ -17,7 +20,7 @@
// clang-format on
#endif
-static inline void __cpuidex(int info[4], int function_id, int subfunction_id) {
+static inline void __cpuidex(int info[4], u32 function_id, u32 subfunction_id) {
#if defined(__DragonFly__) || defined(__FreeBSD__)
// Despite the name, this is just do_cpuid() with ECX as second input.
cpuid_count((u_int)function_id, (u_int)subfunction_id, (u_int*)info);
@@ -30,7 +33,7 @@ static inline void __cpuidex(int info[4], int function_id, int subfunction_id) {
#endif
}
-static inline void __cpuid(int info[4], int function_id) {
+static inline void __cpuid(int info[4], u32 function_id) {
return __cpuidex(info, function_id, 0);
}
@@ -45,6 +48,17 @@ static inline u64 _xgetbv(u32 index) {
namespace Common {
+CPUCaps::Manufacturer CPUCaps::ParseManufacturer(std::string_view brand_string) {
+ if (brand_string == "GenuineIntel") {
+ return Manufacturer::Intel;
+ } else if (brand_string == "AuthenticAMD") {
+ return Manufacturer::AMD;
+ } else if (brand_string == "HygonGenuine") {
+ return Manufacturer::Hygon;
+ }
+ return Manufacturer::Unknown;
+}
+
// Detects the various CPU features
static CPUCaps Detect() {
CPUCaps caps = {};
@@ -53,75 +67,74 @@ static CPUCaps Detect() {
// yuzu at all anyway
int cpu_id[4];
- memset(caps.brand_string, 0, sizeof(caps.brand_string));
- // Detect CPU's CPUID capabilities and grab CPU string
+ // Detect CPU's CPUID capabilities and grab manufacturer string
__cpuid(cpu_id, 0x00000000);
- u32 max_std_fn = cpu_id[0]; // EAX
-
- std::memcpy(&caps.brand_string[0], &cpu_id[1], sizeof(int));
- std::memcpy(&caps.brand_string[4], &cpu_id[3], sizeof(int));
- std::memcpy(&caps.brand_string[8], &cpu_id[2], sizeof(int));
- if (cpu_id[1] == 0x756e6547 && cpu_id[2] == 0x6c65746e && cpu_id[3] == 0x49656e69)
- caps.manufacturer = Manufacturer::Intel;
- else if (cpu_id[1] == 0x68747541 && cpu_id[2] == 0x444d4163 && cpu_id[3] == 0x69746e65)
- caps.manufacturer = Manufacturer::AMD;
- else if (cpu_id[1] == 0x6f677948 && cpu_id[2] == 0x656e6975 && cpu_id[3] == 0x6e65476e)
- caps.manufacturer = Manufacturer::Hygon;
- else
- caps.manufacturer = Manufacturer::Unknown;
+ const u32 max_std_fn = cpu_id[0]; // EAX
- __cpuid(cpu_id, 0x80000000);
+ std::memset(caps.brand_string, 0, std::size(caps.brand_string));
+ std::memcpy(&caps.brand_string[0], &cpu_id[1], sizeof(u32));
+ std::memcpy(&caps.brand_string[4], &cpu_id[3], sizeof(u32));
+ std::memcpy(&caps.brand_string[8], &cpu_id[2], sizeof(u32));
+
+ caps.manufacturer = CPUCaps::ParseManufacturer(caps.brand_string);
- u32 max_ex_fn = cpu_id[0];
+ // Set reasonable default cpu string even if brand string not available
+ std::strncpy(caps.cpu_string, caps.brand_string, std::size(caps.brand_string));
- // Set reasonable default brand string even if brand string not available
- strcpy(caps.cpu_string, caps.brand_string);
+ __cpuid(cpu_id, 0x80000000);
+
+ const u32 max_ex_fn = cpu_id[0];
// Detect family and other miscellaneous features
if (max_std_fn >= 1) {
__cpuid(cpu_id, 0x00000001);
- if ((cpu_id[3] >> 25) & 1)
- caps.sse = true;
- if ((cpu_id[3] >> 26) & 1)
- caps.sse2 = true;
- if ((cpu_id[2]) & 1)
- caps.sse3 = true;
- if ((cpu_id[2] >> 9) & 1)
- caps.ssse3 = true;
- if ((cpu_id[2] >> 19) & 1)
- caps.sse4_1 = true;
- if ((cpu_id[2] >> 20) & 1)
- caps.sse4_2 = true;
- if ((cpu_id[2] >> 25) & 1)
- caps.aes = true;
+ caps.sse = Common::Bit<25>(cpu_id[3]);
+ caps.sse2 = Common::Bit<26>(cpu_id[3]);
+ caps.sse3 = Common::Bit<0>(cpu_id[2]);
+ caps.pclmulqdq = Common::Bit<1>(cpu_id[2]);
+ caps.ssse3 = Common::Bit<9>(cpu_id[2]);
+ caps.sse4_1 = Common::Bit<19>(cpu_id[2]);
+ caps.sse4_2 = Common::Bit<20>(cpu_id[2]);
+ caps.movbe = Common::Bit<22>(cpu_id[2]);
+ caps.popcnt = Common::Bit<23>(cpu_id[2]);
+ caps.aes = Common::Bit<25>(cpu_id[2]);
+ caps.f16c = Common::Bit<29>(cpu_id[2]);
// AVX support requires 3 separate checks:
// - Is the AVX bit set in CPUID?
// - Is the XSAVE bit set in CPUID?
// - XGETBV result has the XCR bit set.
- if (((cpu_id[2] >> 28) & 1) && ((cpu_id[2] >> 27) & 1)) {
+ if (Common::Bit<28>(cpu_id[2]) && Common::Bit<27>(cpu_id[2])) {
if ((_xgetbv(_XCR_XFEATURE_ENABLED_MASK) & 0x6) == 0x6) {
caps.avx = true;
- if ((cpu_id[2] >> 12) & 1)
+ if (Common::Bit<12>(cpu_id[2]))
caps.fma = true;
}
}
if (max_std_fn >= 7) {
__cpuidex(cpu_id, 0x00000007, 0x00000000);
- // Can't enable AVX2 unless the XSAVE/XGETBV checks above passed
- if ((cpu_id[1] >> 5) & 1)
- caps.avx2 = caps.avx;
- if ((cpu_id[1] >> 3) & 1)
- caps.bmi1 = true;
- if ((cpu_id[1] >> 8) & 1)
- caps.bmi2 = true;
- // Checks for AVX512F, AVX512CD, AVX512VL, AVX512DQ, AVX512BW (Intel Skylake-X/SP)
- if ((cpu_id[1] >> 16) & 1 && (cpu_id[1] >> 28) & 1 && (cpu_id[1] >> 31) & 1 &&
- (cpu_id[1] >> 17) & 1 && (cpu_id[1] >> 30) & 1) {
- caps.avx512 = caps.avx2;
+ // Can't enable AVX{2,512} unless the XSAVE/XGETBV checks above passed
+ if (caps.avx) {
+ caps.avx2 = Common::Bit<5>(cpu_id[1]);
+ caps.avx512f = Common::Bit<16>(cpu_id[1]);
+ caps.avx512dq = Common::Bit<17>(cpu_id[1]);
+ caps.avx512cd = Common::Bit<28>(cpu_id[1]);
+ caps.avx512bw = Common::Bit<30>(cpu_id[1]);
+ caps.avx512vl = Common::Bit<31>(cpu_id[1]);
+ caps.avx512vbmi = Common::Bit<1>(cpu_id[2]);
+ caps.avx512bitalg = Common::Bit<12>(cpu_id[2]);
}
+
+ caps.bmi1 = Common::Bit<3>(cpu_id[1]);
+ caps.bmi2 = Common::Bit<8>(cpu_id[1]);
+ caps.sha = Common::Bit<29>(cpu_id[1]);
+
+ caps.gfni = Common::Bit<8>(cpu_id[2]);
+
+ __cpuidex(cpu_id, 0x00000007, 0x00000001);
+ caps.avx_vnni = caps.avx && Common::Bit<4>(cpu_id[0]);
}
}
@@ -138,15 +151,13 @@ static CPUCaps Detect() {
if (max_ex_fn >= 0x80000001) {
// Check for more features
__cpuid(cpu_id, 0x80000001);
- if ((cpu_id[2] >> 16) & 1)
- caps.fma4 = true;
+ caps.lzcnt = Common::Bit<5>(cpu_id[2]);
+ caps.fma4 = Common::Bit<16>(cpu_id[2]);
}
if (max_ex_fn >= 0x80000007) {
__cpuid(cpu_id, 0x80000007);
- if (cpu_id[3] & (1 << 8)) {
- caps.invariant_tsc = true;
- }
+ caps.invariant_tsc = Common::Bit<8>(cpu_id[3]);
}
if (max_std_fn >= 0x16) {
diff --git a/src/common/x64/cpu_detect.h b/src/common/x64/cpu_detect.h
index e3b63302e..40c48b132 100644
--- a/src/common/x64/cpu_detect.h
+++ b/src/common/x64/cpu_detect.h
@@ -1,42 +1,65 @@
-// Copyright 2013 Dolphin Emulator Project / 2015 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
+// Copyright 2013 Dolphin Emulator Project / 2015 Citra Emulator Project / 2022 Yuzu Emulator
+// Project Project Licensed under GPLv2 or any later version Refer to the license.txt file included.
#pragma once
-namespace Common {
+#include <string_view>
+#include "common/common_types.h"
-enum class Manufacturer : u32 {
- Intel = 0,
- AMD = 1,
- Hygon = 2,
- Unknown = 3,
-};
+namespace Common {
/// x86/x64 CPU capabilities that may be detected by this module
struct CPUCaps {
+
+ enum class Manufacturer : u8 {
+ Unknown = 0,
+ Intel = 1,
+ AMD = 2,
+ Hygon = 3,
+ };
+
+ static Manufacturer ParseManufacturer(std::string_view brand_string);
+
Manufacturer manufacturer;
- char cpu_string[0x21];
- char brand_string[0x41];
- bool sse;
- bool sse2;
- bool sse3;
- bool ssse3;
- bool sse4_1;
- bool sse4_2;
- bool lzcnt;
- bool avx;
- bool avx2;
- bool avx512;
- bool bmi1;
- bool bmi2;
- bool fma;
- bool fma4;
- bool aes;
- bool invariant_tsc;
+ char brand_string[13];
+
+ char cpu_string[48];
+
u32 base_frequency;
u32 max_frequency;
u32 bus_frequency;
+
+ bool sse : 1;
+ bool sse2 : 1;
+ bool sse3 : 1;
+ bool ssse3 : 1;
+ bool sse4_1 : 1;
+ bool sse4_2 : 1;
+
+ bool avx : 1;
+ bool avx_vnni : 1;
+ bool avx2 : 1;
+ bool avx512f : 1;
+ bool avx512dq : 1;
+ bool avx512cd : 1;
+ bool avx512bw : 1;
+ bool avx512vl : 1;
+ bool avx512vbmi : 1;
+ bool avx512bitalg : 1;
+
+ bool aes : 1;
+ bool bmi1 : 1;
+ bool bmi2 : 1;
+ bool f16c : 1;
+ bool fma : 1;
+ bool fma4 : 1;
+ bool gfni : 1;
+ bool invariant_tsc : 1;
+ bool lzcnt : 1;
+ bool movbe : 1;
+ bool pclmulqdq : 1;
+ bool popcnt : 1;
+ bool sha : 1;
};
/**
diff --git a/src/common/x64/native_clock.cpp b/src/common/x64/native_clock.cpp
index 91b842829..7fd9d22f8 100644
--- a/src/common/x64/native_clock.cpp
+++ b/src/common/x64/native_clock.cpp
@@ -4,33 +4,55 @@
#include <array>
#include <chrono>
-#include <limits>
-#include <mutex>
#include <thread>
#include "common/atomic_ops.h"
#include "common/uint128.h"
#include "common/x64/native_clock.h"
+#ifdef _MSC_VER
+#include <intrin.h>
+#endif
+
namespace Common {
+#ifdef _MSC_VER
+__forceinline static u64 FencedRDTSC() {
+ _mm_lfence();
+ _ReadWriteBarrier();
+ const u64 result = __rdtsc();
+ _mm_lfence();
+ _ReadWriteBarrier();
+ return result;
+}
+#else
+static u64 FencedRDTSC() {
+ u64 result;
+ asm volatile("lfence\n\t"
+ "rdtsc\n\t"
+ "shl $32, %%rdx\n\t"
+ "or %%rdx, %0\n\t"
+ "lfence"
+ : "=a"(result)
+ :
+ : "rdx", "memory", "cc");
+ return result;
+}
+#endif
+
u64 EstimateRDTSCFrequency() {
// Discard the first result measuring the rdtsc.
- _mm_mfence();
- __rdtsc();
+ FencedRDTSC();
std::this_thread::sleep_for(std::chrono::milliseconds{1});
- _mm_mfence();
- __rdtsc();
+ FencedRDTSC();
// Get the current time.
const auto start_time = std::chrono::steady_clock::now();
- _mm_mfence();
- const u64 tsc_start = __rdtsc();
+ const u64 tsc_start = FencedRDTSC();
// Wait for 200 milliseconds.
std::this_thread::sleep_for(std::chrono::milliseconds{200});
const auto end_time = std::chrono::steady_clock::now();
- _mm_mfence();
- const u64 tsc_end = __rdtsc();
+ const u64 tsc_end = FencedRDTSC();
// Calculate differences.
const u64 timer_diff = static_cast<u64>(
std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - start_time).count());
@@ -44,8 +66,7 @@ NativeClock::NativeClock(u64 emulated_cpu_frequency_, u64 emulated_clock_frequen
u64 rtsc_frequency_)
: WallClock(emulated_cpu_frequency_, emulated_clock_frequency_, true), rtsc_frequency{
rtsc_frequency_} {
- _mm_mfence();
- time_point.inner.last_measure = __rdtsc();
+ time_point.inner.last_measure = FencedRDTSC();
time_point.inner.accumulated_ticks = 0U;
ns_rtsc_factor = GetFixedPoint64Factor(NS_RATIO, rtsc_frequency);
us_rtsc_factor = GetFixedPoint64Factor(US_RATIO, rtsc_frequency);
@@ -57,10 +78,10 @@ NativeClock::NativeClock(u64 emulated_cpu_frequency_, u64 emulated_clock_frequen
u64 NativeClock::GetRTSC() {
TimePoint new_time_point{};
TimePoint current_time_point{};
+
+ current_time_point.pack = Common::AtomicLoad128(time_point.pack.data());
do {
- current_time_point.pack = time_point.pack;
- _mm_mfence();
- const u64 current_measure = __rdtsc();
+ const u64 current_measure = FencedRDTSC();
u64 diff = current_measure - current_time_point.inner.last_measure;
diff = diff & ~static_cast<u64>(static_cast<s64>(diff) >> 63); // max(diff, 0)
new_time_point.inner.last_measure = current_measure > current_time_point.inner.last_measure
@@ -68,7 +89,7 @@ u64 NativeClock::GetRTSC() {
: current_time_point.inner.last_measure;
new_time_point.inner.accumulated_ticks = current_time_point.inner.accumulated_ticks + diff;
} while (!Common::AtomicCompareAndSwap(time_point.pack.data(), new_time_point.pack,
- current_time_point.pack));
+ current_time_point.pack, current_time_point.pack));
/// The clock cannot be more precise than the guest timer, remove the lower bits
return new_time_point.inner.accumulated_ticks & inaccuracy_mask;
}
@@ -77,13 +98,13 @@ void NativeClock::Pause(bool is_paused) {
if (!is_paused) {
TimePoint current_time_point{};
TimePoint new_time_point{};
+
+ current_time_point.pack = Common::AtomicLoad128(time_point.pack.data());
do {
- current_time_point.pack = time_point.pack;
new_time_point.pack = current_time_point.pack;
- _mm_mfence();
- new_time_point.inner.last_measure = __rdtsc();
+ new_time_point.inner.last_measure = FencedRDTSC();
} while (!Common::AtomicCompareAndSwap(time_point.pack.data(), new_time_point.pack,
- current_time_point.pack));
+ current_time_point.pack, current_time_point.pack));
}
}
diff --git a/src/common/x64/native_clock.h b/src/common/x64/native_clock.h
index 7cbd400d2..2c3082ea0 100644
--- a/src/common/x64/native_clock.h
+++ b/src/common/x64/native_clock.h
@@ -4,8 +4,6 @@
#pragma once
-#include <optional>
-
#include "common/wall_clock.h"
namespace Common {