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

::TouchBuffer(Buffer& buffer, BufferId buffer_id) noexcept { template bool BufferCache

::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::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; return false; } @@ -1699,7 +1696,6 @@ void BufferCache

::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; }