diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/BooleanSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/BooleanSetting.kt
index ef62087e1..997e30a30 100644
--- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/BooleanSetting.kt
+++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/BooleanSetting.kt
@@ -12,6 +12,7 @@ enum class BooleanSetting(
EXPAND_TO_CUTOUT_AREA("expand_to_cutout_area", Settings.SECTION_LAYOUT, false),
SPIRV_SHADER_GEN("spirv_shader_gen", Settings.SECTION_RENDERER, true),
ASYNC_SHADERS("async_shader_compilation", Settings.SECTION_RENDERER, false),
+ DISABLE_SPIRV_OPTIMIZER("disable_spirv_optimizer", Settings.SECTION_RENDERER, true),
PLUGIN_LOADER("plugin_loader", Settings.SECTION_SYSTEM, false),
ALLOW_PLUGIN_LOADER("allow_plugin_loader", Settings.SECTION_SYSTEM, true),
SWAP_SCREEN("swap_screen", Settings.SECTION_LAYOUT, false),
diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt
index fc0b40d67..70b896e92 100644
--- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt
+++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt
@@ -839,6 +839,15 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
BooleanSetting.SPIRV_SHADER_GEN.defaultValue,
)
)
+ add(
+ SwitchSetting(
+ BooleanSetting.DISABLE_SPIRV_OPTIMIZER,
+ R.string.disable_spirv_optimizer,
+ R.string.disable_spirv_optimizer_description,
+ BooleanSetting.DISABLE_SPIRV_OPTIMIZER.key,
+ BooleanSetting.DISABLE_SPIRV_OPTIMIZER.defaultValue,
+ )
+ )
add(
SwitchSetting(
BooleanSetting.ASYNC_SHADERS,
diff --git a/src/android/app/src/main/jni/config.cpp b/src/android/app/src/main/jni/config.cpp
index 9df017a6f..b46333ada 100644
--- a/src/android/app/src/main/jni/config.cpp
+++ b/src/android/app/src/main/jni/config.cpp
@@ -142,6 +142,7 @@ void Config::ReadValues() {
ReadSetting("Renderer", Settings::values.async_presentation);
ReadSetting("Renderer", Settings::values.async_shader_compilation);
ReadSetting("Renderer", Settings::values.spirv_shader_gen);
+ ReadSetting("Renderer", Settings::values.disable_spirv_optimizer);
ReadSetting("Renderer", Settings::values.use_hw_shader);
ReadSetting("Renderer", Settings::values.use_shader_jit);
ReadSetting("Renderer", Settings::values.resolution_factor);
diff --git a/src/android/app/src/main/jni/default_ini.h b/src/android/app/src/main/jni/default_ini.h
index f3a6a169a..83fa897fa 100644
--- a/src/android/app/src/main/jni/default_ini.h
+++ b/src/android/app/src/main/jni/default_ini.h
@@ -113,6 +113,10 @@ async_shader_compilation =
# 0: GLSL, 1: SPIR-V (default)
spirv_shader_gen =
+# Whether to disable the SPIRV optimizer. Disabling it reduces stutter, but may slightly worsen performance
+# 0: Enabled, 1: Disabled (default)
+disable_spirv_optimizer =
+
# Whether to use hardware shaders to emulate 3DS shaders
# 0: Software, 1 (default): Hardware
use_hw_shader =
diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml
index 19e570f21..922c25476 100644
--- a/src/android/app/src/main/res/values/strings.xml
+++ b/src/android/app/src/main/res/values/strings.xml
@@ -870,5 +870,7 @@
Quickload
Quicksave - %1$tF %1$tR
No Quicksave available.
+ Disable SPIR-V Optimizer
+ Disables the SPIR-V optimization pass, reducing stuttering considerably while barely affecting performance.
diff --git a/src/citra_qt/configuration/configure_graphics.cpp b/src/citra_qt/configuration/configure_graphics.cpp
index d06f5a97d..eb706fb56 100644
--- a/src/citra_qt/configuration/configure_graphics.cpp
+++ b/src/citra_qt/configuration/configure_graphics.cpp
@@ -1,4 +1,4 @@
-// Copyright 2016 Citra Emulator Project
+// Copyright Citra Emulator Project / Azahar Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
@@ -59,6 +59,7 @@ ConfigureGraphics::ConfigureGraphics(QString gl_renderer, std::spanphysical_device_combo->setVisible(false);
ui->spirv_shader_gen->setVisible(false);
+ ui->disable_spirv_optimizer->setVisible(false);
} else {
for (const QString& name : physical_devices) {
ui->physical_device_combo->addItem(name);
@@ -143,6 +144,7 @@ void ConfigureGraphics::SetConfiguration() {
ui->toggle_disk_shader_cache->setChecked(Settings::values.use_disk_shader_cache.GetValue());
ui->toggle_vsync_new->setChecked(Settings::values.use_vsync_new.GetValue());
ui->spirv_shader_gen->setChecked(Settings::values.spirv_shader_gen.GetValue());
+ ui->disable_spirv_optimizer->setChecked(Settings::values.disable_spirv_optimizer.GetValue());
ui->toggle_async_shaders->setChecked(Settings::values.async_shader_compilation.GetValue());
ui->toggle_async_present->setChecked(Settings::values.async_presentation.GetValue());
@@ -162,6 +164,8 @@ void ConfigureGraphics::ApplyConfiguration() {
ui->toggle_async_present, async_presentation);
ConfigurationShared::ApplyPerGameSetting(&Settings::values.spirv_shader_gen,
ui->spirv_shader_gen, spirv_shader_gen);
+ ConfigurationShared::ApplyPerGameSetting(&Settings::values.disable_spirv_optimizer,
+ ui->disable_spirv_optimizer, disable_spirv_optimizer);
ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_hw_shader, ui->toggle_hw_shader,
use_hw_shader);
ConfigurationShared::ApplyPerGameSetting(&Settings::values.shaders_accurate_mul,
@@ -241,6 +245,9 @@ void ConfigureGraphics::SetupPerGameUI() {
ui->toggle_async_present, Settings::values.async_presentation, async_presentation);
ConfigurationShared::SetColoredTristate(ui->spirv_shader_gen, Settings::values.spirv_shader_gen,
spirv_shader_gen);
+ ConfigurationShared::SetColoredTristate(ui->disable_spirv_optimizer,
+ Settings::values.disable_spirv_optimizer,
+ disable_spirv_optimizer);
}
void ConfigureGraphics::SetPhysicalDeviceComboVisibility(int index) {
@@ -263,5 +270,6 @@ void ConfigureGraphics::SetPhysicalDeviceComboVisibility(int index) {
ui->physical_device_group->setVisible(effective_api == Settings::GraphicsAPI::Vulkan);
ui->spirv_shader_gen->setVisible(effective_api == Settings::GraphicsAPI::Vulkan);
+ ui->disable_spirv_optimizer->setVisible(effective_api == Settings::GraphicsAPI::Vulkan);
ui->opengl_renderer_group->setVisible(effective_api == Settings::GraphicsAPI::OpenGL);
}
diff --git a/src/citra_qt/configuration/configure_graphics.h b/src/citra_qt/configuration/configure_graphics.h
index 129c4a9d5..1031b964a 100644
--- a/src/citra_qt/configuration/configure_graphics.h
+++ b/src/citra_qt/configuration/configure_graphics.h
@@ -1,4 +1,4 @@
-// Copyright 2016 Citra Emulator Project
+// Copyright Citra Emulator Project / Azahar Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
@@ -42,6 +42,7 @@ private:
ConfigurationShared::CheckState async_shader_compilation;
ConfigurationShared::CheckState async_presentation;
ConfigurationShared::CheckState spirv_shader_gen;
+ ConfigurationShared::CheckState disable_spirv_optimizer;
std::unique_ptr ui;
QColor bg_color;
};
diff --git a/src/citra_qt/configuration/configure_graphics.ui b/src/citra_qt/configuration/configure_graphics.ui
index b2ee3c279..fea3c523d 100644
--- a/src/citra_qt/configuration/configure_graphics.ui
+++ b/src/citra_qt/configuration/configure_graphics.ui
@@ -136,6 +136,16 @@
+ -
+
+
+ Disable GLSL -> SPIR-V Optimizer
+
+
+ <html><head/><body><p>Disables the SPIR-V optimization pass, reducing stuttering considerably while barely affecting performance.</p></body></html>
+
+
+
diff --git a/src/common/settings.h b/src/common/settings.h
index 19b3dfa48..c8e76179c 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -498,6 +498,7 @@ struct Values {
Setting renderer_debug{false, "renderer_debug"};
Setting dump_command_buffers{false, "dump_command_buffers"};
SwitchableSetting spirv_shader_gen{true, "spirv_shader_gen"};
+ SwitchableSetting disable_spirv_optimizer{true, "disable_spirv_optimizer"};
SwitchableSetting async_shader_compilation{false, "async_shader_compilation"};
SwitchableSetting async_presentation{true, "async_presentation"};
SwitchableSetting use_hw_shader{true, "use_hw_shader"};
diff --git a/src/video_core/renderer_vulkan/vk_shader_util.cpp b/src/video_core/renderer_vulkan/vk_shader_util.cpp
index 3d2f2f1d1..ee3db73de 100644
--- a/src/video_core/renderer_vulkan/vk_shader_util.cpp
+++ b/src/video_core/renderer_vulkan/vk_shader_util.cpp
@@ -1,4 +1,4 @@
-// Copyright 2023 Citra Emulator Project
+// Copyright Citra Emulator Project / Azahar Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
@@ -9,6 +9,7 @@
#include "common/assert.h"
#include "common/literals.h"
#include "common/logging/log.h"
+#include "common/settings.h"
#include "video_core/renderer_vulkan/vk_shader_util.h"
namespace Vulkan {
@@ -203,8 +204,8 @@ vk::ShaderModule Compile(std::string_view code, vk::ShaderStageFlagBits stage, v
spv::SpvBuildLogger logger;
glslang::SpvOptions options;
- // Enable optimizations on the generated SPIR-V code.
- options.disableOptimizer = false;
+ // Controls optimizations on the generated SPIR-V code.
+ options.disableOptimizer = Settings::values.disable_spirv_optimizer.GetValue();
options.validate = false;
options.optimizeSize = true;