Compare commits
4 Commits
v0.0.4-rc3
...
showcase2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f9ec137396 | ||
|
|
ea5e15cde5 | ||
|
|
0d3cef65ad | ||
|
|
c2794985b2 |
@@ -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>
|
||||
|
||||
@@ -677,6 +677,7 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline(
|
||||
|
||||
const auto runtime_info{MakeRuntimeInfo(programs, key, program, previous_stage)};
|
||||
ConvertLegacyToGeneric(program, runtime_info);
|
||||
|
||||
const std::vector<u32> code{EmitSPIRV(profile, runtime_info, program, binding, this->optimize_spirv_output)};
|
||||
device.SaveShader(code);
|
||||
modules[stage_index] = BuildShader(device, code);
|
||||
@@ -771,6 +772,17 @@ std::unique_ptr<ComputePipeline> PipelineCache::CreateComputePipeline(
|
||||
}
|
||||
|
||||
auto program{TranslateProgram(pools.inst, pools.block, env, cfg, host_info)};
|
||||
|
||||
// Adreno have lower shared memory limits (32KB)
|
||||
// Clamp shared memory usage to device maximum to avoid validation errors
|
||||
const u32 max_shared_memory = device.GetMaxComputeSharedMemorySize();
|
||||
if (program.shared_memory_size > max_shared_memory) {
|
||||
LOG_WARNING(Render_Vulkan,
|
||||
"Compute shader 0x{:016x} requests {}KB shared memory but device max is {}KB - clamping",
|
||||
key.unique_hash, program.shared_memory_size / 1024, max_shared_memory / 1024);
|
||||
program.shared_memory_size = max_shared_memory;
|
||||
}
|
||||
|
||||
const std::vector<u32> code{EmitSPIRV(profile, program, this->optimize_spirv_output)};
|
||||
device.SaveShader(code);
|
||||
vk::ShaderModule spv_module{BuildShader(device, code)};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user