diff options
-rw-r--r-- | src/common/settings.cpp | 8 | ||||
-rw-r--r-- | src/common/settings.h | 4 | ||||
-rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_32.cpp | 5 | ||||
-rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_64.cpp | 8 | ||||
-rw-r--r-- | src/core/memory.cpp | 14 | ||||
-rw-r--r-- | src/yuzu/configuration/config.cpp | 7 | ||||
-rw-r--r-- | src/yuzu/configuration/configure_cpu.cpp | 9 | ||||
-rw-r--r-- | src/yuzu/configuration/configure_cpu.h | 1 | ||||
-rw-r--r-- | src/yuzu/configuration/configure_cpu.ui | 12 | ||||
-rw-r--r-- | src/yuzu/configuration/configure_cpu_debug.cpp | 3 | ||||
-rw-r--r-- | src/yuzu/configuration/configure_cpu_debug.ui | 14 | ||||
-rw-r--r-- | src/yuzu_cmd/default_ini.h | 4 |
12 files changed, 83 insertions, 6 deletions
diff --git a/src/common/settings.cpp b/src/common/settings.cpp index bcb4e4be1..360e878d6 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp @@ -90,6 +90,13 @@ bool IsGPULevelHigh() { values.gpu_accuracy.GetValue() == GPUAccuracy::High; } +bool IsFastmemEnabled() { + if (values.cpu_accuracy.GetValue() == CPUAccuracy::DebugMode) { + return values.cpuopt_fastmem; + } + return true; +} + float Volume() { if (values.audio_muted) { return 0.0f; @@ -115,6 +122,7 @@ void RestoreGlobalState(bool is_powered_on) { values.cpuopt_unsafe_unfuse_fma.SetGlobal(true); values.cpuopt_unsafe_reduce_fp_error.SetGlobal(true); values.cpuopt_unsafe_inaccurate_nan.SetGlobal(true); + values.cpuopt_unsafe_fastmem_check.SetGlobal(true); // Renderer values.renderer_backend.SetGlobal(true); diff --git a/src/common/settings.h b/src/common/settings.h index 48085b9a9..1af8c5ac2 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -125,10 +125,12 @@ struct Values { bool cpuopt_const_prop; bool cpuopt_misc_ir; bool cpuopt_reduce_misalign_checks; + bool cpuopt_fastmem; Setting<bool> cpuopt_unsafe_unfuse_fma; Setting<bool> cpuopt_unsafe_reduce_fp_error; Setting<bool> cpuopt_unsafe_inaccurate_nan; + Setting<bool> cpuopt_unsafe_fastmem_check; // Renderer Setting<RendererBackend> renderer_backend; @@ -249,6 +251,8 @@ void SetConfiguringGlobal(bool is_global); bool IsGPULevelExtreme(); bool IsGPULevelHigh(); +bool IsFastmemEnabled(); + float Volume(); std::string GetTimeZoneString(); diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index fb128f735..c8f6dc765 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp @@ -144,7 +144,7 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable* // Code cache size config.code_cache_size = 512 * 1024 * 1024; - config.far_code_offset = 256 * 1024 * 1024; + config.far_code_offset = 400 * 1024 * 1024; // Safe optimizations if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::DebugMode) { @@ -172,6 +172,9 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable* if (!Settings::values.cpuopt_reduce_misalign_checks) { config.only_detect_misalignment_via_page_table_on_page_boundary = false; } + if (!Settings::values.cpuopt_fastmem) { + config.fastmem_pointer = nullptr; + } } // Unsafe optimizations diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index b0ac8cf8a..ba524cd05 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp @@ -185,7 +185,7 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable* // Code cache size config.code_cache_size = 512 * 1024 * 1024; - config.far_code_offset = 256 * 1024 * 1024; + config.far_code_offset = 400 * 1024 * 1024; // Safe optimizations if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::DebugMode) { @@ -213,6 +213,9 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable* if (!Settings::values.cpuopt_reduce_misalign_checks) { config.only_detect_misalignment_via_page_table_on_page_boundary = false; } + if (!Settings::values.cpuopt_fastmem) { + config.fastmem_pointer = nullptr; + } } // Unsafe optimizations @@ -227,6 +230,9 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable* if (Settings::values.cpuopt_unsafe_inaccurate_nan.GetValue()) { config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_InaccurateNaN; } + if (Settings::values.cpuopt_unsafe_fastmem_check.GetValue()) { + config.fastmem_address_space_bits = 64; + } } return std::make_shared<Dynarmic::A64::Jit>(config); diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 79468e4dc..f285c6f63 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -47,7 +47,9 @@ struct Memory::Impl { "Out of bounds target: {:016X}", target); MapPages(page_table, base / PAGE_SIZE, size / PAGE_SIZE, target, Common::PageType::Memory); - system.DeviceMemory().buffer.Map(base, target - DramMemoryMap::Base, size); + if (Settings::IsFastmemEnabled()) { + system.DeviceMemory().buffer.Map(base, target - DramMemoryMap::Base, size); + } } void UnmapRegion(Common::PageTable& page_table, VAddr base, u64 size) { @@ -55,7 +57,9 @@ struct Memory::Impl { ASSERT_MSG((base & PAGE_MASK) == 0, "non-page aligned base: {:016X}", base); MapPages(page_table, base / PAGE_SIZE, size / PAGE_SIZE, 0, Common::PageType::Unmapped); - system.DeviceMemory().buffer.Unmap(base, size); + if (Settings::IsFastmemEnabled()) { + system.DeviceMemory().buffer.Unmap(base, size); + } } bool IsValidVirtualAddress(const Kernel::KProcess& process, const VAddr vaddr) const { @@ -475,8 +479,10 @@ struct Memory::Impl { return; } - const bool is_read_enable = Settings::IsGPULevelHigh() || !cached; - system.DeviceMemory().buffer.Protect(vaddr, size, is_read_enable, !cached); + if (Settings::IsFastmemEnabled()) { + const bool is_read_enable = Settings::IsGPULevelHigh() || !cached; + system.DeviceMemory().buffer.Protect(vaddr, size, is_read_enable, !cached); + } // Iterate over a contiguous CPU address space, which corresponds to the specified GPU // address space, marking the region as un/cached. The region is marked un/cached at a diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index e9d4bef60..a59b36e13 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -756,6 +756,8 @@ void Config::ReadCpuValues() { QStringLiteral("cpuopt_unsafe_reduce_fp_error"), true); ReadSettingGlobal(Settings::values.cpuopt_unsafe_inaccurate_nan, QStringLiteral("cpuopt_unsafe_inaccurate_nan"), true); + ReadSettingGlobal(Settings::values.cpuopt_unsafe_fastmem_check, + QStringLiteral("cpuopt_unsafe_fastmem_check"), true); if (global) { Settings::values.cpuopt_page_tables = @@ -774,6 +776,8 @@ 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_fastmem = + ReadSetting(QStringLiteral("cpuopt_fastmem"), true).toBool(); } qt_config->endGroup(); @@ -1332,6 +1336,8 @@ void Config::SaveCpuValues() { Settings::values.cpuopt_unsafe_reduce_fp_error, true); WriteSettingGlobal(QStringLiteral("cpuopt_unsafe_inaccurate_nan"), Settings::values.cpuopt_unsafe_inaccurate_nan, true); + WriteSettingGlobal(QStringLiteral("cpuopt_unsafe_fastmem_check"), + Settings::values.cpuopt_unsafe_fastmem_check, true); if (global) { WriteSetting(QStringLiteral("cpuopt_page_tables"), Settings::values.cpuopt_page_tables, @@ -1348,6 +1354,7 @@ 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_fastmem"), Settings::values.cpuopt_fastmem, true); } qt_config->endGroup(); diff --git a/src/yuzu/configuration/configure_cpu.cpp b/src/yuzu/configuration/configure_cpu.cpp index 525c42ff0..22219cbad 100644 --- a/src/yuzu/configuration/configure_cpu.cpp +++ b/src/yuzu/configuration/configure_cpu.cpp @@ -35,12 +35,15 @@ void ConfigureCpu::SetConfiguration() { ui->cpuopt_unsafe_unfuse_fma->setEnabled(runtime_lock); ui->cpuopt_unsafe_reduce_fp_error->setEnabled(runtime_lock); ui->cpuopt_unsafe_inaccurate_nan->setEnabled(runtime_lock); + ui->cpuopt_unsafe_fastmem_check->setEnabled(runtime_lock); ui->cpuopt_unsafe_unfuse_fma->setChecked(Settings::values.cpuopt_unsafe_unfuse_fma.GetValue()); ui->cpuopt_unsafe_reduce_fp_error->setChecked( Settings::values.cpuopt_unsafe_reduce_fp_error.GetValue()); ui->cpuopt_unsafe_inaccurate_nan->setChecked( Settings::values.cpuopt_unsafe_inaccurate_nan.GetValue()); + ui->cpuopt_unsafe_fastmem_check->setChecked( + Settings::values.cpuopt_unsafe_fastmem_check.GetValue()); if (Settings::IsConfiguringGlobal()) { ui->accuracy->setCurrentIndex(static_cast<int>(Settings::values.cpu_accuracy.GetValue())); @@ -84,6 +87,9 @@ void ConfigureCpu::ApplyConfiguration() { ConfigurationShared::ApplyPerGameSetting(&Settings::values.cpuopt_unsafe_inaccurate_nan, ui->cpuopt_unsafe_inaccurate_nan, cpuopt_unsafe_inaccurate_nan); + ConfigurationShared::ApplyPerGameSetting(&Settings::values.cpuopt_unsafe_fastmem_check, + ui->cpuopt_unsafe_fastmem_check, + cpuopt_unsafe_fastmem_check); if (Settings::IsConfiguringGlobal()) { // Guard if during game and set to game-specific value @@ -134,4 +140,7 @@ void ConfigureCpu::SetupPerGameUI() { ConfigurationShared::SetColoredTristate(ui->cpuopt_unsafe_inaccurate_nan, Settings::values.cpuopt_unsafe_inaccurate_nan, cpuopt_unsafe_inaccurate_nan); + ConfigurationShared::SetColoredTristate(ui->cpuopt_unsafe_fastmem_check, + Settings::values.cpuopt_unsafe_fastmem_check, + cpuopt_unsafe_fastmem_check); } diff --git a/src/yuzu/configuration/configure_cpu.h b/src/yuzu/configuration/configure_cpu.h index 8e2eeb7a6..57ff2772a 100644 --- a/src/yuzu/configuration/configure_cpu.h +++ b/src/yuzu/configuration/configure_cpu.h @@ -41,4 +41,5 @@ private: ConfigurationShared::CheckState cpuopt_unsafe_unfuse_fma; ConfigurationShared::CheckState cpuopt_unsafe_reduce_fp_error; ConfigurationShared::CheckState cpuopt_unsafe_inaccurate_nan; + ConfigurationShared::CheckState cpuopt_unsafe_fastmem_check; }; diff --git a/src/yuzu/configuration/configure_cpu.ui b/src/yuzu/configuration/configure_cpu.ui index 99b573640..31ef9e3f5 100644 --- a/src/yuzu/configuration/configure_cpu.ui +++ b/src/yuzu/configuration/configure_cpu.ui @@ -123,6 +123,18 @@ </property> </widget> </item> + <item> + <widget class="QCheckBox" name="cpuopt_unsafe_fastmem_check"> + <property name="toolTip"> + <string> + <div>This option improves speed by eliminating a safety check before every memory read/write in guest. Disabling it may allow a game to read/write the emulator's memory.</div> + </string> + </property> + <property name="text"> + <string>Disable address space checks</string> + </property> + </widget> + </item> </layout> </widget> </item> diff --git a/src/yuzu/configuration/configure_cpu_debug.cpp b/src/yuzu/configuration/configure_cpu_debug.cpp index c925c023c..e25c52baf 100644 --- a/src/yuzu/configuration/configure_cpu_debug.cpp +++ b/src/yuzu/configuration/configure_cpu_debug.cpp @@ -39,6 +39,8 @@ void ConfigureCpuDebug::SetConfiguration() { ui->cpuopt_misc_ir->setChecked(Settings::values.cpuopt_misc_ir); ui->cpuopt_reduce_misalign_checks->setEnabled(runtime_lock); ui->cpuopt_reduce_misalign_checks->setChecked(Settings::values.cpuopt_reduce_misalign_checks); + ui->cpuopt_fastmem->setEnabled(runtime_lock); + ui->cpuopt_fastmem->setChecked(Settings::values.cpuopt_fastmem); } void ConfigureCpuDebug::ApplyConfiguration() { @@ -50,6 +52,7 @@ void ConfigureCpuDebug::ApplyConfiguration() { Settings::values.cpuopt_const_prop = ui->cpuopt_const_prop->isChecked(); Settings::values.cpuopt_misc_ir = ui->cpuopt_misc_ir->isChecked(); Settings::values.cpuopt_reduce_misalign_checks = ui->cpuopt_reduce_misalign_checks->isChecked(); + Settings::values.cpuopt_fastmem = ui->cpuopt_fastmem->isChecked(); } void ConfigureCpuDebug::changeEvent(QEvent* event) { diff --git a/src/yuzu/configuration/configure_cpu_debug.ui b/src/yuzu/configuration/configure_cpu_debug.ui index a90dc64fe..11ee19a12 100644 --- a/src/yuzu/configuration/configure_cpu_debug.ui +++ b/src/yuzu/configuration/configure_cpu_debug.ui @@ -139,6 +139,20 @@ </property> </widget> </item> + <item> + <widget class="QCheckBox" name="cpuopt_fastmem"> + <property name="text"> + <string>Enable Host MMU Emulation</string> + </property> + <property name="toolTip"> + <string> + <div style="white-space: nowrap">This optimization speeds up memory accesses by the guest program.</div> + <div style="white-space: nowrap">Enabling it causes guest memory reads/writes to be done directly into memory and make use of Host's MMU.</div> + <div style="white-space: nowrap">Disabling this forces all memory accesses to use Software MMU Emulation.</div> + </string> + </property> + </widget> + </item> </layout> </widget> </item> diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h index 8ce2967ac..f48d935a1 100644 --- a/src/yuzu_cmd/default_ini.h +++ b/src/yuzu_cmd/default_ini.h @@ -150,6 +150,10 @@ cpuopt_misc_ir = # 0: Disabled, 1 (default): Enabled cpuopt_reduce_misalign_checks = +# Enable Host MMU Emulation (faster guest memory access) +# 0: Disabled, 1 (default): Enabled +cpuopt_fastmem = + [Renderer] # Which backend API to use. # 0 (default): OpenGL, 1: Vulkan |