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/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/settings.cpp | 10 | ||||
-rw-r--r-- | src/common/settings.h | 4 | ||||
-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 |
12 files changed, 159 insertions, 4 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) target_link_libraries(common PRIVATE xbyak::xbyak) endif() +if (ARCHITECTURE_arm64 AND (ANDROID OR LINUX)) + target_sources(common + PRIVATE + arm64/native_clock.cpp + arm64/native_clock.h + ) +endif() + if (MSVC) target_compile_definitions(common PRIVATE # 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 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/arm64/native_clock.h" + +namespace Common::Arm64 { + +namespace { + +NativeClock::FactorType GetFixedPointFactor(u64 num, u64 den) { + return (static_cast<NativeClock::FactorType>(num) << 64) / den; +} + +u64 MultiplyHigh(u64 m, NativeClock::FactorType factor) { + return static_cast<u64>((m * factor) >> 64); +} + +} // namespace + +NativeClock::NativeClock() { + const u64 host_cntfrq = GetHostCNTFRQ(); + ns_cntfrq_factor = GetFixedPointFactor(NsRatio::den, host_cntfrq); + us_cntfrq_factor = GetFixedPointFactor(UsRatio::den, host_cntfrq); + ms_cntfrq_factor = GetFixedPointFactor(MsRatio::den, host_cntfrq); + guest_cntfrq_factor = GetFixedPointFactor(CNTFRQ, host_cntfrq); + gputick_cntfrq_factor = GetFixedPointFactor(GPUTickFreq, host_cntfrq); +} + +std::chrono::nanoseconds NativeClock::GetTimeNS() const { + return std::chrono::nanoseconds{MultiplyHigh(GetHostTicksElapsed(), ns_cntfrq_factor)}; +} + +std::chrono::microseconds NativeClock::GetTimeUS() const { + return std::chrono::microseconds{MultiplyHigh(GetHostTicksElapsed(), us_cntfrq_factor)}; +} + +std::chrono::milliseconds NativeClock::GetTimeMS() const { + return std::chrono::milliseconds{MultiplyHigh(GetHostTicksElapsed(), ms_cntfrq_factor)}; +} + +u64 NativeClock::GetCNTPCT() const { + return MultiplyHigh(GetHostTicksElapsed(), guest_cntfrq_factor); +} + +u64 NativeClock::GetGPUTick() const { + return MultiplyHigh(GetHostTicksElapsed(), gputick_cntfrq_factor); +} + +u64 NativeClock::GetHostTicksNow() const { + u64 cntvct_el0 = 0; + asm volatile("dsb ish\n\t" + "mrs %[cntvct_el0], cntvct_el0\n\t" + "dsb ish\n\t" + : [cntvct_el0] "=r"(cntvct_el0)); + return cntvct_el0; +} + +u64 NativeClock::GetHostTicksElapsed() const { + return GetHostTicksNow(); +} + +bool NativeClock::IsNative() const { + return true; +} + +u64 NativeClock::GetHostCNTFRQ() { + u64 cntfrq_el0 = 0; + asm("mrs %[cntfrq_el0], cntfrq_el0" : [cntfrq_el0] "=r"(cntfrq_el0)); + return cntfrq_el0; +} + +} // 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 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "common/wall_clock.h" + +namespace Common::Arm64 { + +class NativeClock final : public WallClock { +public: + explicit NativeClock(); + + std::chrono::nanoseconds GetTimeNS() const override; + + std::chrono::microseconds GetTimeUS() const override; + + std::chrono::milliseconds GetTimeMS() const override; + + u64 GetCNTPCT() const override; + + u64 GetGPUTick() const override; + + u64 GetHostTicksNow() const override; + + u64 GetHostTicksElapsed() const override; + + bool IsNative() const override; + + static u64 GetHostCNTFRQ(); + +public: + using FactorType = unsigned __int128; + + FactorType GetGuestCNTFRQFactor() const { + return guest_cntfrq_factor; + } + +private: + FactorType ns_cntfrq_factor; + FactorType us_cntfrq_factor; + FactorType ms_cntfrq_factor; + FactorType guest_cntfrq_factor; + FactorType gputick_cntfrq_factor; +}; + +} // namespace Common::Arm64 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 @@ #define LOAD_DIR "load" #define LOG_DIR "log" #define NAND_DIR "nand" +#define PLAY_TIME_DIR "play_time" #define SCREENSHOTS_DIR "screenshots" #define SDMC_DIR "sdmc" #define SHADER_DIR "shader" #define TAS_DIR "tas" +#define ICONS_DIR "icons" // yuzu-specific files 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: GenerateYuzuPath(YuzuPath::LoadDir, yuzu_path / LOAD_DIR); GenerateYuzuPath(YuzuPath::LogDir, yuzu_path / LOG_DIR); GenerateYuzuPath(YuzuPath::NANDDir, yuzu_path / NAND_DIR); + GenerateYuzuPath(YuzuPath::PlayTimeDir, yuzu_path / PLAY_TIME_DIR); GenerateYuzuPath(YuzuPath::ScreenshotsDir, yuzu_path / SCREENSHOTS_DIR); GenerateYuzuPath(YuzuPath::SDMCDir, yuzu_path / SDMC_DIR); GenerateYuzuPath(YuzuPath::ShaderDir, yuzu_path / SHADER_DIR); GenerateYuzuPath(YuzuPath::TASDir, yuzu_path / TAS_DIR); + GenerateYuzuPath(YuzuPath::IconsDir, yuzu_path / ICONS_DIR); } 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 { LoadDir, // Where cheat/mod files are stored. LogDir, // Where log files are stored. NANDDir, // Where the emulated NAND is stored. + PlayTimeDir, // Where play time data is stored. ScreenshotsDir, // Where yuzu screenshots are stored. SDMCDir, // Where the emulated SDMC is stored. ShaderDir, // Where shaders are stored. TASDir, // Where TAS scripts are stored. + IconsDir, // Where Icons for Windows shortcuts are stored. }; /** diff --git a/src/common/settings.cpp b/src/common/settings.cpp index 4ecaf550b..3fde3cae6 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp @@ -130,13 +130,17 @@ void LogSettings() { log_path("DataStorage_SDMCDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::SDMCDir)); } +void UpdateGPUAccuracy() { + values.current_gpu_accuracy = values.gpu_accuracy.GetValue(); +} + bool IsGPULevelExtreme() { - return values.gpu_accuracy.GetValue() == GpuAccuracy::Extreme; + return values.current_gpu_accuracy == GpuAccuracy::Extreme; } bool IsGPULevelHigh() { - return values.gpu_accuracy.GetValue() == GpuAccuracy::Extreme || - values.gpu_accuracy.GetValue() == GpuAccuracy::High; + return values.current_gpu_accuracy == GpuAccuracy::Extreme || + values.current_gpu_accuracy == GpuAccuracy::High; } bool IsFastmemEnabled() { diff --git a/src/common/settings.h b/src/common/settings.h index 82ec9077e..98ab0ec2e 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -307,6 +307,7 @@ struct Values { Specialization::Default, true, true}; + GpuAccuracy current_gpu_accuracy{GpuAccuracy::High}; SwitchableSetting<AnisotropyMode, true> max_anisotropy{ linkage, AnisotropyMode::Automatic, AnisotropyMode::Automatic, AnisotropyMode::X16, "max_anisotropy", Category::RendererAdvanced}; @@ -350,6 +351,8 @@ struct Values { linkage, false, "disable_shader_loop_safety_checks", Category::RendererDebug}; Setting<bool> enable_renderdoc_hotkey{linkage, false, "renderdoc_hotkey", Category::RendererDebug}; + // TODO: remove this once AMDVLK supports VK_EXT_depth_bias_control + bool renderer_amdvlk_depth_bias_workaround{}; // System SwitchableSetting<Language, true> language_index{linkage, @@ -522,6 +525,7 @@ struct Values { extern Values values; +void UpdateGPUAccuracy(); bool IsGPULevelExtreme(); bool IsGPULevelHigh(); 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: this->SetValue(input == "true"); } else if constexpr (std::is_same_v<Type, float>) { this->SetValue(std::stof(input)); + } else if constexpr (std::is_same_v<Type, AudioEngine>) { + this->SetValue(ToEnum<AudioEngine>(input)); } else { this->SetValue(static_cast<Type>(std::stoll(input))); } 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) { return convert.from_bytes(input.data(), input.data() + input.size()); } +std::u32string UTF8ToUTF32(std::string_view input) { + std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> convert; + return convert.from_bytes(input.data(), input.data() + input.size()); +} + #ifdef _WIN32 static std::wstring CPToUTF16(u32 code_page, std::string_view input) { 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* _ [[nodiscard]] std::string UTF16ToUTF8(std::u16string_view input); [[nodiscard]] std::u16string UTF8ToUTF16(std::string_view input); +[[nodiscard]] std::u32string UTF8ToUTF32(std::string_view input); #ifdef _WIN32 [[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 @@ #include "common/x64/rdtsc.h" #endif +#if defined(ARCHITECTURE_arm64) && defined(__linux__) +#include "common/arm64/native_clock.h" +#endif + namespace Common { class StandardWallClock final : public WallClock { @@ -53,7 +57,7 @@ private: }; std::unique_ptr<WallClock> CreateOptimalClock() { -#ifdef ARCHITECTURE_x86_64 +#if defined(ARCHITECTURE_x86_64) const auto& caps = GetCPUCaps(); if (caps.invariant_tsc && caps.tsc_frequency >= std::nano::den) { @@ -64,6 +68,8 @@ std::unique_ptr<WallClock> CreateOptimalClock() { // - Is not more precise than 1 GHz (1ns resolution) return std::make_unique<StandardWallClock>(); } +#elif defined(ARCHITECTURE_arm64) && defined(__linux__) + return std::make_unique<Arm64::NativeClock>(); #else return std::make_unique<StandardWallClock>(); #endif |