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 a558afab47..fe778d8370 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
@@ -17,6 +17,7 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting {
RENDERER_USE_SPEED_LIMIT("use_speed_limit"),
USE_FAST_CPU_TIME("use_fast_cpu_time"),
USE_CUSTOM_CPU_TICKS("use_custom_cpu_ticks"),
+ FORCE_GPU_BLIT("force_gpu_blit"),
SKIP_CPU_INNER_INVALIDATION("skip_cpu_inner_invalidation"),
USE_DOCKED_MODE("use_docked_mode"),
USE_AUTO_STUB("use_auto_stub"),
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 ab35a9180c..2d13796172 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
@@ -655,6 +655,13 @@ abstract class SettingsItem(
max = 65535
)
)
+ put(
+ SwitchSetting(
+ BooleanSetting.FORCE_GPU_BLIT,
+ titleId = R.string.force_gpu_blit,
+ descriptionId = R.string.force_gpu_blit_description
+ )
+ )
put(
SwitchSetting(
BooleanSetting.SKIP_CPU_INNER_INVALIDATION,
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 31e2873b58..0caf37afdb 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
@@ -463,6 +463,7 @@ class SettingsFragmentPresenter(
add(IntSetting.FAST_CPU_TIME.key)
add(BooleanSetting.USE_CUSTOM_CPU_TICKS.key)
add(IntSetting.CPU_TICKS.key)
+ add(BooleanSetting.FORCE_GPU_BLIT.key)
add(BooleanSetting.SKIP_CPU_INNER_INVALIDATION.key)
add(BooleanSetting.USE_LRU_CACHE.key)
add(BooleanSetting.CORE_SYNC_CORE_SPEED.key)
diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml
index e611e66c1f..8a104ae560 100644
--- a/src/android/app/src/main/res/values/strings.xml
+++ b/src/android/app/src/main/res/values/strings.xml
@@ -103,8 +103,10 @@
Fast CPU Time
Forces the emulated CPU to run at a higher clock, reducing certain FPS limiters. This option is hacky and may cause issues, and weaker CPUs may see reduced performance.
Custom CPU Ticks
- Set a custom value of CPU ticks. Higher values can increase performance, but may also cause the game to freeze. A range of 77–21000 is recommended.
+ Set a custom value of CPU ticks. Higher values can increase performance, but may also cause the game to freeze. A range of 77 to 21000 is recommended.
Ticks
+ Force GPU Blit
+ Forces all surface copy operations to use GPU acceleration. If your system fails to perform a hardware-accelerated copy, the operation will be skipped and software fallback will not be used. This may significantly improve the performance, but may cause rendering issues on some games.
Skip CPU Inner Invalidation
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.
CPU Clock
diff --git a/src/common/settings.h b/src/common/settings.h
index 551e66c57e..75946bd1ae 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -450,8 +450,15 @@ struct Values {
VramUsageMode::Aggressive,
"vram_usage_mode",
Category::RendererAdvanced};
+ SwitchableSetting force_gpu_blit{linkage,
+ false,
+ "force_gpu_blit",
+ Category::RendererAdvanced,
+ Specialization::Default,
+ true,
+ true};
SwitchableSetting skip_cpu_inner_invalidation{linkage,
- true,
+ false,
"skip_cpu_inner_invalidation",
Category::RendererAdvanced,
Specialization::Default,
diff --git a/src/video_core/engines/fermi_2d.cpp b/src/video_core/engines/fermi_2d.cpp
index 94239b80f8..690c99aba2 100644
--- a/src/video_core/engines/fermi_2d.cpp
+++ b/src/video_core/engines/fermi_2d.cpp
@@ -114,9 +114,14 @@ void Fermi2D::Blit() {
}
memory_manager.FlushCaching();
- /*if (!rasterizer->AccelerateSurfaceCopy(src, regs.dst, config)) {
+
+ if (!rasterizer->AccelerateSurfaceCopy(src, regs.dst, config)) {
+ if (Settings::values.force_gpu_blit.GetValue()) {
+ LOG_ERROR(HW_GPU, "AccelerateSurfaceCopy failed, and GPU blit is forced.");
+ return;
+ }
sw_blitter->Blit(src, regs.dst, config);
- }*/
+ }
}
} // namespace Tegra::Engines
diff --git a/src/yuzu/configuration/shared_translation.cpp b/src/yuzu/configuration/shared_translation.cpp
index c743e65ae3..7d4ed9d370 100644
--- a/src/yuzu/configuration/shared_translation.cpp
+++ b/src/yuzu/configuration/shared_translation.cpp
@@ -250,6 +250,12 @@ std::unique_ptr InitializeTranslations(QWidget* parent)
"of available video memory for performance. Has no effect on integrated graphics. "
"Aggressive mode may severely impact the performance of other applications such as "
"recording software."));
+ INSERT(Settings,
+ force_gpu_blit,
+ tr("Force GPU Blit"),
+ tr("Forces all surface copy operations to use GPU acceleration. If your system fails to "
+ "perform a hardware-accelerated copy, the operation will be skipped and software fallback will not be used. "
+ "This may significantly improve the performance, but may cause rendering issues on some games."));
INSERT(Settings,
skip_cpu_inner_invalidation,
tr("Skip CPU Inner Invalidation"),