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 63ac7b0630..579ea3b258 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 594099f159..27a5bba655 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 @@ -294,7 +294,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 dd03ec453f..0a6124cd82 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 a5092c4b2f..0f83543e40 100644 --- a/src/android/app/src/main/res/values-es/strings.xml +++ b/src/android/app/src/main/res/values-es/strings.xml @@ -491,8 +491,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 1e6ba26041..005979e62f 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 bb1d85db82..2ecf0ec418 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 0f35045622..8a41d61ade 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 26597d412c..94ef8edf8a 100644 --- a/src/qt_common/config/shared_translation.cpp +++ b/src/qt_common/config/shared_translation.cpp @@ -223,8 +223,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, gpu_clock, tr("GPU Clocks"), 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);