mirror of
https://git.suyu.dev/suyu/suyu
synced 2024-12-26 11:22:33 -06:00
Merge pull request #11253 from liamwhite/i-hate-this-toolchain
general: fix apple clang build
This commit is contained in:
commit
640f7cd945
5 changed files with 81 additions and 73 deletions
|
@ -1,7 +1,9 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
#include "common/settings_common.h"
|
#include "common/settings_common.h"
|
||||||
|
|
||||||
namespace Settings {
|
namespace Settings {
|
||||||
|
|
|
@ -12,8 +12,8 @@ namespace Settings {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct EnumMetadata {
|
struct EnumMetadata {
|
||||||
static constexpr std::vector<std::pair<std::string, T>> Canonicalizations();
|
static std::vector<std::pair<std::string, T>> Canonicalizations();
|
||||||
static constexpr u32 Index();
|
static u32 Index();
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PAIR_45(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_46(N, __VA_ARGS__))
|
#define PAIR_45(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_46(N, __VA_ARGS__))
|
||||||
|
@ -66,11 +66,11 @@ struct EnumMetadata {
|
||||||
#define ENUM(NAME, ...) \
|
#define ENUM(NAME, ...) \
|
||||||
enum class NAME : u32 { __VA_ARGS__ }; \
|
enum class NAME : u32 { __VA_ARGS__ }; \
|
||||||
template <> \
|
template <> \
|
||||||
constexpr std::vector<std::pair<std::string, NAME>> EnumMetadata<NAME>::Canonicalizations() { \
|
inline std::vector<std::pair<std::string, NAME>> EnumMetadata<NAME>::Canonicalizations() { \
|
||||||
return {PAIR(NAME, __VA_ARGS__)}; \
|
return {PAIR(NAME, __VA_ARGS__)}; \
|
||||||
} \
|
} \
|
||||||
template <> \
|
template <> \
|
||||||
constexpr u32 EnumMetadata<NAME>::Index() { \
|
inline u32 EnumMetadata<NAME>::Index() { \
|
||||||
return __COUNTER__; \
|
return __COUNTER__; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ enum class AudioEngine : u32 {
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
constexpr std::vector<std::pair<std::string, AudioEngine>>
|
inline std::vector<std::pair<std::string, AudioEngine>>
|
||||||
EnumMetadata<AudioEngine>::Canonicalizations() {
|
EnumMetadata<AudioEngine>::Canonicalizations() {
|
||||||
return {
|
return {
|
||||||
{"auto", AudioEngine::Auto},
|
{"auto", AudioEngine::Auto},
|
||||||
|
@ -96,7 +96,7 @@ EnumMetadata<AudioEngine>::Canonicalizations() {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
constexpr u32 EnumMetadata<AudioEngine>::Index() {
|
inline u32 EnumMetadata<AudioEngine>::Index() {
|
||||||
// This is just a sufficiently large number that is more than the number of other enums declared
|
// This is just a sufficiently large number that is more than the number of other enums declared
|
||||||
// here
|
// here
|
||||||
return 100;
|
return 100;
|
||||||
|
@ -147,7 +147,7 @@ ENUM(AntiAliasing, None, Fxaa, Smaa, MaxEnum);
|
||||||
ENUM(AspectRatio, R16_9, R4_3, R21_9, R16_10, Stretch);
|
ENUM(AspectRatio, R16_9, R4_3, R21_9, R16_10, Stretch);
|
||||||
|
|
||||||
template <typename Type>
|
template <typename Type>
|
||||||
constexpr std::string CanonicalizeEnum(Type id) {
|
inline std::string CanonicalizeEnum(Type id) {
|
||||||
const auto group = EnumMetadata<Type>::Canonicalizations();
|
const auto group = EnumMetadata<Type>::Canonicalizations();
|
||||||
for (auto& [name, value] : group) {
|
for (auto& [name, value] : group) {
|
||||||
if (value == id) {
|
if (value == id) {
|
||||||
|
@ -158,7 +158,7 @@ constexpr std::string CanonicalizeEnum(Type id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Type>
|
template <typename Type>
|
||||||
constexpr Type ToEnum(const std::string& canonicalization) {
|
inline Type ToEnum(const std::string& canonicalization) {
|
||||||
const auto group = EnumMetadata<Type>::Canonicalizations();
|
const auto group = EnumMetadata<Type>::Canonicalizations();
|
||||||
for (auto& [name, value] : group) {
|
for (auto& [name, value] : group) {
|
||||||
if (name == canonicalization) {
|
if (name == canonicalization) {
|
||||||
|
|
|
@ -190,7 +190,7 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] std::string constexpr Canonicalize() const override final {
|
[[nodiscard]] std::string Canonicalize() const override final {
|
||||||
if constexpr (std::is_enum_v<Type>) {
|
if constexpr (std::is_enum_v<Type>) {
|
||||||
return CanonicalizeEnum(this->GetValue());
|
return CanonicalizeEnum(this->GetValue());
|
||||||
} else {
|
} else {
|
||||||
|
@ -256,11 +256,11 @@ public:
|
||||||
* @param runtime_modifiable_ Suggests whether this is modifiable while a guest is loaded
|
* @param runtime_modifiable_ Suggests whether this is modifiable while a guest is loaded
|
||||||
* @param other_setting_ A second Setting to associate to this one in metadata
|
* @param other_setting_ A second Setting to associate to this one in metadata
|
||||||
*/
|
*/
|
||||||
|
template <typename T = BasicSetting>
|
||||||
explicit SwitchableSetting(Linkage& linkage, const Type& default_val, const std::string& name,
|
explicit SwitchableSetting(Linkage& linkage, const Type& default_val, const std::string& name,
|
||||||
Category category_, u32 specialization_ = Specialization::Default,
|
Category category_, u32 specialization_ = Specialization::Default,
|
||||||
bool save_ = true, bool runtime_modifiable_ = false,
|
bool save_ = true, bool runtime_modifiable_ = false,
|
||||||
BasicSetting* other_setting_ = nullptr)
|
typename std::enable_if<!ranged, T*>::type other_setting_ = nullptr)
|
||||||
requires(!ranged)
|
|
||||||
: Setting<Type, false>{
|
: Setting<Type, false>{
|
||||||
linkage, default_val, name, category_, specialization_,
|
linkage, default_val, name, category_, specialization_,
|
||||||
save_, runtime_modifiable_, other_setting_} {
|
save_, runtime_modifiable_, other_setting_} {
|
||||||
|
@ -282,12 +282,12 @@ public:
|
||||||
* @param runtime_modifiable_ Suggests whether this is modifiable while a guest is loaded
|
* @param runtime_modifiable_ Suggests whether this is modifiable while a guest is loaded
|
||||||
* @param other_setting_ A second Setting to associate to this one in metadata
|
* @param other_setting_ A second Setting to associate to this one in metadata
|
||||||
*/
|
*/
|
||||||
|
template <typename T = BasicSetting>
|
||||||
explicit SwitchableSetting(Linkage& linkage, const Type& default_val, const Type& min_val,
|
explicit SwitchableSetting(Linkage& linkage, const Type& default_val, const Type& min_val,
|
||||||
const Type& max_val, const std::string& name, Category category_,
|
const Type& max_val, const std::string& name, Category category_,
|
||||||
u32 specialization_ = Specialization::Default, bool save_ = true,
|
u32 specialization_ = Specialization::Default, bool save_ = true,
|
||||||
bool runtime_modifiable_ = false,
|
bool runtime_modifiable_ = false,
|
||||||
BasicSetting* other_setting_ = nullptr)
|
typename std::enable_if<ranged, T*>::type other_setting_ = nullptr)
|
||||||
requires(ranged)
|
|
||||||
: Setting<Type, true>{linkage, default_val, min_val,
|
: Setting<Type, true>{linkage, default_val, min_val,
|
||||||
max_val, name, category_,
|
max_val, name, category_,
|
||||||
specialization_, save_, runtime_modifiable_,
|
specialization_, save_, runtime_modifiable_,
|
||||||
|
|
|
@ -509,9 +509,9 @@ class GuestMemory {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GuestMemory() = delete;
|
GuestMemory() = delete;
|
||||||
explicit GuestMemory(M& memory_, u64 addr_, std::size_t size_,
|
explicit GuestMemory(M& memory, u64 addr, std::size_t size,
|
||||||
Common::ScratchBuffer<T>* backup = nullptr)
|
Common::ScratchBuffer<T>* backup = nullptr)
|
||||||
: memory{memory_}, addr{addr_}, size{size_} {
|
: m_memory{memory}, m_addr{addr}, m_size{size} {
|
||||||
static_assert(FLAGS & GuestMemoryFlags::Read || FLAGS & GuestMemoryFlags::Write);
|
static_assert(FLAGS & GuestMemoryFlags::Read || FLAGS & GuestMemoryFlags::Write);
|
||||||
if constexpr (FLAGS & GuestMemoryFlags::Read) {
|
if constexpr (FLAGS & GuestMemoryFlags::Read) {
|
||||||
Read(addr, size, backup);
|
Read(addr, size, backup);
|
||||||
|
@ -521,89 +521,97 @@ public:
|
||||||
~GuestMemory() = default;
|
~GuestMemory() = default;
|
||||||
|
|
||||||
T* data() noexcept {
|
T* data() noexcept {
|
||||||
return data_span.data();
|
return m_data_span.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
const T* data() const noexcept {
|
const T* data() const noexcept {
|
||||||
return data_span.data();
|
return m_data_span.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size() const noexcept {
|
||||||
|
return m_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size_bytes() const noexcept {
|
||||||
|
return this->size() * sizeof(T);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] T* begin() noexcept {
|
[[nodiscard]] T* begin() noexcept {
|
||||||
return data();
|
return this->data();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] const T* begin() const noexcept {
|
[[nodiscard]] const T* begin() const noexcept {
|
||||||
return data();
|
return this->data();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] T* end() noexcept {
|
[[nodiscard]] T* end() noexcept {
|
||||||
return data() + size;
|
return this->data() + this->size();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] const T* end() const noexcept {
|
[[nodiscard]] const T* end() const noexcept {
|
||||||
return data() + size;
|
return this->data() + this->size();
|
||||||
}
|
}
|
||||||
|
|
||||||
T& operator[](size_t index) noexcept {
|
T& operator[](size_t index) noexcept {
|
||||||
return data_span[index];
|
return m_data_span[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
const T& operator[](size_t index) const noexcept {
|
const T& operator[](size_t index) const noexcept {
|
||||||
return data_span[index];
|
return m_data_span[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetAddressAndSize(u64 addr_, std::size_t size_) noexcept {
|
void SetAddressAndSize(u64 addr, std::size_t size) noexcept {
|
||||||
addr = addr_;
|
m_addr = addr;
|
||||||
size = size_;
|
m_size = size;
|
||||||
addr_changed = true;
|
m_addr_changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::span<T> Read(u64 addr_, std::size_t size_,
|
std::span<T> Read(u64 addr, std::size_t size,
|
||||||
Common::ScratchBuffer<T>* backup = nullptr) noexcept {
|
Common::ScratchBuffer<T>* backup = nullptr) noexcept {
|
||||||
addr = addr_;
|
m_addr = addr;
|
||||||
size = size_;
|
m_size = size;
|
||||||
if (size == 0) {
|
if (m_size == 0) {
|
||||||
is_data_copy = true;
|
m_is_data_copy = true;
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TrySetSpan()) {
|
if (this->TrySetSpan()) {
|
||||||
if constexpr (FLAGS & GuestMemoryFlags::Safe) {
|
if constexpr (FLAGS & GuestMemoryFlags::Safe) {
|
||||||
memory.FlushRegion(addr, size * sizeof(T));
|
m_memory.FlushRegion(m_addr, this->size_bytes());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (backup) {
|
if (backup) {
|
||||||
backup->resize_destructive(size);
|
backup->resize_destructive(this->size());
|
||||||
data_span = *backup;
|
m_data_span = *backup;
|
||||||
} else {
|
} else {
|
||||||
data_copy.resize(size);
|
m_data_copy.resize(this->size());
|
||||||
data_span = std::span(data_copy);
|
m_data_span = std::span(m_data_copy);
|
||||||
}
|
}
|
||||||
is_data_copy = true;
|
m_is_data_copy = true;
|
||||||
span_valid = true;
|
m_span_valid = true;
|
||||||
if constexpr (FLAGS & GuestMemoryFlags::Safe) {
|
if constexpr (FLAGS & GuestMemoryFlags::Safe) {
|
||||||
memory.ReadBlock(addr, data_span.data(), size * sizeof(T));
|
m_memory.ReadBlock(m_addr, this->data(), this->size_bytes());
|
||||||
} else {
|
} else {
|
||||||
memory.ReadBlockUnsafe(addr, data_span.data(), size * sizeof(T));
|
m_memory.ReadBlockUnsafe(m_addr, this->data(), this->size_bytes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return data_span;
|
return m_data_span;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write(std::span<T> write_data) noexcept {
|
void Write(std::span<T> write_data) noexcept {
|
||||||
if constexpr (FLAGS & GuestMemoryFlags::Cached) {
|
if constexpr (FLAGS & GuestMemoryFlags::Cached) {
|
||||||
memory.WriteBlockCached(addr, write_data.data(), size * sizeof(T));
|
m_memory.WriteBlockCached(m_addr, write_data.data(), this->size_bytes());
|
||||||
} else if constexpr (FLAGS & GuestMemoryFlags::Safe) {
|
} else if constexpr (FLAGS & GuestMemoryFlags::Safe) {
|
||||||
memory.WriteBlock(addr, write_data.data(), size * sizeof(T));
|
m_memory.WriteBlock(m_addr, write_data.data(), this->size_bytes());
|
||||||
} else {
|
} else {
|
||||||
memory.WriteBlockUnsafe(addr, write_data.data(), size * sizeof(T));
|
m_memory.WriteBlockUnsafe(m_addr, write_data.data(), this->size_bytes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TrySetSpan() noexcept {
|
bool TrySetSpan() noexcept {
|
||||||
if (u8* ptr = memory.GetSpan(addr, size * sizeof(T)); ptr) {
|
if (u8* ptr = m_memory.GetSpan(m_addr, this->size_bytes()); ptr) {
|
||||||
data_span = {reinterpret_cast<T*>(ptr), size};
|
m_data_span = {reinterpret_cast<T*>(ptr), this->size()};
|
||||||
span_valid = true;
|
m_span_valid = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -611,36 +619,36 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool IsDataCopy() const noexcept {
|
bool IsDataCopy() const noexcept {
|
||||||
return is_data_copy;
|
return m_is_data_copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AddressChanged() const noexcept {
|
bool AddressChanged() const noexcept {
|
||||||
return addr_changed;
|
return m_addr_changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
M& memory;
|
M& m_memory;
|
||||||
u64 addr;
|
u64 m_addr{};
|
||||||
size_t size;
|
size_t m_size{};
|
||||||
std::span<T> data_span{};
|
std::span<T> m_data_span{};
|
||||||
std::vector<T> data_copy;
|
std::vector<T> m_data_copy{};
|
||||||
bool span_valid{false};
|
bool m_span_valid{false};
|
||||||
bool is_data_copy{false};
|
bool m_is_data_copy{false};
|
||||||
bool addr_changed{false};
|
bool m_addr_changed{false};
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename M, typename T, GuestMemoryFlags FLAGS>
|
template <typename M, typename T, GuestMemoryFlags FLAGS>
|
||||||
class GuestMemoryScoped : public GuestMemory<M, T, FLAGS> {
|
class GuestMemoryScoped : public GuestMemory<M, T, FLAGS> {
|
||||||
public:
|
public:
|
||||||
GuestMemoryScoped() = delete;
|
GuestMemoryScoped() = delete;
|
||||||
explicit GuestMemoryScoped(M& memory_, u64 addr_, std::size_t size_,
|
explicit GuestMemoryScoped(M& memory, u64 addr, std::size_t size,
|
||||||
Common::ScratchBuffer<T>* backup = nullptr)
|
Common::ScratchBuffer<T>* backup = nullptr)
|
||||||
: GuestMemory<M, T, FLAGS>(memory_, addr_, size_, backup) {
|
: GuestMemory<M, T, FLAGS>(memory, addr, size, backup) {
|
||||||
if constexpr (!(FLAGS & GuestMemoryFlags::Read)) {
|
if constexpr (!(FLAGS & GuestMemoryFlags::Read)) {
|
||||||
if (!this->TrySetSpan()) {
|
if (!this->TrySetSpan()) {
|
||||||
if (backup) {
|
if (backup) {
|
||||||
this->data_span = *backup;
|
this->m_data_span = *backup;
|
||||||
this->span_valid = true;
|
this->m_span_valid = true;
|
||||||
this->is_data_copy = true;
|
this->m_is_data_copy = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -648,24 +656,21 @@ public:
|
||||||
|
|
||||||
~GuestMemoryScoped() {
|
~GuestMemoryScoped() {
|
||||||
if constexpr (FLAGS & GuestMemoryFlags::Write) {
|
if constexpr (FLAGS & GuestMemoryFlags::Write) {
|
||||||
if (this->size == 0) [[unlikely]] {
|
if (this->size() == 0) [[unlikely]] {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->AddressChanged() || this->IsDataCopy()) {
|
if (this->AddressChanged() || this->IsDataCopy()) {
|
||||||
ASSERT(this->span_valid);
|
ASSERT(this->m_span_valid);
|
||||||
if constexpr (FLAGS & GuestMemoryFlags::Cached) {
|
if constexpr (FLAGS & GuestMemoryFlags::Cached) {
|
||||||
this->memory.WriteBlockCached(this->addr, this->data_span.data(),
|
this->m_memory.WriteBlockCached(this->m_addr, this->data(), this->size_bytes());
|
||||||
this->size * sizeof(T));
|
|
||||||
} else if constexpr (FLAGS & GuestMemoryFlags::Safe) {
|
} else if constexpr (FLAGS & GuestMemoryFlags::Safe) {
|
||||||
this->memory.WriteBlock(this->addr, this->data_span.data(),
|
this->m_memory.WriteBlock(this->m_addr, this->data(), this->size_bytes());
|
||||||
this->size * sizeof(T));
|
|
||||||
} else {
|
} else {
|
||||||
this->memory.WriteBlockUnsafe(this->addr, this->data_span.data(),
|
this->m_memory.WriteBlockUnsafe(this->m_addr, this->data(), this->size_bytes());
|
||||||
this->size * sizeof(T));
|
|
||||||
}
|
}
|
||||||
} else if constexpr (FLAGS & GuestMemoryFlags::Safe) {
|
} else if constexpr (FLAGS & GuestMemoryFlags::Safe) {
|
||||||
this->memory.InvalidateRegion(this->addr, this->size * sizeof(T));
|
this->m_memory.InvalidateRegion(this->m_addr, this->size_bytes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "common/microprofile.h"
|
#include "common/microprofile.h"
|
||||||
|
#include "common/polyfill_ranges.h"
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/memory.h"
|
#include "core/memory.h"
|
||||||
|
|
Loading…
Reference in a new issue