From c2794985b2a4edbe4108776d404137c4d962d120 Mon Sep 17 00:00:00 2001 From: kleidis Date: Tue, 18 Nov 2025 18:41:47 +0100 Subject: [PATCH] [android] Wipe shader cache on GPU Driver change (#2984) A permanently dismissible warning dialog is shown to let the suer know of this change Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2984 Reviewed-by: Maufeat Reviewed-by: Caio Oliveira Reviewed-by: crueter Co-authored-by: kleidis Co-committed-by: kleidis --- .../features/settings/model/BooleanSetting.kt | 4 +- .../fragments/DriverManagerFragment.kt | 22 +++++++- .../yuzu/yuzu_emu/model/DriverViewModel.kt | 50 ++++++++++++++++++- .../app/src/main/jni/android_settings.h | 6 +-- .../app/src/main/res/values/strings.xml | 2 + 5 files changed, 78 insertions(+), 6 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 5c21ea7dc1..90d6110a62 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 @@ -69,7 +69,9 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting { SHOW_SHADERS_BUILDING("show_shaders_building"), DEBUG_FLUSH_BY_LINE("flush_line"), - USE_LRU_CACHE("use_lru_cache"); + USE_LRU_CACHE("use_lru_cache"), + + DONT_SHOW_DRIVER_SHADER_WARNING("dont_show_driver_shader_warning"); // external fun isFrameSkippingEnabled(): Boolean diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/DriverManagerFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/DriverManagerFragment.kt index f521343272..23334f05eb 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/DriverManagerFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/DriverManagerFragment.kt @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later package org.yuzu.yuzu_emu.fragments @@ -91,6 +91,12 @@ class DriverManagerFragment : Fragment() { } } + driverViewModel.shouldShowDriverShaderDialog.collect(viewLifecycleOwner) { shouldShow -> + if (shouldShow) { + showDriverShaderWipeDialog() + } + } + if (!driverViewModel.isInteractionAllowed.value) { DriversLoadingDialogFragment().show( childFragmentManager, @@ -236,4 +242,18 @@ class DriverManagerFragment : Fragment() { ).show(requireActivity().supportFragmentManager, MessageDialogFragment.TAG) } } + + private fun showDriverShaderWipeDialog() { + com.google.android.material.dialog.MaterialAlertDialogBuilder(requireContext()) + .setTitle(R.string.driver_shader_wipe_dialog_title) + .setMessage(R.string.driver_shader_wipe_dialog_message) + .setPositiveButton(android.R.string.ok) { _, _ -> + driverViewModel.onDriverShaderDialogDismissed(dontShowAgain = false) + } + .setNegativeButton(R.string.dont_show_again) { _, _ -> + driverViewModel.onDriverShaderDialogDismissed(dontShowAgain = true) + } + .setCancelable(false) + .show() + } } diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/DriverViewModel.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/DriverViewModel.kt index a49c887a12..d26320bbb3 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/DriverViewModel.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/DriverViewModel.kt @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -16,6 +19,7 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import org.yuzu.yuzu_emu.R import org.yuzu.yuzu_emu.YuzuApplication +import org.yuzu.yuzu_emu.features.settings.model.BooleanSetting import org.yuzu.yuzu_emu.features.settings.model.StringSetting import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile import org.yuzu.yuzu_emu.model.Driver.Companion.toDriver @@ -52,9 +56,15 @@ class DriverViewModel : ViewModel() { private val driversToDelete = mutableListOf() + private var previousDriverPath: String = "" + + private val _shouldShowDriverShaderDialog = MutableStateFlow(false) + val shouldShowDriverShaderDialog: StateFlow get() = _shouldShowDriverShaderDialog + init { updateDriverList() updateDriverNameForGame(null) + previousDriverPath = StringSetting.DRIVER_PATH.getString() } fun reloadDriverData() { @@ -79,6 +89,7 @@ class DriverViewModel : ViewModel() { newDriverList.add(it.second.toDriver(it.second == selectedDriver)) } _driverList.value = newDriverList + previousDriverPath = StringSetting.DRIVER_PATH.getString() } fun onOpenDriverManager(game: Game?) { @@ -92,12 +103,49 @@ class DriverViewModel : ViewModel() { _showClearButton.value = value } - fun onDriverSelected(position: Int) { + fun onDriverSelected(position: Int, skipShaderWipe: Boolean = false) { + val newDriverPath = if (position == 0) { + "" + } else { + driverData[position - 1].first + } + + if (!skipShaderWipe && newDriverPath != previousDriverPath) { + wipeAllShaders() + + if (!BooleanSetting.DONT_SHOW_DRIVER_SHADER_WARNING.getBoolean(needsGlobal = true)) { + _shouldShowDriverShaderDialog.value = true + } + } + if (position == 0) { StringSetting.DRIVER_PATH.setString("") } else { StringSetting.DRIVER_PATH.setString(driverData[position - 1].first) } + previousDriverPath = newDriverPath + } + + fun onDriverShaderDialogDismissed(dontShowAgain: Boolean) { + if (dontShowAgain) { + BooleanSetting.DONT_SHOW_DRIVER_SHADER_WARNING.setBoolean(true) + NativeConfig.saveGlobalConfig() + } + _shouldShowDriverShaderDialog.value = false + } + + private fun wipeAllShaders() { + viewModelScope.launch { + withContext(Dispatchers.IO) { + val shaderDir = File( + YuzuApplication.appContext.getExternalFilesDir(null)?.canonicalPath + + "/shader/" + ) + if (shaderDir.exists()) { + shaderDir.deleteRecursively() + } + } + } } fun onDriverRemoved(removedPosition: Int, selectedPosition: Int) { diff --git a/src/android/app/src/main/jni/android_settings.h b/src/android/app/src/main/jni/android_settings.h index 8a46a22df1..19ac95652b 100644 --- a/src/android/app/src/main/jni/android_settings.h +++ b/src/android/app/src/main/jni/android_settings.h @@ -182,9 +182,9 @@ namespace AndroidSettings { Settings::Specialization::Default, true, true, &show_soc_overlay}; - Settings::Setting dont_show_eden_veil_warning{linkage, false, - "dont_show_eden_veil_warning", - Settings::Category::Miscellaneous}; + Settings::Setting dont_show_driver_shader_warning{linkage, false, + "dont_show_driver_shader_warning", + Settings::Category::Android, Settings::Specialization::Default, true, true}; }; extern Values values; diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index 6ea171ea2b..7d0579155e 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -722,6 +722,8 @@ Removes all shaders built while playing this game You will experience more stuttering as the shader cache regenerates Cleared shaders successfully + Shaders Cleared + Eden has automatically cleared all shader caches to maintain Vulkan pipeline validation. This is required when switching GPU drivers to prevent crashes and graphical corruption. You may experience some stuttering as shaders rebuild. Addons: %1$s Save data Manage save data specific to this game