aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaranBr <maranbr@eden-emu.dev>2026-06-22 17:05:59 +0200
committercrueter <crueter@eden-emu.dev>2026-06-22 17:05:59 +0200
commit68aaea60855d7791480a546b8888e123e083ca1a (patch)
treeeb141ec12a09b727d57c82f7a84bf81b1ec6ecfa
parentba608d2b578b4f11784e6bac118d10790b1e7c2e (diff)
[buffer_cache] Refactor buffer synchronization to use bounding-box download region (#4094)
Implement bounding-box buffer synchronization to minimize downloads and preserve GPU-modified regions during uploads. Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4094 Reviewed-by: Lizzie <lizzie@eden-emu.dev> Reviewed-by: Shinmegumi <shinmegumi@eden-emu.dev>
-rw-r--r--src/video_core/buffer_cache/buffer_cache.h48
1 files changed, 22 insertions, 26 deletions
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h
index 7feae1462a..3494895f66 100644
--- a/src/video_core/buffer_cache/buffer_cache.h
+++ b/src/video_core/buffer_cache/buffer_cache.h
@@ -1619,36 +1619,33 @@ void BufferCache<P>::TouchBuffer(Buffer& buffer, BufferId buffer_id) noexcept {
template <class P>
bool BufferCache<P>::SynchronizeBuffer(Buffer& buffer, DAddr device_addr, u32 size) {
upload_copies.clear();
- u64 staging_offset = 0;
+ u64 total_size_bytes = 0;
u64 largest_copy = 0;
- DAddr buffer_start = buffer.CpuAddr();
- auto push = [&](u64 start, u64 end) {
- if (start >= end) {
- return;
- }
- u64 sz = end - start;
- upload_copies.push_back({
- .src_offset = staging_offset,
- .dst_offset = start - buffer_start,
- .size = sz
+ const DAddr buffer_start = buffer.cpu_addr_cached;
+ memory_tracker.ForEachUploadRange(device_addr, size, [&](u64 device_addr_out, u64 range_size) {
+ upload_copies.push_back(BufferCopy{
+ .src_offset = total_size_bytes,
+ .dst_offset = device_addr_out - buffer_start,
+ .size = range_size,
});
- staging_offset += sz;
- largest_copy = (std::max)(largest_copy, sz);
- };
- memory_tracker.ForEachUploadRange(device_addr, size, [&](u64 addr, u64 range_size) {
- u64 start = addr;
- u64 end = addr + range_size;
- gpu_modified_ranges.ForEachInRange(start, range_size, [&](u64 gstart, u64 gsize) {
- u64 gend = gstart + gsize;
- push(start, gstart);
- start = (std::max)(start, gend);
- });
- push(start, end);
+ total_size_bytes += range_size;
+ largest_copy = (std::max)(largest_copy, range_size);
});
- if (upload_copies.empty()) {
+ if (total_size_bytes == 0) {
return true;
}
- UploadMemory(buffer, staging_offset, largest_copy, std::span(upload_copies));
+ u64 min_offset = (std::numeric_limits<u64>::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<BufferCopy> copies_span(upload_copies.data(), upload_copies.size());
+ UploadMemory(buffer, total_size_bytes, largest_copy, copies_span);
+ any_buffer_uploaded = true;
return false;
}
@@ -1699,7 +1696,6 @@ void BufferCache<P>::MappedUploadMemory([[maybe_unused]] Buffer& buffer,
u8* const src_pointer = staging_pointer.data() + copy.src_offset;
const DAddr device_addr = buffer.CpuAddr() + copy.dst_offset;
device_memory.ReadBlockUnsafe(device_addr, src_pointer, copy.size);
-
// Apply the staging offset
copy.src_offset += upload_staging.offset;
}