diff options
8 files changed, 69 insertions, 31 deletions
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt index 97be7f1bd9..239d56837c 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt @@ -16,6 +16,8 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting { RENDERER_USE_SPEED_LIMIT("use_speed_limit"), USE_CUSTOM_CPU_TICKS("use_custom_cpu_ticks"), SKIP_CPU_INNER_INVALIDATION("skip_cpu_inner_invalidation"), + NCE_INVALIDATION_GPU_READBACK("nce_invalidation_gpu_readback"), + NCE_RUNTIME_NRO_PATCH("nce_runtime_nro_patch"), FIX_BLOOM_EFFECTS("fix_bloom_effects"), EMULATE_BGR565("emulate_bgr565"), RESCALE_HACK("rescale_hack"), diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt index 366d3a8b3b..ef52b23053 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt @@ -868,6 +868,20 @@ abstract class SettingsItem( ) put( SwitchSetting( + BooleanSetting.NCE_INVALIDATION_GPU_READBACK, + titleId = R.string.nce_invalidation_gpu_readback, + descriptionId = R.string.nce_invalidation_gpu_readback_description + ) + ) + put( + SwitchSetting( + BooleanSetting.NCE_RUNTIME_NRO_PATCH, + titleId = R.string.nce_runtime_nro_patch, + descriptionId = R.string.nce_runtime_nro_patch_description + ) + ) + put( + SwitchSetting( BooleanSetting.FIX_BLOOM_EFFECTS, titleId = R.string.fix_bloom_effects, descriptionId = R.string.fix_bloom_effects_description diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt index e9f818d9bc..dccc8b859a 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt @@ -554,6 +554,8 @@ class SettingsFragmentPresenter( add(HeaderSetting(R.string.hacks)) add(BooleanSetting.SKIP_CPU_INNER_INVALIDATION.key) + add(BooleanSetting.NCE_INVALIDATION_GPU_READBACK.key) + add(BooleanSetting.NCE_RUNTIME_NRO_PATCH.key) add(BooleanSetting.FIX_BLOOM_EFFECTS.key) add(BooleanSetting.EMULATE_BGR565.key) add(BooleanSetting.RENDERER_ASYNCHRONOUS_SHADERS.key) diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index 5a587be351..e48319f483 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -595,6 +595,10 @@ <string name="fast_gpu_time_description">Makes the game believe GPU work finishes faster than it does, so it stops lowering resolution and render distance to fit the Switch\'s clocks.</string> <string name="skip_cpu_inner_invalidation">Skip CPU Inner Invalidation</string> <string name="skip_cpu_inner_invalidation_description">Skips certain CPU-side cache invalidations during memory updates, reducing CPU usage and improving it\'s performance. This may cause glitches or crashes on some games.</string> + <string name="nce_invalidation_gpu_readback">GPU Readback Before NCE Invalidation</string> + <string name="nce_invalidation_gpu_readback_description">Temporary. Fix Ender Magnolia (and other UE titles) crashes. May reduce performance. Improvement in progress.</string> + <string name="nce_runtime_nro_patch">Patch Runtime NROs for NCE</string> + <string name="nce_runtime_nro_patch_description">Temporary. Fix Biomutant boot. May impact performance. Improvement in progress.</string> <string name="fix_bloom_effects">Fix Bloom Effects</string> <string name="fix_bloom_effects_description">Reduces bloom blur in LA/EOW (Adreno A6XX - A7XX/ Turnip), removes bloom in Burnout. Warning: may cause graphical artifacts in other games.</string> <string name="emulate_bgr565">Emulate BGR565</string> diff --git a/src/common/settings.h b/src/common/settings.h index 5d66f49ebd..d4c445c27c 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -639,6 +639,10 @@ struct Values { Specialization::Default, true, true}; + SwitchableSetting<bool> nce_invalidation_gpu_readback{ + linkage, false, "nce_invalidation_gpu_readback", Category::RendererHacks}; + SwitchableSetting<bool> nce_runtime_nro_patch{ + linkage, false, "nce_runtime_nro_patch", Category::RendererHacks}; SwitchableSetting<bool> async_presentation{linkage, #ifdef __ANDROID__ false, diff --git a/src/core/hle/service/ro/ro.cpp b/src/core/hle/service/ro/ro.cpp index b847811fe5..167bf04c9a 100644 --- a/src/core/hle/service/ro/ro.cpp +++ b/src/core/hle/service/ro/ro.cpp @@ -426,28 +426,30 @@ public: std::addressof(ro_size), std::addressof(rw_size), nro_info->base_address, nro_size, bss_size)); #ifdef HAS_NCE - if (Settings::IsNceEnabled()) { - auto* process = context->GetProcess(); - auto& memory = process->GetMemory(); - - std::vector<u8> image(total_size); - memory.ReadBlock(nro_info->base_address, image.data(), rx_size); - - Kernel::CodeSet::Segment code{.size = static_cast<u32>(rx_size)}; - Core::NCE::Patcher patch; - patch.PatchText(image, code); - patch.RelocateAndCopy(nro_info->base_address, code, image, nullptr); - - const u64 patch_address = nro_info->base_address + total_size; - const size_t patch_size = patch.GetSectionSize(); - constexpr auto permission = Kernel::Svc::MemoryPermission::ReadExecute; - - auto* patch_memory = Kernel::KSharedMemory::Create(kernel); - R_TRY(patch_memory->Initialize(kernel, kernel.System().DeviceMemory(), process, permission, permission, patch_size)); - std::memcpy(patch_memory->GetPointer(), image.data() + total_size, patch_size); - R_TRY(process->AddSharedMemory(kernel, patch_memory, patch_address, patch_size)); - R_TRY(patch_memory->Map(*process, patch_address, patch_size, permission)); - memory.WriteBlock(nro_info->base_address, image.data(), rx_size); + if (Settings::values.nce_runtime_nro_patch.GetValue()) { + if (Settings::IsNceEnabled()) { + auto* process = context->GetProcess(); + auto& memory = process->GetMemory(); + + std::vector<u8> image(total_size); + memory.ReadBlock(nro_info->base_address, image.data(), rx_size); + + Kernel::CodeSet::Segment code{.size = static_cast<u32>(rx_size)}; + Core::NCE::Patcher patch; + patch.PatchText(image, code); + patch.RelocateAndCopy(nro_info->base_address, code, image, nullptr); + + const u64 patch_address = nro_info->base_address + total_size; + const size_t patch_size = patch.GetSectionSize(); + constexpr auto permission = Kernel::Svc::MemoryPermission::ReadExecute; + + auto* patch_memory = Kernel::KSharedMemory::Create(kernel); + R_TRY(patch_memory->Initialize(kernel, kernel.System().DeviceMemory(), process, permission, permission, patch_size)); + std::memcpy(patch_memory->GetPointer(), image.data() + total_size, patch_size); + R_TRY(process->AddSharedMemory(kernel, patch_memory, patch_address, patch_size)); + R_TRY(patch_memory->Map(*process, patch_address, patch_size, permission)); + memory.WriteBlock(nro_info->base_address, image.data(), rx_size); + } } #endif // Set NRO perms. diff --git a/src/qt_common/config/shared_translation.cpp b/src/qt_common/config/shared_translation.cpp index 29fbd32de5..0fe2366dfc 100644 --- a/src/qt_common/config/shared_translation.cpp +++ b/src/qt_common/config/shared_translation.cpp @@ -194,6 +194,14 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QObject* parent) { INSERT(Settings, skip_cpu_inner_invalidation, tr("Skip CPU Inner Invalidation"), tr("Skips certain cache invalidations during memory updates, reducing CPU usage and " "improving latency. This may cause soft-crashes.")); + INSERT(Settings, nce_invalidation_gpu_readback, + tr("GPU Readback Before NCE Invalidation"), + tr("Flushes GPU buffer data back to guest memory before NCE invalidates the whole " + "guest page, preserving it while the CPU store proceeds.")); + INSERT(Settings, nce_runtime_nro_patch, + tr("Patch Runtime NROs for NCE"), + tr("Applies NCE code patches to runtime-loaded NRO modules." + "This is required for some games to run correctly.")); INSERT(Settings, vsync_mode, tr("VSync Mode:"), tr("FIFO (VSync) does not drop frames or exhibit tearing but is limited by the screen " "refresh rate.\nFIFO Relaxed allows tearing as it recovers from a slow down.\n" diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index 6aa7f9abd8..4e36d086e6 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp @@ -227,15 +227,17 @@ struct GPU::Impl { /// Notify rasterizer that any caches of the specified region should be invalidated void InvalidateRegion(DAddr addr, u64 size, bool preserve_gpu_writes) { - VideoCore::RasterizerInterface* rasterizer = renderer->ReadRasterizer(); - if (preserve_gpu_writes && rasterizer->MustFlushRegion(addr, size, VideoCommon::CacheType::BufferCache)) { - const u64 fence = RequestSyncOperation([rasterizer, addr, size] { - rasterizer->FlushRegion(addr, size, VideoCommon::CacheType::BufferCache); - rasterizer->OnCacheInvalidation(addr, size); - }); - gpu_thread.TickGPU(is_async); - WaitForSyncOperation(fence); - return; + if (Settings::values.nce_invalidation_gpu_readback.GetValue()) { + VideoCore::RasterizerInterface* rasterizer = renderer->ReadRasterizer(); + if (preserve_gpu_writes && rasterizer->MustFlushRegion(addr, size, VideoCommon::CacheType::BufferCache)) { + const u64 fence = RequestSyncOperation([rasterizer, addr, size] { + rasterizer->FlushRegion(addr, size, VideoCommon::CacheType::BufferCache); + rasterizer->OnCacheInvalidation(addr, size); + }); + gpu_thread.TickGPU(is_async); + WaitForSyncOperation(fence); + return; + } } gpu_thread.InvalidateRegion(addr, size); } |
