diff options
Diffstat (limited to '')
-rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_32.cpp | 13 | ||||
-rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_64.cpp | 13 | ||||
-rw-r--r-- | src/core/core_timing.cpp | 12 | ||||
-rw-r--r-- | src/core/core_timing_util.cpp | 1 | ||||
-rw-r--r-- | src/core/core_timing_util.h | 1 | ||||
-rw-r--r-- | src/core/settings.h | 6 | ||||
-rw-r--r-- | src/video_core/macro/macro_interpreter.cpp | 1 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_shader_disk_cache.cpp | 23 | ||||
-rw-r--r-- | src/yuzu/configuration/config.cpp | 10 | ||||
-rw-r--r-- | src/yuzu/configuration/configure_cpu.cpp | 17 | ||||
-rw-r--r-- | src/yuzu/configuration/configure_cpu.h | 1 | ||||
-rw-r--r-- | src/yuzu/configuration/configure_cpu.ui | 52 |
12 files changed, 126 insertions, 24 deletions
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index 443ca72eb..b5f28a86e 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp @@ -143,7 +143,7 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable& config.wall_clock_cntpct = uses_wall_clock; // Safe optimizations - if (Settings::values.cpu_accuracy != Settings::CPUAccuracy::Accurate) { + if (Settings::values.cpu_accuracy == Settings::CPUAccuracy::DebugMode) { if (!Settings::values.cpuopt_page_tables) { config.page_table = nullptr; } @@ -170,6 +170,17 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable& } } + // Unsafe optimizations + if (Settings::values.cpu_accuracy == Settings::CPUAccuracy::Unsafe) { + config.unsafe_optimizations = true; + if (Settings::values.cpuopt_unsafe_unfuse_fma) { + config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA; + } + if (Settings::values.cpuopt_unsafe_reduce_fp_error) { + config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_ReducedErrorFP; + } + } + return std::make_unique<Dynarmic::A32::Jit>(config); } diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index a63a04a25..ce9968724 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp @@ -195,7 +195,7 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable& config.wall_clock_cntpct = uses_wall_clock; // Safe optimizations - if (Settings::values.cpu_accuracy != Settings::CPUAccuracy::Accurate) { + if (Settings::values.cpu_accuracy == Settings::CPUAccuracy::DebugMode) { if (!Settings::values.cpuopt_page_tables) { config.page_table = nullptr; } @@ -222,6 +222,17 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable& } } + // Unsafe optimizations + if (Settings::values.cpu_accuracy == Settings::CPUAccuracy::Unsafe) { + config.unsafe_optimizations = true; + if (Settings::values.cpuopt_unsafe_unfuse_fma) { + config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA; + } + if (Settings::values.cpuopt_unsafe_reduce_fp_error) { + config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_ReducedErrorFP; + } + } + return std::make_shared<Dynarmic::A64::Jit>(config); } diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp index 71af26ec5..e6c8461a5 100644 --- a/src/core/core_timing.cpp +++ b/src/core/core_timing.cpp @@ -7,14 +7,14 @@ #include <string> #include <tuple> -#include "common/assert.h" #include "common/microprofile.h" #include "core/core_timing.h" #include "core/core_timing_util.h" +#include "core/hardware_properties.h" namespace Core::Timing { -constexpr u64 MAX_SLICE_LENGTH = 4000; +constexpr s64 MAX_SLICE_LENGTH = 4000; std::shared_ptr<EventType> CreateEvent(std::string name, TimedCallback&& callback) { return std::make_shared<EventType>(std::move(callback), std::move(name)); @@ -37,10 +37,8 @@ struct CoreTiming::Event { } }; -CoreTiming::CoreTiming() { - clock = - Common::CreateBestMatchingClock(Core::Hardware::BASE_CLOCK_RATE, Core::Hardware::CNTFREQ); -} +CoreTiming::CoreTiming() + : clock{Common::CreateBestMatchingClock(Hardware::BASE_CLOCK_RATE, Hardware::CNTFREQ)} {} CoreTiming::~CoreTiming() = default; @@ -136,7 +134,7 @@ void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type, void CoreTiming::AddTicks(u64 ticks) { this->ticks += ticks; - downcount -= ticks; + downcount -= static_cast<s64>(ticks); } void CoreTiming::Idle() { diff --git a/src/core/core_timing_util.cpp b/src/core/core_timing_util.cpp index aefc63663..8ce8e602e 100644 --- a/src/core/core_timing_util.cpp +++ b/src/core/core_timing_util.cpp @@ -8,6 +8,7 @@ #include <limits> #include "common/logging/log.h" #include "common/uint128.h" +#include "core/hardware_properties.h" namespace Core::Timing { diff --git a/src/core/core_timing_util.h b/src/core/core_timing_util.h index 2ed979e14..e4a046bf9 100644 --- a/src/core/core_timing_util.h +++ b/src/core/core_timing_util.h @@ -6,7 +6,6 @@ #include <chrono> #include "common/common_types.h" -#include "core/hardware_properties.h" namespace Core::Timing { diff --git a/src/core/settings.h b/src/core/settings.h index bb145f193..3681b5e9d 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -359,7 +359,8 @@ enum class GPUAccuracy : u32 { enum class CPUAccuracy { Accurate = 0, - DebugMode = 1, + Unsafe = 1, + DebugMode = 2, }; extern bool configuring_global; @@ -419,6 +420,9 @@ struct Values { bool cpuopt_misc_ir; bool cpuopt_reduce_misalign_checks; + bool cpuopt_unsafe_unfuse_fma; + bool cpuopt_unsafe_reduce_fp_error; + // Renderer Setting<RendererBackend> renderer_backend; bool renderer_debug; diff --git a/src/video_core/macro/macro_interpreter.cpp b/src/video_core/macro/macro_interpreter.cpp index aa5256419..bd01fd1f2 100644 --- a/src/video_core/macro/macro_interpreter.cpp +++ b/src/video_core/macro/macro_interpreter.cpp @@ -34,7 +34,6 @@ void MacroInterpreterImpl::Execute(const std::vector<u32>& parameters, u32 metho this->parameters = std::make_unique<u32[]>(num_parameters); } std::memcpy(this->parameters.get(), parameters.data(), num_parameters * sizeof(u32)); - this->num_parameters = num_parameters; // Execute the code until we hit an exit condition. bool keep_executing = true; diff --git a/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp b/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp index 52fbab3c1..40c0877c1 100644 --- a/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp @@ -214,20 +214,20 @@ std::optional<std::vector<ShaderDiskCacheEntry>> ShaderDiskCacheOpenGL::LoadTran // Skip games without title id const bool has_title_id = system.CurrentProcess()->GetTitleID() != 0; if (!Settings::values.use_disk_shader_cache.GetValue() || !has_title_id) { - return {}; + return std::nullopt; } Common::FS::IOFile file(GetTransferablePath(), "rb"); if (!file.IsOpen()) { LOG_INFO(Render_OpenGL, "No transferable shader cache found"); is_usable = true; - return {}; + return std::nullopt; } u32 version{}; if (file.ReadBytes(&version, sizeof(version)) != sizeof(version)) { LOG_ERROR(Render_OpenGL, "Failed to get transferable cache version, skipping it"); - return {}; + return std::nullopt; } if (version < NativeVersion) { @@ -235,12 +235,12 @@ std::optional<std::vector<ShaderDiskCacheEntry>> ShaderDiskCacheOpenGL::LoadTran file.Close(); InvalidateTransferable(); is_usable = true; - return {}; + return std::nullopt; } if (version > NativeVersion) { LOG_WARNING(Render_OpenGL, "Transferable shader cache was generated with a newer version " "of the emulator, skipping"); - return {}; + return std::nullopt; } // Version is valid, load the shaders @@ -249,7 +249,7 @@ std::optional<std::vector<ShaderDiskCacheEntry>> ShaderDiskCacheOpenGL::LoadTran ShaderDiskCacheEntry& entry = entries.emplace_back(); if (!entry.Load(file)) { LOG_ERROR(Render_OpenGL, "Failed to load transferable raw entry, skipping"); - return {}; + return std::nullopt; } } @@ -290,12 +290,12 @@ std::optional<std::vector<ShaderDiskCachePrecompiled>> ShaderDiskCacheOpenGL::Lo ShaderCacheVersionHash file_hash{}; if (!LoadArrayFromPrecompiled(file_hash.data(), file_hash.size())) { precompiled_cache_virtual_file_offset = 0; - return {}; + return std::nullopt; } if (GetShaderCacheVersionHash() != file_hash) { LOG_INFO(Render_OpenGL, "Precompiled cache is from another version of the emulator"); precompiled_cache_virtual_file_offset = 0; - return {}; + return std::nullopt; } std::vector<ShaderDiskCachePrecompiled> entries; @@ -305,15 +305,16 @@ std::optional<std::vector<ShaderDiskCachePrecompiled>> ShaderDiskCacheOpenGL::Lo if (!LoadObjectFromPrecompiled(entry.unique_identifier) || !LoadObjectFromPrecompiled(entry.binary_format) || !LoadObjectFromPrecompiled(binary_size)) { - return {}; + return std::nullopt; } entry.binary.resize(binary_size); if (!LoadArrayFromPrecompiled(entry.binary.data(), entry.binary.size())) { - return {}; + return std::nullopt; } } - return entries; + + return std::move(entries); } void ShaderDiskCacheOpenGL::InvalidateTransferable() { diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index a372190cc..7af974d8d 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -635,6 +635,11 @@ void Config::ReadCpuValues() { ReadSetting(QStringLiteral("cpuopt_misc_ir"), true).toBool(); Settings::values.cpuopt_reduce_misalign_checks = ReadSetting(QStringLiteral("cpuopt_reduce_misalign_checks"), true).toBool(); + + Settings::values.cpuopt_unsafe_unfuse_fma = + ReadSetting(QStringLiteral("cpuopt_unsafe_unfuse_fma"), true).toBool(); + Settings::values.cpuopt_unsafe_reduce_fp_error = + ReadSetting(QStringLiteral("cpuopt_unsafe_reduce_fp_error"), true).toBool(); } qt_config->endGroup(); @@ -1132,6 +1137,11 @@ void Config::SaveCpuValues() { WriteSetting(QStringLiteral("cpuopt_misc_ir"), Settings::values.cpuopt_misc_ir, true); WriteSetting(QStringLiteral("cpuopt_reduce_misalign_checks"), Settings::values.cpuopt_reduce_misalign_checks, true); + + WriteSetting(QStringLiteral("cpuopt_unsafe_unfuse_fma"), + Settings::values.cpuopt_unsafe_unfuse_fma, true); + WriteSetting(QStringLiteral("cpuopt_unsafe_reduce_fp_error"), + Settings::values.cpuopt_unsafe_reduce_fp_error, true); } qt_config->endGroup(); diff --git a/src/yuzu/configuration/configure_cpu.cpp b/src/yuzu/configuration/configure_cpu.cpp index 7493e5ffb..37fcd6adc 100644 --- a/src/yuzu/configuration/configure_cpu.cpp +++ b/src/yuzu/configuration/configure_cpu.cpp @@ -19,6 +19,8 @@ ConfigureCpu::ConfigureCpu(QWidget* parent) : QWidget(parent), ui(new Ui::Config connect(ui->accuracy, qOverload<int>(&QComboBox::activated), this, &ConfigureCpu::AccuracyUpdated); + connect(ui->accuracy, qOverload<int>(&QComboBox::currentIndexChanged), this, + &ConfigureCpu::UpdateGroup); } ConfigureCpu::~ConfigureCpu() = default; @@ -28,6 +30,12 @@ void ConfigureCpu::SetConfiguration() { ui->accuracy->setEnabled(runtime_lock); ui->accuracy->setCurrentIndex(static_cast<int>(Settings::values.cpu_accuracy)); + UpdateGroup(static_cast<int>(Settings::values.cpu_accuracy)); + + ui->cpuopt_unsafe_unfuse_fma->setEnabled(runtime_lock); + ui->cpuopt_unsafe_unfuse_fma->setChecked(Settings::values.cpuopt_unsafe_unfuse_fma); + ui->cpuopt_unsafe_reduce_fp_error->setEnabled(runtime_lock); + ui->cpuopt_unsafe_reduce_fp_error->setChecked(Settings::values.cpuopt_unsafe_reduce_fp_error); } void ConfigureCpu::AccuracyUpdated(int index) { @@ -38,14 +46,21 @@ void ConfigureCpu::AccuracyUpdated(int index) { QMessageBox::Yes | QMessageBox::No); if (result == QMessageBox::No) { ui->accuracy->setCurrentIndex(static_cast<int>(Settings::CPUAccuracy::Accurate)); - return; + UpdateGroup(static_cast<int>(Settings::CPUAccuracy::Accurate)); } } } +void ConfigureCpu::UpdateGroup(int index) { + ui->unsafe_group->setVisible(static_cast<Settings::CPUAccuracy>(index) == + Settings::CPUAccuracy::Unsafe); +} + void ConfigureCpu::ApplyConfiguration() { Settings::values.cpu_accuracy = static_cast<Settings::CPUAccuracy>(ui->accuracy->currentIndex()); + Settings::values.cpuopt_unsafe_unfuse_fma = ui->cpuopt_unsafe_unfuse_fma->isChecked(); + Settings::values.cpuopt_unsafe_reduce_fp_error = ui->cpuopt_unsafe_reduce_fp_error->isChecked(); } void ConfigureCpu::changeEvent(QEvent* event) { diff --git a/src/yuzu/configuration/configure_cpu.h b/src/yuzu/configuration/configure_cpu.h index e4741d3a4..3c5683d81 100644 --- a/src/yuzu/configuration/configure_cpu.h +++ b/src/yuzu/configuration/configure_cpu.h @@ -26,6 +26,7 @@ private: void RetranslateUI(); void AccuracyUpdated(int index); + void UpdateGroup(int index); void SetConfiguration(); diff --git a/src/yuzu/configuration/configure_cpu.ui b/src/yuzu/configuration/configure_cpu.ui index bf6ea79bb..ebdd2e6e9 100644 --- a/src/yuzu/configuration/configure_cpu.ui +++ b/src/yuzu/configuration/configure_cpu.ui @@ -40,6 +40,11 @@ </item> <item> <property name="text"> + <string>Unsafe</string> + </property> + </item> + <item> + <property name="text"> <string>Enable Debug Mode</string> </property> </item> @@ -63,6 +68,53 @@ </layout> </item> <item> + <layout class="QVBoxLayout"> + <item> + <widget class="QGroupBox" name="unsafe_group"> + <property name="title"> + <string>Unsafe CPU Optimization Settings</string> + </property> + <layout class="QVBoxLayout"> + <item> + <widget class="QLabel"> + <property name="wordWrap"> + <bool>1</bool> + </property> + <property name="text"> + <string>These settings reduce accuracy for speed.</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="cpuopt_unsafe_unfuse_fma"> + <property name="text"> + <string>Unfuse FMA (improve performance on CPUs without FMA)</string> + </property> + <property name="toolTip"> + <string> + <div>This option improves speed by reducing accuracy of fused-multiply-add instructions on CPUs without native FMA support.</div> + </string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="cpuopt_unsafe_reduce_fp_error"> + <property name="text"> + <string>Faster FRSQRTE and FRECPE</string> + </property> + <property name="toolTip"> + <string> + <div>This option improves the speed of some approximate floating-point functions by using less accurate native approximations.</div> + </string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </item> + <item> <spacer name="verticalSpacer"> <property name="orientation"> <enum>Qt::Vertical</enum> |