Compare commits

...

2 Commits

Author SHA1 Message Date
crueter 0d3cef65ad fix clang-cl comp (#3044)
Signed-off-by: crueter <crueter@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3044
2025-11-18 19:02:08 +01:00
kleidis c2794985b2 [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 <sahyno1996@gmail.com>
Reviewed-by: Caio Oliveira <caiooliveirafarias0@gmail.com>
Reviewed-by: crueter <crueter@eden-emu.dev>
Co-authored-by: kleidis <kleidis1@protonmail.com>
Co-committed-by: kleidis <kleidis1@protonmail.com>
2025-11-18 18:41:47 +01:00
6 changed files with 82 additions and 10 deletions
@@ -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
@@ -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()
}
}
@@ -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<String>()
private var previousDriverPath: String = ""
private val _shouldShowDriverShaderDialog = MutableStateFlow(false)
val shouldShowDriverShaderDialog: StateFlow<Boolean> 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) {
@@ -182,9 +182,9 @@ namespace AndroidSettings {
Settings::Specialization::Default, true, true,
&show_soc_overlay};
Settings::Setting<bool> dont_show_eden_veil_warning{linkage, false,
"dont_show_eden_veil_warning",
Settings::Category::Miscellaneous};
Settings::Setting<bool> dont_show_driver_shader_warning{linkage, false,
"dont_show_driver_shader_warning",
Settings::Category::Android, Settings::Specialization::Default, true, true};
};
extern Values values;
@@ -722,6 +722,8 @@
<string name="clear_shader_cache_description">Removes all shaders built while playing this game</string>
<string name="clear_shader_cache_warning_description">You will experience more stuttering as the shader cache regenerates</string>
<string name="cleared_shaders_successfully">Cleared shaders successfully</string>
<string name="driver_shader_wipe_dialog_title">Shaders Cleared</string>
<string name="driver_shader_wipe_dialog_message">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.</string>
<string name="addons_game">Addons: %1$s</string>
<string name="save_data">Save data</string>
<string name="save_data_description">Manage save data specific to this game</string>
@@ -1029,8 +1029,8 @@ void RasterizerVulkan::UpdateViewportsState(Tegra::Engines::Maxwell3D::Regs& reg
if (!regs.viewport_scale_offset_enabled) {
float x = static_cast<float>(regs.surface_clip.x);
float y = static_cast<float>(regs.surface_clip.y);
float width = std::max(1.0f, static_cast<float>(regs.surface_clip.width));
float height = std::max(1.0f, static_cast<float>(regs.surface_clip.height));
float width = (std::max)(1.0f, static_cast<float>(regs.surface_clip.width));
float height = (std::max)(1.0f, static_cast<float>(regs.surface_clip.height));
if (regs.window_origin.mode != Maxwell::WindowOrigin::Mode::UpperLeft) {
y += height;
height = -height;
@@ -1074,8 +1074,8 @@ void RasterizerVulkan::UpdateScissorsState(Tegra::Engines::Maxwell3D::Regs& regs
if (!regs.viewport_scale_offset_enabled) {
u32 x = regs.surface_clip.x;
u32 y = regs.surface_clip.y;
u32 width = std::max(1u, static_cast<u32>(regs.surface_clip.width));
u32 height = std::max(1u, static_cast<u32>(regs.surface_clip.height));
u32 width = (std::max)(1u, static_cast<u32>(regs.surface_clip.width));
u32 height = (std::max)(1u, static_cast<u32>(regs.surface_clip.height));
if (regs.window_origin.mode != Maxwell::WindowOrigin::Mode::UpperLeft) {
y = regs.surface_clip.height - (y + height);
}