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 ca282ba159..e9f818d9bc 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 @@ -549,7 +549,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 44f86d380f..fe8e1e0555 100644 --- a/src/android/app/src/main/res/values-ar/strings.xml +++ b/src/android/app/src/main/res/values-ar/strings.xml @@ -580,8 +580,6 @@ يحسن دقة العرض في بعض الألعاب على حساب الأداء. تمكين سجل التخزين المؤقت يُتيح هذا الخيار الوصول إلى حالات التخزين المؤقت السابقة. وقد يُحسّن جودة العرض وثبات الأداء في بعض الألعاب. - تفعيل قراءة مخزن وحدة معالجة الرسومات - يحافظ هذا النظام على بيانات المخزن المؤقت المُعدّلة بواسطة وحدة معالجة الرسومات عن طريق قراءتها مرة أخرى قبل التحميل. تتطلب بعض الألعاب ذلك لعرض بعض التأثيرات بشكل صحيح. قد يُسبب ذلك مشاكل إذا لم يتمكن الجهاز من التعامل مع عبء العمل الإضافي. مخازن الرؤوس المُحسّنة يُتيح ربطًا مُحسَّنًا لمخازن الرؤوس لتحسين الأداء. يتطلب برامج تشغيل Mesa 26.0+ Turnip/ برامج تشغيل QCOM. قد يتعطل على برامج تشغيل Turnip القديمة (25.3 وما دون). @@ -1099,7 +1097,6 @@ فوري متوازن دقيق - صارم محافظ عدواني diff --git a/src/android/app/src/main/res/values-de/strings.xml b/src/android/app/src/main/res/values-de/strings.xml index 6ed158fc72..8f6b691176 100644 --- a/src/android/app/src/main/res/values-de/strings.xml +++ b/src/android/app/src/main/res/values-de/strings.xml @@ -967,7 +967,6 @@ Wirklich fortfahren? Direkt Ausgewogen Genau - Strikt Konservativ Aggressiv 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 3444ccaa71..72f8d74203 100644 --- a/src/android/app/src/main/res/values-es/strings.xml +++ b/src/android/app/src/main/res/values-es/strings.xml @@ -524,8 +524,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). @@ -1038,7 +1036,6 @@ Inmediato Equilibrado Preciso - Estricto Conservador Agresivo diff --git a/src/android/app/src/main/res/values-ru/strings.xml b/src/android/app/src/main/res/values-ru/strings.xml index 7bfe003317..912ce84caf 100644 --- a/src/android/app/src/main/res/values-ru/strings.xml +++ b/src/android/app/src/main/res/values-ru/strings.xml @@ -569,8 +569,6 @@ Повышение точности рендеринга в некоторых играх за счет снижения производительности. Включить историю буфера Позволяет обращаться к предыдущим состояниям буфера. Эта опция может повысить качество рендеринга и стабильность производительности в некоторых играх. - Включить обратное чтение буфера ГПУ - Сохраняет измененные ГПУ данные буфера путем чтения их обратно перед выгрузками. Некоторые игры требуют этого, чтобы рендерить определенные эффекты правильно. Может вызывать проблемы если оборудование не может обработать дополнительную рабочую нагрузку. Оптимизированные вершинные буферы Включает оптимизированную привязку вершинного буфера для повышения производительности. Требует Mesa Turnip 26.0+ / QCOM. Приводит к вылету на старых версиях драйверов Turnip (25.3 и ниже). @@ -1088,7 +1086,6 @@ Мгновенный Сбалансированный Точный - Строгий Консервативный Агрессивный 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 2f41b5d65a..19f5f0aae7 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 @@ -570,8 +570,6 @@ 通过牺牲性能来提升某些游戏的渲染精度。 启用缓冲区历史 启用对先前缓冲区状态的访问。此选项可在某些游戏中提升渲染质量并保持性能的一致性。 - 启用 GPU 缓冲区回读 - 在上传前回读经由 GPU 修改过的缓冲区数据,以将其保留。一些游戏会用到这项设定以正确渲染某些效果。如果硬件无法处理额外的工作负载,则可能会导致问题。 优化顶点缓冲区 启用经过优化的顶点缓冲区绑定以提升性能。需要 Mesa 26.0 及以上版本的 Turnip 或 QCOM 驱动程序。若使用较旧版本的 Turnip 驱动 (25.3 及以下版本) 则会导致崩溃。 @@ -1089,7 +1087,6 @@ 即时 均衡 精确 - 严格 保守式 主动式 diff --git a/src/android/app/src/main/res/values-zh-rTW/strings.xml b/src/android/app/src/main/res/values-zh-rTW/strings.xml index 5db1e31a2b..044b7675de 100644 --- a/src/android/app/src/main/res/values-zh-rTW/strings.xml +++ b/src/android/app/src/main/res/values-zh-rTW/strings.xml @@ -561,8 +561,6 @@ 犧牲效能,以改善部分遊戲的轉譯準確度 啟用緩衝區歷史 允許存取先前的緩衝區狀態。此選項可能會改善部分遊戲的渲染品質與效能穩定性 - 啟用 GPU 緩衝區讀回 - 透過在上傳之前先將 GPU 修改過的緩衝區資料讀回來保存資料,部分遊戲需要啟用此功能才能正常渲染遊戲特效。如果硬體無法負荷可能會導致錯誤 最佳化頂點緩衝區 啟用最佳化的頂點緩衝區綁定。需要安裝 Mesa 26.0+ Turnip drivers/Qualcomm drivers。使用舊版 Turnip drivers 會導致當機 (25.3版和更低的版本) diff --git a/src/android/app/src/main/res/values/arrays.xml b/src/android/app/src/main/res/values/arrays.xml index b3aed5758c..be367a2fcf 100644 --- a/src/android/app/src/main/res/values/arrays.xml +++ b/src/android/app/src/main/res/values/arrays.xml @@ -558,7 +558,6 @@ @string/gpu_fence_behavior_immediate @string/gpu_fence_behavior_balanced @string/gpu_fence_behavior_accurate - @string/gpu_fence_behavior_strict 0 diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index 730f6bbade..5a587be351 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -586,8 +586,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). @@ -1138,7 +1136,6 @@ Immediate Balanced Accurate - Strict CPU diff --git a/src/common/settings.cpp b/src/common/settings.cpp index bc46b61bb4..3f5154026e 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp @@ -178,10 +178,6 @@ bool IsGPUFenceBehaviorAccurate() { return values.gpu_fence_behavior.GetValue() == GpuFenceBehavior::Accurate; } -bool IsGPUFenceBehaviorStrict() { - return values.gpu_fence_behavior.GetValue() == GpuFenceBehavior::Strict; -} - bool IsFastmemEnabled() { if (values.cpu_accuracy.GetValue() == Settings::CpuAccuracy::Debugging) return bool(values.cpuopt_fastmem); diff --git a/src/common/settings.h b/src/common/settings.h index c1c2d4f0df..5d66f49ebd 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -525,7 +525,7 @@ struct Values { SwitchableSetting gpu_fence_behavior{linkage, GpuFenceBehavior::Default, GpuFenceBehavior::Default, - GpuFenceBehavior::Strict, + GpuFenceBehavior::Accurate, "gpu_fence_behavior", Category::RendererAdvanced, Specialization::Default, @@ -655,13 +655,6 @@ struct Values { SwitchableSetting rescale_hack{linkage, false, "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}; @@ -979,7 +972,6 @@ bool IsDMALevelSafe(); bool IsGPUFenceBehaviorDefault(); bool IsGPUFenceBehaviorBalanced(); bool IsGPUFenceBehaviorAccurate(); -bool IsGPUFenceBehaviorStrict(); bool IsFastmemEnabled(); void SetNceEnabled(bool is_64bit); diff --git a/src/common/settings_enums.h b/src/common/settings_enums.h index 4b406f4c35..55acb0ae8c 100644 --- a/src/common/settings_enums.h +++ b/src/common/settings_enums.h @@ -137,7 +137,7 @@ ENUM(VramUsageMode, Conservative, Aggressive); ENUM(RendererBackend, OpenGL_GLSL, Vulkan, Null, OpenGL_GLASM, OpenGL_SPIRV); ENUM(GpuAccuracy, Low, High); ENUM(DmaAccuracy, Default, Unsafe, Safe); -ENUM(GpuFenceBehavior, Default, Immediate, Balanced, Accurate, Strict); +ENUM(GpuFenceBehavior, Default, Immediate, Balanced, Accurate); ENUM(CpuBackend, Dynarmic, Nce); ENUM(CpuAccuracy, Auto, Accurate, Unsafe, Paranoid, Debugging); ENUM(CpuClock, Normal, Boost, Overclock) diff --git a/src/qt_common/config/shared_translation.cpp b/src/qt_common/config/shared_translation.cpp index 4ef97c602a..d61c84e278 100644 --- a/src/qt_common/config/shared_translation.cpp +++ b/src/qt_common/config/shared_translation.cpp @@ -226,9 +226,7 @@ std::unique_ptr InitializeTranslations(QObject* parent) { INSERT(Settings, dma_accuracy, tr("DMA Accuracy:"), 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.")); + 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.\nDefault follows the GPU Mode setting.")); INSERT(Settings, use_asynchronous_shaders, tr("Enable asynchronous shader compilation"), tr("May reduce shader stutter.")); INSERT(Settings, gpu_clock, tr("GPU Clocks"), @@ -442,7 +440,6 @@ std::unique_ptr ComboboxEnumeration(QObject* parent) { PAIR(GpuFenceBehavior, Immediate, tr("Immediate")), PAIR(GpuFenceBehavior, Balanced, tr("Balanced")), PAIR(GpuFenceBehavior, Accurate, tr("Accurate")), - PAIR(GpuFenceBehavior, Strict, tr("Strict")), }}); translations->insert( {Settings::EnumMetadata::Index(), diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 576f20c4e7..e87cefdfa0 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -249,6 +249,10 @@ bool BufferCache

::DMACopy(GPUVAddr src_address, GPUVAddr dest_address, u64 am runtime.CopyBuffer(dest_buffer, src_buffer, copies, true); if (has_new_downloads) { memory_tracker.MarkRegionAsGpuModified(*cpu_dest_address, amount); + const bool should_sync = Settings::IsGPUFenceBehaviorBalanced(); + if (should_sync) { + runtime.Finish(); + } } Tegra::Memory::DeviceGuestMemoryScoped @@ -1230,7 +1234,7 @@ void BufferCache

::BindHostComputeStorageBuffers() { buffer.MarkUsage(offset, size); if (is_written) { - MarkWrittenBuffer(binding.buffer_id, binding.device_addr, size); + MarkWrittenBuffer(binding.buffer_id, binding.device_addr, size, true); } if constexpr (NEEDS_BIND_STORAGE_INDEX) { @@ -1516,10 +1520,12 @@ void BufferCache

::UpdateComputeTextureBuffers() { } template -void BufferCache

::MarkWrittenBuffer(BufferId buffer_id, DAddr device_addr, u32 size) { +void BufferCache

::MarkWrittenBuffer(BufferId buffer_id, DAddr device_addr, u32 size, bool needs_sync) { if constexpr (!IS_OPENGL) { - Buffer& buffer = slot_buffers[buffer_id]; - buffer.setWriteTick(runtime.CurrentTick()); + if (needs_sync) { + Buffer& buffer = slot_buffers[buffer_id]; + buffer.setWriteTick(runtime.CurrentTick()); + } } memory_tracker.MarkRegionAsGpuModified(device_addr, size); gpu_modified_ranges.Add(device_addr, size); @@ -1535,8 +1541,11 @@ BufferId BufferCache

::FindBuffer(DAddr device_addr, u32 size, bool sparse_com const BufferId buffer_id = page_table[page]; if (buffer_id) { Buffer& buffer = slot_buffers[buffer_id]; - WaitForGpuFenceIfNeeded(buffer); if (buffer.IsInBounds(device_addr, size)) { + const bool should_sync = Settings::IsGPUFenceBehaviorAccurate(); + if (should_sync) { + SynchronizeBufferWrites(buffer); + } bool usable = true; if constexpr (requires { buffer.IsSparseCompatible(); }) { if (sparse_compatible && !buffer.IsSparseCompatible()) { @@ -1552,17 +1561,11 @@ BufferId BufferCache

::FindBuffer(DAddr device_addr, u32 size, bool sparse_com } template -void BufferCache

::WaitForGpuFenceIfNeeded(Buffer& buffer) { +void BufferCache

::SynchronizeBufferWrites(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); - } + const u64 buffer_tick = buffer.GetWriteTick(); + if (!runtime.IsFree(buffer_tick)) { + runtime.Wait(buffer_tick); } } } @@ -1795,9 +1798,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); } @@ -1816,9 +1816,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 0dbb368c47..26bf3dd9ed 100644 --- a/src/video_core/buffer_cache/buffer_cache_base.h +++ b/src/video_core/buffer_cache/buffer_cache_base.h @@ -430,11 +430,11 @@ private: void UpdateComputeTextureBuffers(); - void MarkWrittenBuffer(BufferId buffer_id, DAddr device_addr, u32 size); + void MarkWrittenBuffer(BufferId buffer_id, DAddr device_addr, u32 size, bool needs_sync = false); [[nodiscard]] BufferId FindBuffer(DAddr device_addr, u32 size, bool sparse_compatible); - void WaitForGpuFenceIfNeeded(Buffer& buffer); + void SynchronizeBufferWrites(Buffer& buffer); [[nodiscard]] OverlapResult ResolveOverlaps(DAddr device_addr, u32 wanted_size); diff --git a/src/video_core/fence_manager.h b/src/video_core/fence_manager.h index 885c714025..776c01e3fa 100644 --- a/src/video_core/fence_manager.h +++ b/src/video_core/fence_manager.h @@ -72,7 +72,7 @@ public: } void SignalFence(std::function&& func) { - const bool delay_fence = Settings::IsGPUFenceBehaviorDefault() ? Settings::IsGPULevelHigh() : Settings::IsGPUFenceBehaviorBalanced() || Settings::IsGPUFenceBehaviorAccurate() || Settings::IsGPUFenceBehaviorStrict(); + const bool delay_fence = Settings::IsGPUFenceBehaviorDefault() ? Settings::IsGPULevelHigh() : Settings::IsGPUFenceBehaviorBalanced() || Settings::IsGPUFenceBehaviorAccurate(); const bool should_flush = ShouldFlush(); if constexpr (!can_async_check) { TryReleasePendingFences(); diff --git a/src/video_core/query_cache/query_cache.h b/src/video_core/query_cache/query_cache.h index 5404dec943..b8c1bc4f45 100644 --- a/src/video_core/query_cache/query_cache.h +++ b/src/video_core/query_cache/query_cache.h @@ -260,7 +260,7 @@ void QueryCacheBase::CounterReport(GPUVAddr addr, QueryType counter_type }; u8* pointer = impl->device_memory.template GetPointer(cpu_addr); u8* pointer_timestamp = impl->device_memory.template GetPointer(cpu_addr + 8); - bool is_synced = (Settings::IsGPUFenceBehaviorDefault() ? !Settings::IsGPULevelHigh() : !Settings::IsGPUFenceBehaviorBalanced() && !Settings::IsGPUFenceBehaviorAccurate() && !Settings::IsGPUFenceBehaviorStrict()) && is_fence; + bool is_synced = (Settings::IsGPUFenceBehaviorDefault() ? !Settings::IsGPULevelHigh() : !Settings::IsGPUFenceBehaviorBalanced() && !Settings::IsGPUFenceBehaviorAccurate()) && is_fence; std::function operation([this, is_synced, streamer, query_base = query, query_location, pointer, pointer_timestamp] { if (True(query_base->flags & QueryFlagBits::IsInvalidated)) { diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp index 958f3b2a2e..1a33189bf8 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp @@ -419,15 +419,15 @@ void BufferCacheRuntime::TickFrame(Common::SlotVector& slot_buffers) noe } u64 BufferCacheRuntime::CurrentTick() { - return scheduler.GetMasterSemaphore().CurrentTick(); + return scheduler.CurrentTick(); } -u64 BufferCacheRuntime::KnownGpuTick() { - return scheduler.GetMasterSemaphore().KnownGpuTick(); +bool BufferCacheRuntime::IsFree(u64 tick) { + return scheduler.IsFree(tick); } -void BufferCacheRuntime::Wait(u64 buffer_tick) { - scheduler.Wait(buffer_tick); +void BufferCacheRuntime::Wait(u64 tick) { + scheduler.Wait(tick); } void BufferCacheRuntime::Finish() { diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.h b/src/video_core/renderer_vulkan/vk_buffer_cache.h index fbd8c2e753..fff1f8164d 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.h +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.h @@ -112,9 +112,9 @@ public: u64 CurrentTick(); - u64 KnownGpuTick(); + bool IsFree(u64 tick); - void Wait(u64 buffer_tick); + void Wait(u64 tick); void Finish();