diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/GpuUnswizzleSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/GpuUnswizzleSetting.kt index c83c20a46f..5d6535e81e 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/GpuUnswizzleSetting.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/GpuUnswizzleSetting.kt @@ -22,10 +22,11 @@ class GpuUnswizzleSetting( @ArrayRes val chunkSizeValuesId: Int ) : SettingsItem( object : AbstractSetting { - override val key: String = "gpu_unswizzle_combined" + override val key: String = SettingsItem.GPU_UNSWIZZLE_COMBINED override val defaultValue: Any = false override val isSaveable = true - override val isRuntimeModifiable = false + override val isRuntimeModifiable = true + override val isSwitchable = true override fun getValueAsString(needsGlobal: Boolean): String = "combined" override fun reset() { BooleanSetting.GPU_UNSWIZZLE_ENABLED.reset() 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 6338374aa9..acbfbac337 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 @@ -107,6 +107,7 @@ abstract class SettingsItem( const val TYPE_GPU_UNSWIZZLE = 15 const val FASTMEM_COMBINED = "fastmem_combined" + const val GPU_UNSWIZZLE_COMBINED = "gpu_unswizzle_combined" val emptySetting = object : AbstractSetting { override val key: String = "" 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 e44c589e67..5ea94d3ac5 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 @@ -282,7 +282,7 @@ class SettingsFragmentPresenter( add(BooleanSetting.SKIP_CPU_INNER_INVALIDATION.key) add(BooleanSetting.FIX_BLOOM_EFFECTS.key) add(BooleanSetting.RENDERER_ASYNCHRONOUS_SHADERS.key) - add("gpu_unswizzle_combined") + add(SettingsItem.GPU_UNSWIZZLE_COMBINED) add(HeaderSetting(R.string.extensions)) diff --git a/src/qt_common/config/shared_translation.cpp b/src/qt_common/config/shared_translation.cpp index 5d4185b47d..404685b36c 100644 --- a/src/qt_common/config/shared_translation.cpp +++ b/src/qt_common/config/shared_translation.cpp @@ -284,6 +284,11 @@ std::unique_ptr InitializeTranslations(QObject* parent) tr("Fast GPU Time"), tr("Overclocks the emulated GPU to increase dynamic resolution and render " "distance.\nUse 256 for maximal performance and 512 for maximal graphics fidelity.")); + INSERT(Settings, + gpu_unswizzle_enabled, + tr("GPU Unswizzle"), + tr("Accelerates BCn 3D texture decoding using GPU compute.\n" + "Disable if experiencing crashes or graphical glitches.")); INSERT(Settings, gpu_unswizzle_texture_size, tr("GPU Unswizzle Max Texture Size"), diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 988ab53266..0069f10f9c 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -893,8 +893,10 @@ TextureCacheRuntime::TextureCacheRuntime(const Device& device_, Scheduler& sched } } - bl3d_unswizzle_pass.emplace(device, scheduler, descriptor_pool, - staging_buffer_pool, compute_pass_descriptor_queue); + if (Settings::values.gpu_unswizzle_enabled.GetValue()) { + bl3d_unswizzle_pass.emplace(device, scheduler, descriptor_pool, + staging_buffer_pool, compute_pass_descriptor_queue); + } // --- Create swizzle table buffer --- { @@ -2538,6 +2540,14 @@ void TextureCacheRuntime::AccelerateImageUpload( return astc_decoder_pass->Assemble(image, map, swizzles); } + if (!Settings::values.gpu_unswizzle_enabled.GetValue() || !bl3d_unswizzle_pass) { + if (IsPixelFormatBCn(image.info.format) && image.info.type == ImageType::e3D) { + ASSERT_MSG(false, "GPU unswizzle is disabled for BCn 3D texture"); + } + ASSERT(false); + return; + } + if (bl3d_unswizzle_pass && IsPixelFormatBCn(image.info.format) && image.info.type == ImageType::e3D && diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 0ed65e29e9..603a042ba2 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -80,31 +80,39 @@ TextureCache

::TextureCache(Runtime& runtime_, Tegra::MaxwellDeviceMemoryManag lowmemorydevice = true; } - switch (Settings::values.gpu_unswizzle_texture_size.GetValue()) { - case Settings::GpuUnswizzleSize::VerySmall: gpu_unswizzle_maxsize = 16_MiB; break; - case Settings::GpuUnswizzleSize::Small: gpu_unswizzle_maxsize = 32_MiB; break; - case Settings::GpuUnswizzleSize::Normal: gpu_unswizzle_maxsize = 128_MiB; break; - case Settings::GpuUnswizzleSize::Large: gpu_unswizzle_maxsize = 256_MiB; break; - case Settings::GpuUnswizzleSize::VeryLarge: gpu_unswizzle_maxsize = 512_MiB; break; - default: gpu_unswizzle_maxsize = 128_MiB; break; - } + const bool gpu_unswizzle_enabled = Settings::values.gpu_unswizzle_enabled.GetValue(); - switch (Settings::values.gpu_unswizzle_stream_size.GetValue()) { - case Settings::GpuUnswizzle::VeryLow: swizzle_chunk_size = 4_MiB; break; - case Settings::GpuUnswizzle::Low: swizzle_chunk_size = 8_MiB; break; - case Settings::GpuUnswizzle::Normal: swizzle_chunk_size = 16_MiB; break; - case Settings::GpuUnswizzle::Medium: swizzle_chunk_size = 32_MiB; break; - case Settings::GpuUnswizzle::High: swizzle_chunk_size = 64_MiB; break; - default: swizzle_chunk_size = 16_MiB; - } + if (gpu_unswizzle_enabled) { + switch (Settings::values.gpu_unswizzle_texture_size.GetValue()) { + case Settings::GpuUnswizzleSize::VerySmall: gpu_unswizzle_maxsize = 16_MiB; break; + case Settings::GpuUnswizzleSize::Small: gpu_unswizzle_maxsize = 32_MiB; break; + case Settings::GpuUnswizzleSize::Normal: gpu_unswizzle_maxsize = 128_MiB; break; + case Settings::GpuUnswizzleSize::Large: gpu_unswizzle_maxsize = 256_MiB; break; + case Settings::GpuUnswizzleSize::VeryLarge: gpu_unswizzle_maxsize = 512_MiB; break; + default: gpu_unswizzle_maxsize = 128_MiB; break; + } - switch (Settings::values.gpu_unswizzle_chunk_size.GetValue()) { - case Settings::GpuUnswizzleChunk::VeryLow: swizzle_slices_per_batch = 32; break; - case Settings::GpuUnswizzleChunk::Low: swizzle_slices_per_batch = 64; break; - case Settings::GpuUnswizzleChunk::Normal: swizzle_slices_per_batch = 128; break; - case Settings::GpuUnswizzleChunk::Medium: swizzle_slices_per_batch = 256; break; - case Settings::GpuUnswizzleChunk::High: swizzle_slices_per_batch = 512; break; - default: swizzle_slices_per_batch = 128; + switch (Settings::values.gpu_unswizzle_stream_size.GetValue()) { + case Settings::GpuUnswizzle::VeryLow: swizzle_chunk_size = 4_MiB; break; + case Settings::GpuUnswizzle::Low: swizzle_chunk_size = 8_MiB; break; + case Settings::GpuUnswizzle::Normal: swizzle_chunk_size = 16_MiB; break; + case Settings::GpuUnswizzle::Medium: swizzle_chunk_size = 32_MiB; break; + case Settings::GpuUnswizzle::High: swizzle_chunk_size = 64_MiB; break; + default: swizzle_chunk_size = 16_MiB; + } + + switch (Settings::values.gpu_unswizzle_chunk_size.GetValue()) { + case Settings::GpuUnswizzleChunk::VeryLow: swizzle_slices_per_batch = 32; break; + case Settings::GpuUnswizzleChunk::Low: swizzle_slices_per_batch = 64; break; + case Settings::GpuUnswizzleChunk::Normal: swizzle_slices_per_batch = 128; break; + case Settings::GpuUnswizzleChunk::Medium: swizzle_slices_per_batch = 256; break; + case Settings::GpuUnswizzleChunk::High: swizzle_slices_per_batch = 512; break; + default: swizzle_slices_per_batch = 128; + } + } else { + gpu_unswizzle_maxsize = 0; + swizzle_chunk_size = 0; + swizzle_slices_per_batch = 0; } } @@ -1161,7 +1169,11 @@ void TextureCache

::RefreshContents(Image& image, ImageId image_id) { QueueAsyncDecode(image, image_id); return; } - if (IsPixelFormatBCn(image.info.format) && + + const bool gpu_unswizzle_enabled = Settings::values.gpu_unswizzle_enabled.GetValue(); + + if (gpu_unswizzle_enabled && + IsPixelFormatBCn(image.info.format) && image.info.type == ImageType::e3D && image.info.resources.levels == 1 && image.info.resources.layers == 1 &&