diff options
Diffstat (limited to 'src/common')
| -rw-r--r-- | src/common/CMakeLists.txt | 8 | ||||
| -rw-r--r-- | src/common/arm64/native_clock.cpp | 72 | ||||
| -rw-r--r-- | src/common/arm64/native_clock.h | 47 | ||||
| -rw-r--r-- | src/common/common_funcs.h | 4 | ||||
| -rw-r--r-- | src/common/elf.h | 8 | ||||
| -rw-r--r-- | src/common/fs/fs_paths.h | 2 | ||||
| -rw-r--r-- | src/common/fs/path_util.cpp | 2 | ||||
| -rw-r--r-- | src/common/fs/path_util.h | 2 | ||||
| -rw-r--r-- | src/common/polyfill_thread.h | 21 | ||||
| -rw-r--r-- | src/common/settings.cpp | 15 | ||||
| -rw-r--r-- | src/common/settings.h | 9 | ||||
| -rw-r--r-- | src/common/settings_enums.h | 2 | ||||
| -rw-r--r-- | src/common/settings_setting.h | 2 | ||||
| -rw-r--r-- | src/common/string_util.cpp | 5 | ||||
| -rw-r--r-- | src/common/string_util.h | 1 | ||||
| -rw-r--r-- | src/common/wall_clock.cpp | 8 |
16 files changed, 194 insertions, 14 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 416203c59..8a1861051 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt | |||
| @@ -189,6 +189,14 @@ if(ARCHITECTURE_x86_64) | |||
| 189 | target_link_libraries(common PRIVATE xbyak::xbyak) | 189 | target_link_libraries(common PRIVATE xbyak::xbyak) |
| 190 | endif() | 190 | endif() |
| 191 | 191 | ||
| 192 | if (ARCHITECTURE_arm64 AND (ANDROID OR LINUX)) | ||
| 193 | target_sources(common | ||
| 194 | PRIVATE | ||
| 195 | arm64/native_clock.cpp | ||
| 196 | arm64/native_clock.h | ||
| 197 | ) | ||
| 198 | endif() | ||
| 199 | |||
| 192 | if (MSVC) | 200 | if (MSVC) |
| 193 | target_compile_definitions(common PRIVATE | 201 | target_compile_definitions(common PRIVATE |
| 194 | # The standard library doesn't provide any replacement for codecvt yet | 202 | # The standard library doesn't provide any replacement for codecvt yet |
diff --git a/src/common/arm64/native_clock.cpp b/src/common/arm64/native_clock.cpp new file mode 100644 index 000000000..88fdba527 --- /dev/null +++ b/src/common/arm64/native_clock.cpp | |||
| @@ -0,0 +1,72 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "common/arm64/native_clock.h" | ||
| 5 | |||
| 6 | namespace Common::Arm64 { | ||
| 7 | |||
| 8 | namespace { | ||
| 9 | |||
| 10 | NativeClock::FactorType GetFixedPointFactor(u64 num, u64 den) { | ||
| 11 | return (static_cast<NativeClock::FactorType>(num) << 64) / den; | ||
| 12 | } | ||
| 13 | |||
| 14 | u64 MultiplyHigh(u64 m, NativeClock::FactorType factor) { | ||
| 15 | return static_cast<u64>((m * factor) >> 64); | ||
| 16 | } | ||
| 17 | |||
| 18 | } // namespace | ||
| 19 | |||
| 20 | NativeClock::NativeClock() { | ||
| 21 | const u64 host_cntfrq = GetHostCNTFRQ(); | ||
| 22 | ns_cntfrq_factor = GetFixedPointFactor(NsRatio::den, host_cntfrq); | ||
| 23 | us_cntfrq_factor = GetFixedPointFactor(UsRatio::den, host_cntfrq); | ||
| 24 | ms_cntfrq_factor = GetFixedPointFactor(MsRatio::den, host_cntfrq); | ||
| 25 | guest_cntfrq_factor = GetFixedPointFactor(CNTFRQ, host_cntfrq); | ||
| 26 | gputick_cntfrq_factor = GetFixedPointFactor(GPUTickFreq, host_cntfrq); | ||
| 27 | } | ||
| 28 | |||
| 29 | std::chrono::nanoseconds NativeClock::GetTimeNS() const { | ||
| 30 | return std::chrono::nanoseconds{MultiplyHigh(GetHostTicksElapsed(), ns_cntfrq_factor)}; | ||
| 31 | } | ||
| 32 | |||
| 33 | std::chrono::microseconds NativeClock::GetTimeUS() const { | ||
| 34 | return std::chrono::microseconds{MultiplyHigh(GetHostTicksElapsed(), us_cntfrq_factor)}; | ||
| 35 | } | ||
| 36 | |||
| 37 | std::chrono::milliseconds NativeClock::GetTimeMS() const { | ||
| 38 | return std::chrono::milliseconds{MultiplyHigh(GetHostTicksElapsed(), ms_cntfrq_factor)}; | ||
| 39 | } | ||
| 40 | |||
| 41 | u64 NativeClock::GetCNTPCT() const { | ||
| 42 | return MultiplyHigh(GetHostTicksElapsed(), guest_cntfrq_factor); | ||
| 43 | } | ||
| 44 | |||
| 45 | u64 NativeClock::GetGPUTick() const { | ||
| 46 | return MultiplyHigh(GetHostTicksElapsed(), gputick_cntfrq_factor); | ||
| 47 | } | ||
| 48 | |||
| 49 | u64 NativeClock::GetHostTicksNow() const { | ||
| 50 | u64 cntvct_el0 = 0; | ||
| 51 | asm volatile("dsb ish\n\t" | ||
| 52 | "mrs %[cntvct_el0], cntvct_el0\n\t" | ||
| 53 | "dsb ish\n\t" | ||
| 54 | : [cntvct_el0] "=r"(cntvct_el0)); | ||
| 55 | return cntvct_el0; | ||
| 56 | } | ||
| 57 | |||
| 58 | u64 NativeClock::GetHostTicksElapsed() const { | ||
| 59 | return GetHostTicksNow(); | ||
| 60 | } | ||
| 61 | |||
| 62 | bool NativeClock::IsNative() const { | ||
| 63 | return true; | ||
| 64 | } | ||
| 65 | |||
| 66 | u64 NativeClock::GetHostCNTFRQ() { | ||
| 67 | u64 cntfrq_el0 = 0; | ||
| 68 | asm("mrs %[cntfrq_el0], cntfrq_el0" : [cntfrq_el0] "=r"(cntfrq_el0)); | ||
| 69 | return cntfrq_el0; | ||
| 70 | } | ||
| 71 | |||
| 72 | } // namespace Common::Arm64 | ||
diff --git a/src/common/arm64/native_clock.h b/src/common/arm64/native_clock.h new file mode 100644 index 000000000..a28b419f2 --- /dev/null +++ b/src/common/arm64/native_clock.h | |||
| @@ -0,0 +1,47 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/wall_clock.h" | ||
| 7 | |||
| 8 | namespace Common::Arm64 { | ||
| 9 | |||
| 10 | class NativeClock final : public WallClock { | ||
| 11 | public: | ||
| 12 | explicit NativeClock(); | ||
| 13 | |||
| 14 | std::chrono::nanoseconds GetTimeNS() const override; | ||
| 15 | |||
| 16 | std::chrono::microseconds GetTimeUS() const override; | ||
| 17 | |||
| 18 | std::chrono::milliseconds GetTimeMS() const override; | ||
| 19 | |||
| 20 | u64 GetCNTPCT() const override; | ||
| 21 | |||
| 22 | u64 GetGPUTick() const override; | ||
| 23 | |||
| 24 | u64 GetHostTicksNow() const override; | ||
| 25 | |||
| 26 | u64 GetHostTicksElapsed() const override; | ||
| 27 | |||
| 28 | bool IsNative() const override; | ||
| 29 | |||
| 30 | static u64 GetHostCNTFRQ(); | ||
| 31 | |||
| 32 | public: | ||
| 33 | using FactorType = unsigned __int128; | ||
| 34 | |||
| 35 | FactorType GetGuestCNTFRQFactor() const { | ||
| 36 | return guest_cntfrq_factor; | ||
| 37 | } | ||
| 38 | |||
| 39 | private: | ||
| 40 | FactorType ns_cntfrq_factor; | ||
| 41 | FactorType us_cntfrq_factor; | ||
| 42 | FactorType ms_cntfrq_factor; | ||
| 43 | FactorType guest_cntfrq_factor; | ||
| 44 | FactorType gputick_cntfrq_factor; | ||
| 45 | }; | ||
| 46 | |||
| 47 | } // namespace Common::Arm64 | ||
diff --git a/src/common/common_funcs.h b/src/common/common_funcs.h index 0dad9338a..47d028d48 100644 --- a/src/common/common_funcs.h +++ b/src/common/common_funcs.h | |||
| @@ -39,8 +39,12 @@ | |||
| 39 | #define Crash() exit(1) | 39 | #define Crash() exit(1) |
| 40 | #endif | 40 | #endif |
| 41 | 41 | ||
| 42 | #define LTO_NOINLINE __attribute__((noinline)) | ||
| 43 | |||
| 42 | #else // _MSC_VER | 44 | #else // _MSC_VER |
| 43 | 45 | ||
| 46 | #define LTO_NOINLINE | ||
| 47 | |||
| 44 | // Locale Cross-Compatibility | 48 | // Locale Cross-Compatibility |
| 45 | #define locale_t _locale_t | 49 | #define locale_t _locale_t |
| 46 | 50 | ||
diff --git a/src/common/elf.h b/src/common/elf.h index 14a5e9597..0b728dc54 100644 --- a/src/common/elf.h +++ b/src/common/elf.h | |||
| @@ -211,6 +211,11 @@ struct Elf64_Rela { | |||
| 211 | Elf64_Sxword r_addend; /* Addend */ | 211 | Elf64_Sxword r_addend; /* Addend */ |
| 212 | }; | 212 | }; |
| 213 | 213 | ||
| 214 | /* RELR relocation table entry */ | ||
| 215 | |||
| 216 | using Elf32_Relr = Elf32_Word; | ||
| 217 | using Elf64_Relr = Elf64_Xword; | ||
| 218 | |||
| 214 | /* How to extract and insert information held in the r_info field. */ | 219 | /* How to extract and insert information held in the r_info field. */ |
| 215 | 220 | ||
| 216 | static inline u32 Elf32RelSymIndex(Elf32_Word r_info) { | 221 | static inline u32 Elf32RelSymIndex(Elf32_Word r_info) { |
| @@ -328,6 +333,9 @@ constexpr u32 ElfDtFiniArray = 26; /* Array with addresses of fini fct */ | |||
| 328 | constexpr u32 ElfDtInitArraySz = 27; /* Size in bytes of DT_INIT_ARRAY */ | 333 | constexpr u32 ElfDtInitArraySz = 27; /* Size in bytes of DT_INIT_ARRAY */ |
| 329 | constexpr u32 ElfDtFiniArraySz = 28; /* Size in bytes of DT_FINI_ARRAY */ | 334 | constexpr u32 ElfDtFiniArraySz = 28; /* Size in bytes of DT_FINI_ARRAY */ |
| 330 | constexpr u32 ElfDtSymtabShndx = 34; /* Address of SYMTAB_SHNDX section */ | 335 | constexpr u32 ElfDtSymtabShndx = 34; /* Address of SYMTAB_SHNDX section */ |
| 336 | constexpr u32 ElfDtRelrsz = 35; /* Size of RELR relative relocations */ | ||
| 337 | constexpr u32 ElfDtRelr = 36; /* Address of RELR relative relocations */ | ||
| 338 | constexpr u32 ElfDtRelrent = 37; /* Size of one RELR relative relocation */ | ||
| 331 | 339 | ||
| 332 | } // namespace ELF | 340 | } // namespace ELF |
| 333 | } // namespace Common | 341 | } // namespace Common |
diff --git a/src/common/fs/fs_paths.h b/src/common/fs/fs_paths.h index 61bac9eba..441c8af97 100644 --- a/src/common/fs/fs_paths.h +++ b/src/common/fs/fs_paths.h | |||
| @@ -18,10 +18,12 @@ | |||
| 18 | #define LOAD_DIR "load" | 18 | #define LOAD_DIR "load" |
| 19 | #define LOG_DIR "log" | 19 | #define LOG_DIR "log" |
| 20 | #define NAND_DIR "nand" | 20 | #define NAND_DIR "nand" |
| 21 | #define PLAY_TIME_DIR "play_time" | ||
| 21 | #define SCREENSHOTS_DIR "screenshots" | 22 | #define SCREENSHOTS_DIR "screenshots" |
| 22 | #define SDMC_DIR "sdmc" | 23 | #define SDMC_DIR "sdmc" |
| 23 | #define SHADER_DIR "shader" | 24 | #define SHADER_DIR "shader" |
| 24 | #define TAS_DIR "tas" | 25 | #define TAS_DIR "tas" |
| 26 | #define ICONS_DIR "icons" | ||
| 25 | 27 | ||
| 26 | // yuzu-specific files | 28 | // yuzu-specific files |
| 27 | 29 | ||
diff --git a/src/common/fs/path_util.cpp b/src/common/fs/path_util.cpp index dce219fcf..0abd81a45 100644 --- a/src/common/fs/path_util.cpp +++ b/src/common/fs/path_util.cpp | |||
| @@ -124,10 +124,12 @@ public: | |||
| 124 | GenerateYuzuPath(YuzuPath::LoadDir, yuzu_path / LOAD_DIR); | 124 | GenerateYuzuPath(YuzuPath::LoadDir, yuzu_path / LOAD_DIR); |
| 125 | GenerateYuzuPath(YuzuPath::LogDir, yuzu_path / LOG_DIR); | 125 | GenerateYuzuPath(YuzuPath::LogDir, yuzu_path / LOG_DIR); |
| 126 | GenerateYuzuPath(YuzuPath::NANDDir, yuzu_path / NAND_DIR); | 126 | GenerateYuzuPath(YuzuPath::NANDDir, yuzu_path / NAND_DIR); |
| 127 | GenerateYuzuPath(YuzuPath::PlayTimeDir, yuzu_path / PLAY_TIME_DIR); | ||
| 127 | GenerateYuzuPath(YuzuPath::ScreenshotsDir, yuzu_path / SCREENSHOTS_DIR); | 128 | GenerateYuzuPath(YuzuPath::ScreenshotsDir, yuzu_path / SCREENSHOTS_DIR); |
| 128 | GenerateYuzuPath(YuzuPath::SDMCDir, yuzu_path / SDMC_DIR); | 129 | GenerateYuzuPath(YuzuPath::SDMCDir, yuzu_path / SDMC_DIR); |
| 129 | GenerateYuzuPath(YuzuPath::ShaderDir, yuzu_path / SHADER_DIR); | 130 | GenerateYuzuPath(YuzuPath::ShaderDir, yuzu_path / SHADER_DIR); |
| 130 | GenerateYuzuPath(YuzuPath::TASDir, yuzu_path / TAS_DIR); | 131 | GenerateYuzuPath(YuzuPath::TASDir, yuzu_path / TAS_DIR); |
| 132 | GenerateYuzuPath(YuzuPath::IconsDir, yuzu_path / ICONS_DIR); | ||
| 131 | } | 133 | } |
| 132 | 134 | ||
| 133 | private: | 135 | private: |
diff --git a/src/common/fs/path_util.h b/src/common/fs/path_util.h index ba28964d0..63801c924 100644 --- a/src/common/fs/path_util.h +++ b/src/common/fs/path_util.h | |||
| @@ -20,10 +20,12 @@ enum class YuzuPath { | |||
| 20 | LoadDir, // Where cheat/mod files are stored. | 20 | LoadDir, // Where cheat/mod files are stored. |
| 21 | LogDir, // Where log files are stored. | 21 | LogDir, // Where log files are stored. |
| 22 | NANDDir, // Where the emulated NAND is stored. | 22 | NANDDir, // Where the emulated NAND is stored. |
| 23 | PlayTimeDir, // Where play time data is stored. | ||
| 23 | ScreenshotsDir, // Where yuzu screenshots are stored. | 24 | ScreenshotsDir, // Where yuzu screenshots are stored. |
| 24 | SDMCDir, // Where the emulated SDMC is stored. | 25 | SDMCDir, // Where the emulated SDMC is stored. |
| 25 | ShaderDir, // Where shaders are stored. | 26 | ShaderDir, // Where shaders are stored. |
| 26 | TASDir, // Where TAS scripts are stored. | 27 | TASDir, // Where TAS scripts are stored. |
| 28 | IconsDir, // Where Icons for Windows shortcuts are stored. | ||
| 27 | }; | 29 | }; |
| 28 | 30 | ||
| 29 | /** | 31 | /** |
diff --git a/src/common/polyfill_thread.h b/src/common/polyfill_thread.h index 41cbb9ed5..12e59a893 100644 --- a/src/common/polyfill_thread.h +++ b/src/common/polyfill_thread.h | |||
| @@ -15,12 +15,13 @@ | |||
| 15 | #include <condition_variable> | 15 | #include <condition_variable> |
| 16 | #include <stop_token> | 16 | #include <stop_token> |
| 17 | #include <thread> | 17 | #include <thread> |
| 18 | #include <utility> | ||
| 18 | 19 | ||
| 19 | namespace Common { | 20 | namespace Common { |
| 20 | 21 | ||
| 21 | template <typename Condvar, typename Lock, typename Pred> | 22 | template <typename Condvar, typename Lock, typename Pred> |
| 22 | void CondvarWait(Condvar& cv, std::unique_lock<Lock>& lk, std::stop_token token, Pred&& pred) { | 23 | void CondvarWait(Condvar& cv, std::unique_lock<Lock>& lk, std::stop_token token, Pred&& pred) { |
| 23 | cv.wait(lk, token, std::move(pred)); | 24 | cv.wait(lk, token, std::forward<Pred>(pred)); |
| 24 | } | 25 | } |
| 25 | 26 | ||
| 26 | template <typename Rep, typename Period> | 27 | template <typename Rep, typename Period> |
| @@ -109,7 +110,7 @@ public: | |||
| 109 | 110 | ||
| 110 | // Insert the callback. | 111 | // Insert the callback. |
| 111 | stop_state_callback ret = ++m_next_callback; | 112 | stop_state_callback ret = ++m_next_callback; |
| 112 | m_callbacks.emplace(ret, move(f)); | 113 | m_callbacks.emplace(ret, std::move(f)); |
| 113 | return ret; | 114 | return ret; |
| 114 | } | 115 | } |
| 115 | 116 | ||
| @@ -162,7 +163,7 @@ private: | |||
| 162 | friend class stop_source; | 163 | friend class stop_source; |
| 163 | template <typename Callback> | 164 | template <typename Callback> |
| 164 | friend class stop_callback; | 165 | friend class stop_callback; |
| 165 | stop_token(shared_ptr<polyfill::stop_state> stop_state) : m_stop_state(move(stop_state)) {} | 166 | stop_token(shared_ptr<polyfill::stop_state> stop_state) : m_stop_state(std::move(stop_state)) {} |
| 166 | 167 | ||
| 167 | private: | 168 | private: |
| 168 | shared_ptr<polyfill::stop_state> m_stop_state; | 169 | shared_ptr<polyfill::stop_state> m_stop_state; |
| @@ -198,7 +199,7 @@ public: | |||
| 198 | private: | 199 | private: |
| 199 | friend class jthread; | 200 | friend class jthread; |
| 200 | explicit stop_source(shared_ptr<polyfill::stop_state> stop_state) | 201 | explicit stop_source(shared_ptr<polyfill::stop_state> stop_state) |
| 201 | : m_stop_state(move(stop_state)) {} | 202 | : m_stop_state(std::move(stop_state)) {} |
| 202 | 203 | ||
| 203 | private: | 204 | private: |
| 204 | shared_ptr<polyfill::stop_state> m_stop_state; | 205 | shared_ptr<polyfill::stop_state> m_stop_state; |
| @@ -218,16 +219,16 @@ public: | |||
| 218 | C&& cb) noexcept(is_nothrow_constructible_v<Callback, C>) | 219 | C&& cb) noexcept(is_nothrow_constructible_v<Callback, C>) |
| 219 | : m_stop_state(st.m_stop_state) { | 220 | : m_stop_state(st.m_stop_state) { |
| 220 | if (m_stop_state) { | 221 | if (m_stop_state) { |
| 221 | m_callback = m_stop_state->insert_callback(move(cb)); | 222 | m_callback = m_stop_state->insert_callback(std::move(cb)); |
| 222 | } | 223 | } |
| 223 | } | 224 | } |
| 224 | template <typename C> | 225 | template <typename C> |
| 225 | requires constructible_from<Callback, C> | 226 | requires constructible_from<Callback, C> |
| 226 | explicit stop_callback(stop_token&& st, | 227 | explicit stop_callback(stop_token&& st, |
| 227 | C&& cb) noexcept(is_nothrow_constructible_v<Callback, C>) | 228 | C&& cb) noexcept(is_nothrow_constructible_v<Callback, C>) |
| 228 | : m_stop_state(move(st.m_stop_state)) { | 229 | : m_stop_state(std::move(st.m_stop_state)) { |
| 229 | if (m_stop_state) { | 230 | if (m_stop_state) { |
| 230 | m_callback = m_stop_state->insert_callback(move(cb)); | 231 | m_callback = m_stop_state->insert_callback(std::move(cb)); |
| 231 | } | 232 | } |
| 232 | } | 233 | } |
| 233 | ~stop_callback() { | 234 | ~stop_callback() { |
| @@ -260,7 +261,7 @@ public: | |||
| 260 | typename = enable_if_t<!is_same_v<remove_cvref_t<F>, jthread>>> | 261 | typename = enable_if_t<!is_same_v<remove_cvref_t<F>, jthread>>> |
| 261 | explicit jthread(F&& f, Args&&... args) | 262 | explicit jthread(F&& f, Args&&... args) |
| 262 | : m_stop_state(make_shared<polyfill::stop_state>()), | 263 | : m_stop_state(make_shared<polyfill::stop_state>()), |
| 263 | m_thread(make_thread(move(f), move(args)...)) {} | 264 | m_thread(make_thread(std::forward<F>(f), std::forward<Args>(args)...)) {} |
| 264 | 265 | ||
| 265 | ~jthread() { | 266 | ~jthread() { |
| 266 | if (joinable()) { | 267 | if (joinable()) { |
| @@ -317,9 +318,9 @@ private: | |||
| 317 | template <typename F, typename... Args> | 318 | template <typename F, typename... Args> |
| 318 | thread make_thread(F&& f, Args&&... args) { | 319 | thread make_thread(F&& f, Args&&... args) { |
| 319 | if constexpr (is_invocable_v<decay_t<F>, stop_token, decay_t<Args>...>) { | 320 | if constexpr (is_invocable_v<decay_t<F>, stop_token, decay_t<Args>...>) { |
| 320 | return thread(move(f), get_stop_token(), move(args)...); | 321 | return thread(std::forward<F>(f), get_stop_token(), std::forward<Args>(args)...); |
| 321 | } else { | 322 | } else { |
| 322 | return thread(move(f), move(args)...); | 323 | return thread(std::forward<F>(f), std::forward<Args>(args)...); |
| 323 | } | 324 | } |
| 324 | } | 325 | } |
| 325 | 326 | ||
diff --git a/src/common/settings.cpp b/src/common/settings.cpp index 4ecaf550b..98b43e49c 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp | |||
| @@ -45,6 +45,7 @@ SWITCHABLE(CpuAccuracy, true); | |||
| 45 | SWITCHABLE(FullscreenMode, true); | 45 | SWITCHABLE(FullscreenMode, true); |
| 46 | SWITCHABLE(GpuAccuracy, true); | 46 | SWITCHABLE(GpuAccuracy, true); |
| 47 | SWITCHABLE(Language, true); | 47 | SWITCHABLE(Language, true); |
| 48 | SWITCHABLE(MemoryLayout, true); | ||
| 48 | SWITCHABLE(NvdecEmulation, false); | 49 | SWITCHABLE(NvdecEmulation, false); |
| 49 | SWITCHABLE(Region, true); | 50 | SWITCHABLE(Region, true); |
| 50 | SWITCHABLE(RendererBackend, true); | 51 | SWITCHABLE(RendererBackend, true); |
| @@ -61,6 +62,10 @@ SWITCHABLE(u32, false); | |||
| 61 | SWITCHABLE(u8, false); | 62 | SWITCHABLE(u8, false); |
| 62 | SWITCHABLE(u8, true); | 63 | SWITCHABLE(u8, true); |
| 63 | 64 | ||
| 65 | // Used in UISettings | ||
| 66 | // TODO see if we can move this to uisettings.cpp | ||
| 67 | SWITCHABLE(ConfirmStop, true); | ||
| 68 | |||
| 64 | #undef SETTING | 69 | #undef SETTING |
| 65 | #undef SWITCHABLE | 70 | #undef SWITCHABLE |
| 66 | #endif | 71 | #endif |
| @@ -130,13 +135,17 @@ void LogSettings() { | |||
| 130 | log_path("DataStorage_SDMCDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::SDMCDir)); | 135 | log_path("DataStorage_SDMCDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::SDMCDir)); |
| 131 | } | 136 | } |
| 132 | 137 | ||
| 138 | void UpdateGPUAccuracy() { | ||
| 139 | values.current_gpu_accuracy = values.gpu_accuracy.GetValue(); | ||
| 140 | } | ||
| 141 | |||
| 133 | bool IsGPULevelExtreme() { | 142 | bool IsGPULevelExtreme() { |
| 134 | return values.gpu_accuracy.GetValue() == GpuAccuracy::Extreme; | 143 | return values.current_gpu_accuracy == GpuAccuracy::Extreme; |
| 135 | } | 144 | } |
| 136 | 145 | ||
| 137 | bool IsGPULevelHigh() { | 146 | bool IsGPULevelHigh() { |
| 138 | return values.gpu_accuracy.GetValue() == GpuAccuracy::Extreme || | 147 | return values.current_gpu_accuracy == GpuAccuracy::Extreme || |
| 139 | values.gpu_accuracy.GetValue() == GpuAccuracy::High; | 148 | values.current_gpu_accuracy == GpuAccuracy::High; |
| 140 | } | 149 | } |
| 141 | 150 | ||
| 142 | bool IsFastmemEnabled() { | 151 | bool IsFastmemEnabled() { |
diff --git a/src/common/settings.h b/src/common/settings.h index 82ec9077e..236e33bee 100644 --- a/src/common/settings.h +++ b/src/common/settings.h | |||
| @@ -67,6 +67,7 @@ SWITCHABLE(CpuAccuracy, true); | |||
| 67 | SWITCHABLE(FullscreenMode, true); | 67 | SWITCHABLE(FullscreenMode, true); |
| 68 | SWITCHABLE(GpuAccuracy, true); | 68 | SWITCHABLE(GpuAccuracy, true); |
| 69 | SWITCHABLE(Language, true); | 69 | SWITCHABLE(Language, true); |
| 70 | SWITCHABLE(MemoryLayout, true); | ||
| 70 | SWITCHABLE(NvdecEmulation, false); | 71 | SWITCHABLE(NvdecEmulation, false); |
| 71 | SWITCHABLE(Region, true); | 72 | SWITCHABLE(Region, true); |
| 72 | SWITCHABLE(RendererBackend, true); | 73 | SWITCHABLE(RendererBackend, true); |
| @@ -83,6 +84,10 @@ SWITCHABLE(u32, false); | |||
| 83 | SWITCHABLE(u8, false); | 84 | SWITCHABLE(u8, false); |
| 84 | SWITCHABLE(u8, true); | 85 | SWITCHABLE(u8, true); |
| 85 | 86 | ||
| 87 | // Used in UISettings | ||
| 88 | // TODO see if we can move this to uisettings.h | ||
| 89 | SWITCHABLE(ConfirmStop, true); | ||
| 90 | |||
| 86 | #undef SETTING | 91 | #undef SETTING |
| 87 | #undef SWITCHABLE | 92 | #undef SWITCHABLE |
| 88 | #endif | 93 | #endif |
| @@ -307,6 +312,7 @@ struct Values { | |||
| 307 | Specialization::Default, | 312 | Specialization::Default, |
| 308 | true, | 313 | true, |
| 309 | true}; | 314 | true}; |
| 315 | GpuAccuracy current_gpu_accuracy{GpuAccuracy::High}; | ||
| 310 | SwitchableSetting<AnisotropyMode, true> max_anisotropy{ | 316 | SwitchableSetting<AnisotropyMode, true> max_anisotropy{ |
| 311 | linkage, AnisotropyMode::Automatic, AnisotropyMode::Automatic, AnisotropyMode::X16, | 317 | linkage, AnisotropyMode::Automatic, AnisotropyMode::Automatic, AnisotropyMode::X16, |
| 312 | "max_anisotropy", Category::RendererAdvanced}; | 318 | "max_anisotropy", Category::RendererAdvanced}; |
| @@ -350,6 +356,8 @@ struct Values { | |||
| 350 | linkage, false, "disable_shader_loop_safety_checks", Category::RendererDebug}; | 356 | linkage, false, "disable_shader_loop_safety_checks", Category::RendererDebug}; |
| 351 | Setting<bool> enable_renderdoc_hotkey{linkage, false, "renderdoc_hotkey", | 357 | Setting<bool> enable_renderdoc_hotkey{linkage, false, "renderdoc_hotkey", |
| 352 | Category::RendererDebug}; | 358 | Category::RendererDebug}; |
| 359 | // TODO: remove this once AMDVLK supports VK_EXT_depth_bias_control | ||
| 360 | bool renderer_amdvlk_depth_bias_workaround{}; | ||
| 353 | 361 | ||
| 354 | // System | 362 | // System |
| 355 | SwitchableSetting<Language, true> language_index{linkage, | 363 | SwitchableSetting<Language, true> language_index{linkage, |
| @@ -522,6 +530,7 @@ struct Values { | |||
| 522 | 530 | ||
| 523 | extern Values values; | 531 | extern Values values; |
| 524 | 532 | ||
| 533 | void UpdateGPUAccuracy(); | ||
| 525 | bool IsGPULevelExtreme(); | 534 | bool IsGPULevelExtreme(); |
| 526 | bool IsGPULevelHigh(); | 535 | bool IsGPULevelHigh(); |
| 527 | 536 | ||
diff --git a/src/common/settings_enums.h b/src/common/settings_enums.h index 815cafe15..11429d7a8 100644 --- a/src/common/settings_enums.h +++ b/src/common/settings_enums.h | |||
| @@ -133,6 +133,8 @@ ENUM(CpuAccuracy, Auto, Accurate, Unsafe, Paranoid); | |||
| 133 | 133 | ||
| 134 | ENUM(MemoryLayout, Memory_4Gb, Memory_6Gb, Memory_8Gb); | 134 | ENUM(MemoryLayout, Memory_4Gb, Memory_6Gb, Memory_8Gb); |
| 135 | 135 | ||
| 136 | ENUM(ConfirmStop, Ask_Always, Ask_Based_On_Game, Ask_Never); | ||
| 137 | |||
| 136 | ENUM(FullscreenMode, Borderless, Exclusive); | 138 | ENUM(FullscreenMode, Borderless, Exclusive); |
| 137 | 139 | ||
| 138 | ENUM(NvdecEmulation, Off, Cpu, Gpu); | 140 | ENUM(NvdecEmulation, Off, Cpu, Gpu); |
diff --git a/src/common/settings_setting.h b/src/common/settings_setting.h index 7be6f26f7..3175ab07d 100644 --- a/src/common/settings_setting.h +++ b/src/common/settings_setting.h | |||
| @@ -187,6 +187,8 @@ public: | |||
| 187 | this->SetValue(input == "true"); | 187 | this->SetValue(input == "true"); |
| 188 | } else if constexpr (std::is_same_v<Type, float>) { | 188 | } else if constexpr (std::is_same_v<Type, float>) { |
| 189 | this->SetValue(std::stof(input)); | 189 | this->SetValue(std::stof(input)); |
| 190 | } else if constexpr (std::is_same_v<Type, AudioEngine>) { | ||
| 191 | this->SetValue(ToEnum<AudioEngine>(input)); | ||
| 190 | } else { | 192 | } else { |
| 191 | this->SetValue(static_cast<Type>(std::stoll(input))); | 193 | this->SetValue(static_cast<Type>(std::stoll(input))); |
| 192 | } | 194 | } |
diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp index feab1653d..4c7aba3f5 100644 --- a/src/common/string_util.cpp +++ b/src/common/string_util.cpp | |||
| @@ -135,6 +135,11 @@ std::u16string UTF8ToUTF16(std::string_view input) { | |||
| 135 | return convert.from_bytes(input.data(), input.data() + input.size()); | 135 | return convert.from_bytes(input.data(), input.data() + input.size()); |
| 136 | } | 136 | } |
| 137 | 137 | ||
| 138 | std::u32string UTF8ToUTF32(std::string_view input) { | ||
| 139 | std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> convert; | ||
| 140 | return convert.from_bytes(input.data(), input.data() + input.size()); | ||
| 141 | } | ||
| 142 | |||
| 138 | #ifdef _WIN32 | 143 | #ifdef _WIN32 |
| 139 | static std::wstring CPToUTF16(u32 code_page, std::string_view input) { | 144 | static std::wstring CPToUTF16(u32 code_page, std::string_view input) { |
| 140 | const auto size = | 145 | const auto size = |
diff --git a/src/common/string_util.h b/src/common/string_util.h index c351f1a0c..9da1ca4e9 100644 --- a/src/common/string_util.h +++ b/src/common/string_util.h | |||
| @@ -38,6 +38,7 @@ bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _ | |||
| 38 | 38 | ||
| 39 | [[nodiscard]] std::string UTF16ToUTF8(std::u16string_view input); | 39 | [[nodiscard]] std::string UTF16ToUTF8(std::u16string_view input); |
| 40 | [[nodiscard]] std::u16string UTF8ToUTF16(std::string_view input); | 40 | [[nodiscard]] std::u16string UTF8ToUTF16(std::string_view input); |
| 41 | [[nodiscard]] std::u32string UTF8ToUTF32(std::string_view input); | ||
| 41 | 42 | ||
| 42 | #ifdef _WIN32 | 43 | #ifdef _WIN32 |
| 43 | [[nodiscard]] std::string UTF16ToUTF8(std::wstring_view input); | 44 | [[nodiscard]] std::string UTF16ToUTF8(std::wstring_view input); |
diff --git a/src/common/wall_clock.cpp b/src/common/wall_clock.cpp index 71e15ab4c..caca9a123 100644 --- a/src/common/wall_clock.cpp +++ b/src/common/wall_clock.cpp | |||
| @@ -10,6 +10,10 @@ | |||
| 10 | #include "common/x64/rdtsc.h" | 10 | #include "common/x64/rdtsc.h" |
| 11 | #endif | 11 | #endif |
| 12 | 12 | ||
| 13 | #if defined(ARCHITECTURE_arm64) && defined(__linux__) | ||
| 14 | #include "common/arm64/native_clock.h" | ||
| 15 | #endif | ||
| 16 | |||
| 13 | namespace Common { | 17 | namespace Common { |
| 14 | 18 | ||
| 15 | class StandardWallClock final : public WallClock { | 19 | class StandardWallClock final : public WallClock { |
| @@ -53,7 +57,7 @@ private: | |||
| 53 | }; | 57 | }; |
| 54 | 58 | ||
| 55 | std::unique_ptr<WallClock> CreateOptimalClock() { | 59 | std::unique_ptr<WallClock> CreateOptimalClock() { |
| 56 | #ifdef ARCHITECTURE_x86_64 | 60 | #if defined(ARCHITECTURE_x86_64) |
| 57 | const auto& caps = GetCPUCaps(); | 61 | const auto& caps = GetCPUCaps(); |
| 58 | 62 | ||
| 59 | if (caps.invariant_tsc && caps.tsc_frequency >= std::nano::den) { | 63 | if (caps.invariant_tsc && caps.tsc_frequency >= std::nano::den) { |
| @@ -64,6 +68,8 @@ std::unique_ptr<WallClock> CreateOptimalClock() { | |||
| 64 | // - Is not more precise than 1 GHz (1ns resolution) | 68 | // - Is not more precise than 1 GHz (1ns resolution) |
| 65 | return std::make_unique<StandardWallClock>(); | 69 | return std::make_unique<StandardWallClock>(); |
| 66 | } | 70 | } |
| 71 | #elif defined(ARCHITECTURE_arm64) && defined(__linux__) | ||
| 72 | return std::make_unique<Arm64::NativeClock>(); | ||
| 67 | #else | 73 | #else |
| 68 | return std::make_unique<StandardWallClock>(); | 74 | return std::make_unique<StandardWallClock>(); |
| 69 | #endif | 75 | #endif |