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 7f6e793199..961d1714ff 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 @@ -30,7 +30,6 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting { RENDERER_REACTIVE_FLUSHING("use_reactive_flushing"), ENABLE_BUFFER_HISTORY("enable_buffer_history"), USE_OPTIMIZED_VERTEX_BUFFERS("use_optimized_vertex_buffers"), - ENABLE_GPU_BUFFER_READBACK("enable_gpu_buffer_readback"), SYNC_MEMORY_OPERATIONS("sync_memory_operations"), BUFFER_REORDER_DISABLE("disable_buffer_reorder"), RENDERER_DEBUG("debug"), 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 7c6063988f..a3f95eff4b 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 @@ -808,13 +808,6 @@ abstract class SettingsItem( descriptionId = R.string.enable_buffer_history_description ) ) - put( - SwitchSetting( - BooleanSetting.ENABLE_GPU_BUFFER_READBACK, - titleId = R.string.enable_gpu_buffer_readback, - descriptionId = R.string.enable_gpu_buffer_readback_description - ) - ) put( SwitchSetting( BooleanSetting.USE_OPTIMIZED_VERTEX_BUFFERS, 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 81702d7110..751869be5c 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 @@ -293,7 +293,6 @@ class SettingsFragmentPresenter( add(BooleanSetting.RENDERER_FORCE_MAX_CLOCK.key) add(BooleanSetting.RENDERER_REACTIVE_FLUSHING.key) add(BooleanSetting.ENABLE_BUFFER_HISTORY.key) - add(BooleanSetting.ENABLE_GPU_BUFFER_READBACK.key) add(BooleanSetting.USE_OPTIMIZED_VERTEX_BUFFERS.key) add(HeaderSetting(R.string.hacks)) diff --git a/src/android/app/src/main/res/values-ar/strings.xml b/src/android/app/src/main/res/values-ar/strings.xml index 5a65afe533..1bb569e236 100644 --- a/src/android/app/src/main/res/values-ar/strings.xml +++ b/src/android/app/src/main/res/values-ar/strings.xml @@ -499,8 +499,6 @@ يحسن دقة العرض في بعض الألعاب على حساب الأداء. تمكين سجل التخزين المؤقت يُتيح هذا الخيار الوصول إلى حالات التخزين المؤقت السابقة. وقد يُحسّن جودة العرض وثبات الأداء في بعض الألعاب. - تفعيل قراءة مخزن وحدة معالجة الرسومات - يحافظ هذا النظام على بيانات المخزن المؤقت المُعدّلة بواسطة وحدة معالجة الرسومات عن طريق قراءتها مرة أخرى قبل التحميل. تتطلب بعض الألعاب ذلك لعرض بعض التأثيرات بشكل صحيح. قد يُسبب ذلك مشاكل إذا لم يتمكن الجهاز من التعامل مع عبء العمل الإضافي. مخازن الرؤوس المُحسّنة يُتيح ربطًا مُحسَّنًا لمخازن الرؤوس لتحسين الأداء. يتطلب برامج تشغيل Mesa 26.0+ Turnip/ برامج تشغيل QCOM. قد يتعطل على برامج تشغيل Turnip القديمة (25.3 وما دون). diff --git a/src/android/app/src/main/res/values-es/strings.xml b/src/android/app/src/main/res/values-es/strings.xml index e9ad7ecb6d..45e252f97d 100644 --- a/src/android/app/src/main/res/values-es/strings.xml +++ b/src/android/app/src/main/res/values-es/strings.xml @@ -492,8 +492,6 @@ Mejora la precisión de renderizado en algunos juegos, pero reduce el rendimiento. Activar el historial del búfer Permite el acceso al estado del búfer anterior. Esta opción puede mejorar la calidad de renderizado y la consistencia en el rendimiento de algunos juegos. - Activar la lectura del buffer de la GPU - Conserva los datos del búfer modificados por la GPU leyéndolos antes de subirlos.\nAlgunos juegos requieren esto para renderizar correctamente ciertos efectos.\nPuede causar problemas si el hardware no puede soportar la carga de trabajo adicional. Búferes de vértices optimizados Permite la optimización del enlace del búfer de vértices para un mejor rendimiento. Requiere controladores Mesa 26.0+ Turnip/ controladores QCOM. Fallará con controladores Turnip más antiguos (versión 25.3 o inferior). diff --git a/src/android/app/src/main/res/values-zh-rCN/strings.xml b/src/android/app/src/main/res/values-zh-rCN/strings.xml index d65ffcca9f..f41641767c 100644 --- a/src/android/app/src/main/res/values-zh-rCN/strings.xml +++ b/src/android/app/src/main/res/values-zh-rCN/strings.xml @@ -489,8 +489,6 @@ 通过牺牲性能来提升某些游戏的渲染精度。 启用缓冲区历史 启用对先前缓冲区状态的访问。此选项可在某些游戏中提升渲染质量并保持性能的一致性。 - 启用 GPU 缓冲区回读 - 在上传前回读经由 GPU 修改过的缓冲区数据,以将其保留。一些游戏会用到这项设定以正确渲染某些效果。如果硬件无法处理额外的工作负载,则可能会导致问题。 优化顶点缓冲区 启用经过优化的顶点缓冲区绑定以提升性能。需要 Mesa 26.0 及以上版本的 Turnip 或 QCOM 驱动程序。若使用较旧版本的 Turnip 驱动 (25.3 及以下版本) 则会导致崩溃。 diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index cd5d0c41e7..b8bc67ddab 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -505,8 +505,6 @@ Improves rendering accuracy in some games at the cost of performance. Enable buffer history Enables access to previous buffer states. This option may improve rendering quality and performance consistency in some games. - Enable GPU Buffer Readback - Preserves GPU-modified buffer data by reading it back before uploads. Some games require this to render certain effects properly. May cause issues if the hardware cannot handle the additional workload. Optimized Vertex Buffers Enables optimized vertex buffer binding for improved performance. Requires Mesa 26.0+ Turnip drivers/ QCOM drivers. Will crash on older Turnip drivers (25.3 and below). diff --git a/src/common/settings.h b/src/common/settings.h index 00ba7dddc9..886774f696 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -576,13 +576,6 @@ struct Values { false, #endif "rescale_hack", Category::RendererHacks}; - SwitchableSetting enable_gpu_buffer_readback{linkage, - false, - "enable_gpu_buffer_readback", - Category::RendererAdvanced, - Specialization::Default, - true, - true}; SwitchableSetting use_asynchronous_shaders{linkage, false, "use_asynchronous_shaders", Category::RendererHacks}; diff --git a/src/qt_common/config/shared_translation.cpp b/src/qt_common/config/shared_translation.cpp index 893e4a0854..6c9c6c1474 100644 --- a/src/qt_common/config/shared_translation.cpp +++ b/src/qt_common/config/shared_translation.cpp @@ -226,8 +226,6 @@ std::unique_ptr InitializeTranslations(QObject* parent) { tr("Controls the DMA read mode.\nUnsafe is faster, while Safe is more stable and can fix issues in some games.\nDefault follows the GPU Accuracy setting.")); INSERT(Settings, gpu_fence_behavior, tr("GPU Fence Behavior:"), tr("Controls the GPU fence synchronization behavior.\nImmediate is the fastest option, but can introduce some issues.\nBalanced offers better compatibility and may fix issues in some games.\nAccurate further improves compatibility at the cost of some performance.\nStrict is the slowest option, but can fix issues that require stricter synchronization.\nDefault follows the GPU Accuracy setting.")); - INSERT(Settings, enable_gpu_buffer_readback, tr("Enable GPU buffer readback"), - tr("Preserves GPU-modified data by reading it back before uploading.\nSome games require this to render certain effects properly.")); INSERT(Settings, use_asynchronous_shaders, tr("Enable asynchronous shader compilation"), tr("May reduce shader stutter.")); INSERT(Settings, fast_gpu_time, tr("Fast GPU Time"), diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index e40aad1fb5..c19d8e66b1 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -1448,25 +1448,33 @@ BufferId BufferCache

::FindBuffer(DAddr device_addr, u32 size) { const BufferId buffer_id = page_table[page]; if (buffer_id) { Buffer& buffer = slot_buffers[buffer_id]; - WaitForGpuFenceIfNeeded(buffer); if (buffer.IsInBounds(device_addr, size)) { + SynchronizeBufferIfNeeded(buffer); return buffer_id; } } return CreateBuffer(device_addr, size); } -template -void BufferCache

::WaitForGpuFenceIfNeeded(Buffer& buffer) { - if constexpr (!IS_OPENGL) { - const bool gpu_fence_accurate = Settings::IsGPUFenceBehaviorAccurate(); - const bool gpu_fence_strict = Settings::IsGPUFenceBehaviorStrict(); - if (gpu_fence_accurate || gpu_fence_strict) { - const u64 gpu_tick_delay = gpu_fence_strict ? 0 : 3; - const u64 buffer_tick = buffer.getWriteTick(); - const u64 gpu_tick = runtime.KnownGpuTick(); - if (buffer_tick > gpu_tick + gpu_tick_delay) { - runtime.Wait(buffer_tick); +void BufferCache

::SynchronizeBufferIfNeeded(Buffer& buffer) { + const bool gpu_fence_accurate = Settings::IsGPUFenceBehaviorAccurate(); + const bool gpu_fence_strict = Settings::IsGPUFenceBehaviorStrict(); + const bool should_sync = gpu_fence_accurate || gpu_fence_strict; + if (should_sync) { + if (gpu_fence_accurate) { + if constexpr (!IS_OPENGL) { + const bool should_wait = buffer.getWriteTick() > runtime.KnownGpuTick() + 3; + if (should_wait) { + runtime.Wait(buffer.getWriteTick()); + } + } + } else if (gpu_fence_strict) { + bool should_download = true; + if constexpr (!IS_OPENGL) { + should_download = buffer.getWriteTick() > runtime.KnownGpuTick(); + } + if (should_download) { + DownloadBufferMemory(buffer); } } } @@ -1688,9 +1696,6 @@ void BufferCache

::ImmediateUploadMemory([[maybe_unused]] Buffer& buffer, if (immediate_buffer.empty()) { immediate_buffer = ImmediateBuffer(largest_copy); } - if (Settings::values.enable_gpu_buffer_readback.GetValue()) { - DownloadBufferMemory(buffer, device_addr, copy.size); - } device_memory.ReadBlockUnsafe(device_addr, immediate_buffer.data(), copy.size); upload_span = immediate_buffer.subspan(0, copy.size); } @@ -1709,9 +1714,6 @@ void BufferCache

::MappedUploadMemory([[maybe_unused]] Buffer& buffer, for (BufferCopy& copy : copies) { u8* const src_pointer = staging_pointer.data() + copy.src_offset; const DAddr device_addr = buffer.CpuAddr() + copy.dst_offset; - if (Settings::values.enable_gpu_buffer_readback.GetValue()) { - DownloadBufferMemory(buffer, device_addr, copy.size); - } device_memory.ReadBlockUnsafe(device_addr, src_pointer, copy.size); // Apply the staging offset copy.src_offset += upload_staging.offset; diff --git a/src/video_core/buffer_cache/buffer_cache_base.h b/src/video_core/buffer_cache/buffer_cache_base.h index 14ab3e6ebc..5d8a2a949d 100644 --- a/src/video_core/buffer_cache/buffer_cache_base.h +++ b/src/video_core/buffer_cache/buffer_cache_base.h @@ -435,6 +435,8 @@ private: bool SynchronizeBuffer(Buffer& buffer, DAddr device_addr, u32 size); + void SynchronizeBufferIfNeeded(Buffer& buffer); + void UploadMemory(Buffer& buffer, u64 total_size_bytes, u64 largest_copy, std::span copies);