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 458a20abab..8363116400 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
@@ -37,6 +37,7 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting {
RENDERER_PATCH_OLD_QCOM_DRIVERS("patch_old_qcom_drivers"),
RENDERER_VERTEX_INPUT_DYNAMIC_STATE("vertex_input_dynamic_state"),
RENDERER_DYNAMIC_RENDERING("dynamic_rendering"),
+ RENDERER_WORKGROUP_MEMORY_EXPLICIT_LAYOUT("workgroup_memory_explicit_layout"),
RENDERER_SAMPLE_SHADING("sample_shading"),
GPU_UNSWIZZLE_ENABLED("gpu_unswizzle_enabled"),
PICTURE_IN_PICTURE("picture_in_picture"),
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 bf13d36c11..7a19ab7df1 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
@@ -162,6 +162,13 @@ abstract class SettingsItem(
descriptionId = R.string.dynamic_rendering_description
)
)
+ put(
+ SwitchSetting(
+ BooleanSetting.RENDERER_WORKGROUP_MEMORY_EXPLICIT_LAYOUT,
+ titleId = R.string.workgroup_memory_explicit_layout,
+ descriptionId = R.string.workgroup_memory_explicit_layout_description
+ )
+ )
put(
SliderSetting(
IntSetting.RENDERER_SAMPLE_SHADING,
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 8a258bac92..555c51134c 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
@@ -314,6 +314,7 @@ class SettingsFragmentPresenter(
add(IntSetting.RENDERER_DYNA_STATE.key)
add(BooleanSetting.RENDERER_VERTEX_INPUT_DYNAMIC_STATE.key)
add(BooleanSetting.RENDERER_DYNAMIC_RENDERING.key)
+ add(BooleanSetting.RENDERER_WORKGROUP_MEMORY_EXPLICIT_LAYOUT.key)
add(IntSetting.RENDERER_SAMPLE_SHADING.key)
add(HeaderSetting(R.string.display))
diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml
index 25fd5f0003..a89133550c 100644
--- a/src/android/app/src/main/res/values/strings.xml
+++ b/src/android/app/src/main/res/values/strings.xml
@@ -546,6 +546,8 @@
Enabling this feature allows for more flexible vertex input handling, potentially reducing pipeline compilation time in vertex/buffer.
Dynamic Rendering
Render without render pass and framebuffer objects. Results vary by driver: some gain performance, others lose it.
+ Workgroup Memory Explicit Layout
+ Let shaders declare explicit layouts for workgroup memory. Disabled by default: some Qualcomm drivers are unstable with it.
Sample Shading
Allows the fragment shader to execute per sample in a multi-sampled fragment instead once per fragment. Improves graphics quality at the cost of some performance.
diff --git a/src/common/settings.h b/src/common/settings.h
index fa4a83374c..a52e89a247 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -638,6 +638,9 @@ struct Values {
SwitchableSetting dynamic_rendering{linkage, true, "dynamic_rendering",
Category::RendererExtensions};
+ SwitchableSetting workgroup_memory_explicit_layout{
+ linkage, false, "workgroup_memory_explicit_layout", Category::RendererExtensions};
+
SwitchableSetting pipeline_worker_count{
linkage, 2, 2, 8, "pipeline_worker_count", Category::RendererAdvanced,
Specialization::Scalar};
diff --git a/src/qt_common/config/shared_translation.cpp b/src/qt_common/config/shared_translation.cpp
index ca3c72638c..a787001503 100644
--- a/src/qt_common/config/shared_translation.cpp
+++ b/src/qt_common/config/shared_translation.cpp
@@ -294,6 +294,8 @@ std::unique_ptr InitializeTranslations(QObject* parent) {
tr("Renders without render pass and framebuffer objects.\n"
"Results vary by driver: some gain performance, others lose it."));
+ INSERT(Settings, workgroup_memory_explicit_layout, QString(), QString());
+
INSERT(
Settings, sample_shading, tr("Sample Shading"),
tr("Allows the fragment shader to execute per sample in a multi-sampled fragment "
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp
index 926fe1300d..c44c1eeae1 100644
--- a/src/video_core/vulkan_common/vulkan_device.cpp
+++ b/src/video_core/vulkan_common/vulkan_device.cpp
@@ -539,10 +539,6 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
features.shader_atomic_int64.shaderBufferInt64Atomics = false;
features.shader_atomic_int64.shaderSharedInt64Atomics = false;
features.features.shaderInt64 = false;
- LOG_WARNING(Render_Vulkan, "Qualcomm drivers have broken workgroup memory explicit layout.");
- RemoveExtensionFeature(extensions.workgroup_memory_explicit_layout,
- features.workgroup_memory_explicit_layout,
- VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_EXTENSION_NAME);
#if defined(__ANDROID__) && defined(ARCHITECTURE_arm64)
// BCn patching only safe on Android 9+ (API 28+). Older versions crash on driver load.
@@ -1514,6 +1510,12 @@ void Device::RemoveUnsuitableExtensions() {
}
// VK_KHR_workgroup_memory_explicit_layout
+#ifdef __ANDROID__
+ if (!Settings::values.workgroup_memory_explicit_layout.GetValue()) {
+ LOG_INFO(Render_Vulkan, "Workgroup memory explicit layout disabled by user setting");
+ features.workgroup_memory_explicit_layout.workgroupMemoryExplicitLayout = false;
+ }
+#endif
extensions.workgroup_memory_explicit_layout =
features.workgroup_memory_explicit_layout.workgroupMemoryExplicitLayout &&
features.workgroup_memory_explicit_layout.workgroupMemoryExplicitLayoutScalarBlockLayout;