aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt2
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt14
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt2
-rw-r--r--src/android/app/src/main/res/values/strings.xml4
-rw-r--r--src/common/settings.h4
-rw-r--r--src/core/hle/service/ro/ro.cpp46
-rw-r--r--src/qt_common/config/shared_translation.cpp8
-rw-r--r--src/video_core/gpu.cpp20
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);
}