diff --git a/src/common/settings.h b/src/common/settings.h index 5f6e1a2206..bc798ae755 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -573,6 +573,13 @@ 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 6778f37f7b..72241bab51 100644 --- a/src/qt_common/config/shared_translation.cpp +++ b/src/qt_common/config/shared_translation.cpp @@ -229,6 +229,8 @@ std::unique_ptr InitializeTranslations(QObject* parent) { INSERT(Settings, dma_accuracy, tr("DMA Accuracy:"), tr("Controls the DMA precision accuracy. Safe precision fixes issues in some games but " "may degrade performance.")); + INSERT(Settings, enable_gpu_buffer_readback, tr("Enable GPU buffer readback"), + tr("Preserves GPU-modified buffer data by reading it back before uploads.\nSome games require this to render certain effects properly.\nMay cause issues if the hardware cannot handle the additional workload.")); 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 3494895f66..740d99558e 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -1634,15 +1634,17 @@ bool BufferCache

::SynchronizeBuffer(Buffer& buffer, DAddr device_addr, u32 si if (total_size_bytes == 0) { return true; } - u64 min_offset = (std::numeric_limits::max)(); - u64 max_offset = 0; - for (const auto& copy : upload_copies) { - min_offset = (std::min)(min_offset, copy.dst_offset); - max_offset = (std::max)(max_offset, copy.dst_offset + copy.size); - } - const DAddr sync_addr = buffer.CpuAddr() + min_offset; - const u64 sync_size = max_offset - min_offset; - DownloadBufferMemory(buffer, sync_addr, sync_size); + if (Settings::values.enable_gpu_buffer_readback.GetValue()) { + u64 min_offset = (std::numeric_limits::max)(); + u64 max_offset = 0; + for (const auto& copy : upload_copies) { + min_offset = (std::min)(min_offset, copy.dst_offset); + max_offset = (std::max)(max_offset, copy.dst_offset + copy.size); + } + const DAddr sync_addr = buffer.CpuAddr() + min_offset; + const u64 sync_size = max_offset - min_offset; + DownloadBufferMemory(buffer, sync_addr, sync_size); + } const std::span copies_span(upload_copies.data(), upload_copies.size()); UploadMemory(buffer, total_size_bytes, largest_copy, copies_span); any_buffer_uploaded = true;