diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/IntSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/IntSetting.kt index 3926498c25..35bcf430da 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/IntSetting.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/IntSetting.kt @@ -47,6 +47,7 @@ enum class IntSetting(override val key: String) : AbstractIntSetting { FAST_CPU_TIME("fast_cpu_time"), CPU_TICKS("cpu_ticks"), FAST_GPU_TIME("fast_gpu_time"), + GPU_UNZWIZZLE_MAXTEXTURE_SIZE("gpu_unzwizzle_maxtexture_size"), GPU_UNZWIZZLE_STREAM_SIZE("gpu_unzwizzle_stream_size"), GPU_UNZWIZZLE_CHUNK_SIZE("gpu_unzwizzle_chunk_size"), BAT_TEMPERATURE_UNIT("bat_temperature_unit"), 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 5b37824451..df475271fb 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 @@ -655,6 +655,15 @@ abstract class SettingsItem( valuesId = R.array.gpuValues ) ) + put( + SingleChoiceSetting( + IntSetting.GPU_UNZWIZZLE_MAXTEXTURE_SIZE, + titleId = R.string.gpu_unzwizzle_maxtexture_size, + descriptionId = R.string.gpu_unzwizzle_maxtexture_size_description, + choicesId = R.array.gpuTextureSizeSwizzleEntries, + valuesId = R.array.gpuTextureSizeSwizzleValues + ) + ) put( SingleChoiceSetting( IntSetting.GPU_UNZWIZZLE_STREAM_SIZE, 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 c268d3f8ae..68c8a0b309 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 @@ -280,6 +280,7 @@ class SettingsFragmentPresenter( add(IntSetting.FAST_GPU_TIME.key) add(BooleanSetting.SKIP_CPU_INNER_INVALIDATION.key) add(BooleanSetting.RENDERER_ASYNCHRONOUS_SHADERS.key) + add(IntSetting.GPU_UNZWIZZLE_MAXTEXTURE_SIZE.key) add(IntSetting.GPU_UNZWIZZLE_STREAM_SIZE.key) add(IntSetting.GPU_UNZWIZZLE_CHUNK_SIZE.key) diff --git a/src/android/app/src/main/res/values/arrays.xml b/src/android/app/src/main/res/values/arrays.xml index 7b92c0dc7f..bf553725d5 100644 --- a/src/android/app/src/main/res/values/arrays.xml +++ b/src/android/app/src/main/res/values/arrays.xml @@ -563,7 +563,23 @@ 1 2 - + + + @string/gpu_texturesizeswizzle_verysmall + @string/gpu_texturesizeswizzle_small + @string/gpu_texturesizeswizzle_normal + @string/gpu_texturesizeswizzle_large + @string/gpu_texturesizeswizzle_verylarge + + + + 0 + 1 + 2 + 3 + 4 + + @string/gpu_swizzle_verylow @string/gpu_swizzle_low diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index 95c0a3c4f9..800c229986 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -504,6 +504,8 @@ Skips certain CPU-side cache invalidations during memory updates, reducing CPU usage and improving it\'s performance. This may cause glitches or crashes on some games. Use asynchronous shaders Compiles shaders asynchronously. This may reduce stutters but may also introduce glitches. + GPU Unswizzle Max Texture Size + Sets the maximum size (MB) for GPU-based texture unswizzling. While the GPU is faster for medium and large textures, the CPU may be more efficient for very small ones. Adjust this to find the balance between GPU acceleration and CPU overhead. GPU Unswizzle Stream Size Sets the data limit per frame for unswizzling large textures. Higher values speed up texture loading at the cost of higher frame latency; lower values reduce GPU overhead but may cause visible texture pop-in. GPU Unswizzle Chunk Size @@ -929,12 +931,19 @@ Medium (256) High (512) + + Very Small (16 MB) + Small (32 MB) + Normal (128 MB) + Large (256 MB) + Very Large (512 MB) + - Very Low (4) - Low (8) - Normal (16) - Medium (32) - High (64) + Very Low (4 MB) + Low (8 MB) + Normal (16 MB) + Medium (32 MB) + High (64 MB) Very Low (32) diff --git a/src/common/settings.h b/src/common/settings.h index 90a172c3a0..38b35f7a8f 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -513,6 +513,12 @@ struct Values { SwitchableSetting use_asynchronous_shaders{linkage, false, "use_asynchronous_shaders", Category::RendererHacks}; + SwitchableSetting gpu_unzwizzle_texture_size{linkage, + GpuUnswizzleSize::Large, + "gpu_unzwizzle_texture_size", + Category::RendererHacks, + Specialization::Default}; + SwitchableSetting gpu_unzwizzle_stream_size{linkage, GpuUnswizzle::Medium, "gpu_unzwizzle_stream_size", diff --git a/src/common/settings_enums.h b/src/common/settings_enums.h index 31e11b7319..be0c95906d 100644 --- a/src/common/settings_enums.h +++ b/src/common/settings_enums.h @@ -150,6 +150,7 @@ ENUM(ConsoleMode, Handheld, Docked); ENUM(AppletMode, HLE, LLE); ENUM(SpirvOptimizeMode, Never, OnLoad, Always); ENUM(GpuOverclock, Normal, Medium, High) +ENUM(GpuUnswizzleSize, VerySmall, Small, Normal, Large, VeryLarge) ENUM(GpuUnswizzle, VeryLow, Low, Normal, Medium, High) ENUM(GpuUnswizzleChunk, VeryLow, Low, Normal, Medium, High) ENUM(TemperatureUnits, Celsius, Fahrenheit) diff --git a/src/qt_common/config/shared_translation.cpp b/src/qt_common/config/shared_translation.cpp index 885a8c02bc..f48dcac55e 100644 --- a/src/qt_common/config/shared_translation.cpp +++ b/src/qt_common/config/shared_translation.cpp @@ -288,6 +288,12 @@ 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_unzwizzle_texture_size, + tr("GPU Unswizzle Max Texture Size"), + tr("Sets the maximum size (MiB) for GPU-based texture unswizzling.\n" + "While the GPU is faster for medium and large textures, the CPU may be more efficient for very small ones.\n" + "Adjust this to find the balance between GPU acceleration and CPU overhead.")); INSERT(Settings, gpu_unzwizzle_stream_size, tr("GPU Unswizzle Stream Size"), @@ -729,13 +735,21 @@ std::unique_ptr ComboboxEnumeration(QObject* parent) PAIR(GpuOverclock, Medium, tr("Medium (256)")), PAIR(GpuOverclock, High, tr("High (512)")), }}); + translations->insert({Settings::EnumMetadata::Index(), + { + PAIR(GpuUnswizzleSize, VerySmall, tr("Very Small (16 MB)")), + PAIR(GpuUnswizzleSize, Small, tr("Small (32 MB)")), + PAIR(GpuUnswizzleSize, Normal, tr("Normal (128 MB)")), + PAIR(GpuUnswizzleSize, Large, tr("Large (256 MB)")), + PAIR(GpuUnswizzleSize, VeryLarge, tr("Very Large (512 MB)")), + }}); translations->insert({Settings::EnumMetadata::Index(), { - PAIR(GpuUnswizzle, VeryLow, tr("Very Low (4)")), - PAIR(GpuUnswizzle, Low, tr("Low (8)")), - PAIR(GpuUnswizzle, Normal, tr("Normal (16)")), - PAIR(GpuUnswizzle, Medium, tr("Medium (32)")), - PAIR(GpuUnswizzle, High, tr("High (64)")), + PAIR(GpuUnswizzle, VeryLow, tr("Very Low (4 MB)")), + PAIR(GpuUnswizzle, Low, tr("Low (8 MB)")), + PAIR(GpuUnswizzle, Normal, tr("Normal (16 MB)")), + PAIR(GpuUnswizzle, Medium, tr("Medium (32 MB)")), + PAIR(GpuUnswizzle, High, tr("High (64 MB)")), }}); translations->insert({Settings::EnumMetadata::Index(), { diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 59b4804c08..8b432c4c97 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -77,6 +77,33 @@ TextureCache

::TextureCache(Runtime& runtime_, Tegra::MaxwellDeviceMemoryManag } lowmemorydevice = Settings::values.enable_low_memory.GetValue(); + + switch (Settings::values.gpu_unzwizzle_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_unzwizzle_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_unzwizzle_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; + } } template @@ -1152,7 +1179,7 @@ void TextureCache

::RefreshContents(Image& image, ImageId image_id) { image.info.type == ImageType::e3D && image.info.resources.levels == 1 && image.info.resources.layers == 1 && - MapSizeBytes(image) >= 128_MiB && + MapSizeBytes(image) >= gpu_unswizzle_maxsize && False(image.flags & ImageFlagBits::GpuModified)) { QueueAsyncUnswizzle(image, image_id); @@ -1471,33 +1498,13 @@ void TextureCache

::TickAsyncUnswizzle() { task.initialized = true; } - size_t CHUNK_SIZE; - switch (Settings::values.gpu_unzwizzle_stream_size.GetValue()) { - case Settings::GpuUnswizzle::VeryLow: CHUNK_SIZE = 4_MiB; break; - case Settings::GpuUnswizzle::Low: CHUNK_SIZE = 8_MiB; break; - case Settings::GpuUnswizzle::Normal: CHUNK_SIZE = 16_MiB; break; - case Settings::GpuUnswizzle::Medium: CHUNK_SIZE = 32_MiB; break; - case Settings::GpuUnswizzle::High: CHUNK_SIZE = 64_MiB; break; - default: CHUNK_SIZE = 16_MiB; - } - - u32 SLICES_PER_BATCH; - switch (Settings::values.gpu_unzwizzle_chunk_size.GetValue()) { - case Settings::GpuUnswizzleChunk::VeryLow: SLICES_PER_BATCH = 32; break; - case Settings::GpuUnswizzleChunk::Low: SLICES_PER_BATCH = 64; break; - case Settings::GpuUnswizzleChunk::Normal: SLICES_PER_BATCH = 128; break; - case Settings::GpuUnswizzleChunk::Medium: SLICES_PER_BATCH = 256; break; - case Settings::GpuUnswizzleChunk::High: SLICES_PER_BATCH = 512; break; - default: SLICES_PER_BATCH = 128; - } - // Read data if (task.current_offset < task.total_size) { const size_t remaining = task.total_size - task.current_offset; - size_t copy_amount = std::min(CHUNK_SIZE, remaining); + size_t copy_amount = std::min(swizzle_chunk_size, remaining); - if (remaining > CHUNK_SIZE) { + if (remaining > swizzle_chunk_size) { copy_amount = (copy_amount / task.bytes_per_slice) * task.bytes_per_slice; if (copy_amount == 0) copy_amount = task.bytes_per_slice; } @@ -1512,9 +1519,9 @@ void TextureCache

::TickAsyncUnswizzle() { const size_t bytes_ready = task.current_offset - task.last_submitted_offset; const u32 complete_slices = static_cast(bytes_ready / task.bytes_per_slice); - if (complete_slices >= SLICES_PER_BATCH || (is_final_batch && complete_slices > 0)) { + if (complete_slices >= swizzle_slices_per_batch || (is_final_batch && complete_slices > 0)) { const u32 z_start = static_cast(task.last_submitted_offset / task.bytes_per_slice); - const u32 slices_to_process = std::min(complete_slices, SLICES_PER_BATCH); + const u32 slices_to_process = std::min(complete_slices, swizzle_slices_per_batch); const u32 z_count = std::min(slices_to_process, image.info.size.depth - z_start); if (z_count > 0) { diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h index 97de31d424..5c8f420bfc 100644 --- a/src/video_core/texture_cache/texture_cache_base.h +++ b/src/video_core/texture_cache/texture_cache_base.h @@ -472,6 +472,9 @@ private: u64 expected_memory; u64 critical_memory; bool lowmemorydevice = false; + size_t gpu_unswizzle_maxsize = 0; + size_t swizzle_chunk_size = 0; + u32 swizzle_slices_per_batch = 0; struct BufferDownload { GPUVAddr address;