diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 32c2066363..da86c14500 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -26,6 +26,7 @@ BufferCache

::BufferCache(Tegra::MaxwellDeviceMemoryManager& device_memory_, R // Ensure the first slot is used for the null buffer void(slot_buffers.insert(runtime, NullBufferParams{})); gpu_modified_ranges.Clear(); + in_place_gpu_written_ranges.Clear(); inline_buffer_id = NULL_BUFFER_ID; #ifdef YUZU_LEGACY immediately_free = (Settings::values.vram_usage_mode.GetValue() == Settings::VramUsageMode::Aggressive); @@ -116,7 +117,7 @@ template void BufferCache

::WriteMemory(DAddr device_addr, u64 size) { if (memory_tracker.IsRegionGpuModified(device_addr, size)) { ClearDownload(device_addr, size); - gpu_modified_ranges.Subtract(device_addr, size); + ForgetGpuModifiedRange(device_addr, size); } memory_tracker.MarkRegionAsCpuModified(device_addr, size); } @@ -231,7 +232,7 @@ bool BufferCache

::DMACopy(GPUVAddr src_address, GPUVAddr dest_address, u64 am }; gpu_modified_ranges.ForEachInRange(*cpu_src_address, amount, mirror); // This subtraction in this order is important for overlapping copies. - gpu_modified_ranges.Subtract(*cpu_dest_address, amount); + ForgetGpuModifiedRange(*cpu_dest_address, amount); const bool has_new_downloads = tmp_intervals.size() != 0; for (const auto& pair : tmp_intervals) { gpu_modified_ranges.Add(pair.first, pair.second); @@ -263,7 +264,7 @@ bool BufferCache

::DMAClear(GPUVAddr dst_address, u64 amount, u32 value) { const size_t size = amount * sizeof(u32); ClearDownload(*cpu_dst_address, size); - gpu_modified_ranges.Subtract(*cpu_dst_address, size); + ForgetGpuModifiedRange(*cpu_dst_address, size); const BufferId buffer = FindBuffer(*cpu_dst_address, static_cast(size)); Buffer& dest_buffer = slot_buffers[buffer]; @@ -308,7 +309,7 @@ std::pair BufferCache

::ObtainCPUBuffer( const DAddr device_addr_end = Common::AlignUp(device_addr + size, 64); const size_t new_size = device_addr_end - device_addr_start; ClearDownload(device_addr_start, new_size); - gpu_modified_ranges.Subtract(device_addr_start, new_size); + ForgetGpuModifiedRange(device_addr_start, new_size); break; } default: @@ -760,7 +761,7 @@ void BufferCache

::PopAsyncBuffers() { {start, &read_mapped_memory[start - device_addr], end - start}); }); async_downloads.Subtract(device_addr, copy.size, [&](DAddr start, DAddr end) { - gpu_modified_ranges.Subtract(start, end - start); + ForgetGpuModifiedRange(start, end - start); }); } async_buffers_death_ring.emplace_back(*async_buffer); @@ -768,7 +769,7 @@ void BufferCache

::PopAsyncBuffers() { for (const auto& copy : batch.unified_copies) { const DAddr device_addr = static_cast(copy.src_offset); async_downloads.Subtract(device_addr, copy.size, [&](DAddr start, DAddr end) { - gpu_modified_ranges.Subtract(start, end - start); + ForgetGpuModifiedRange(start, end - start); }); } async_buffers.pop_front(); @@ -1580,6 +1581,20 @@ void BufferCache

::MarkWrittenBuffer(BufferId buffer_id, DAddr device_addr, u3 uncommitted_gpu_modified_ranges.Add(device_addr, size); } +template +void BufferCache

::MarkWrittenBufferInPlace(DAddr device_addr, u32 size) { + memory_tracker.MarkRegionAsGpuModified(device_addr, size); + gpu_modified_ranges.Add(device_addr, size); + uncommitted_gpu_modified_ranges.Add(device_addr, size); + in_place_gpu_written_ranges.Add(device_addr, size); +} + +template +void BufferCache

::ForgetGpuModifiedRange(DAddr device_addr, u64 size) { + gpu_modified_ranges.Subtract(device_addr, size); + in_place_gpu_written_ranges.Subtract(device_addr, size); +} + template BufferId BufferCache

::FindBuffer(DAddr device_addr, u32 size) { if (device_addr == 0) { @@ -2063,7 +2078,7 @@ template void BufferCache

::InlineMemoryImplementation(DAddr dest_address, size_t copy_size, std::span inlined_buffer) { ClearDownload(dest_address, copy_size); - gpu_modified_ranges.Subtract(dest_address, copy_size); + ForgetGpuModifiedRange(dest_address, copy_size); BufferId buffer_id = FindBuffer(dest_address, static_cast(copy_size)); auto& buffer = slot_buffers[buffer_id]; @@ -2115,7 +2130,7 @@ void BufferCache

::DownloadBufferMemory(Buffer& buffer, DAddr device_addr, u64 gpu_modified_ranges.ForEachInRange(device_addr_out, range_size, add_download); ClearDownload(device_addr_out, range_size); - gpu_modified_ranges.Subtract(device_addr_out, range_size); + ForgetGpuModifiedRange(device_addr_out, range_size); }); if (total_size_bytes == 0) { return; diff --git a/src/video_core/buffer_cache/buffer_cache_base.h b/src/video_core/buffer_cache/buffer_cache_base.h index e30f768bb5..49cc1ba08f 100644 --- a/src/video_core/buffer_cache/buffer_cache_base.h +++ b/src/video_core/buffer_cache/buffer_cache_base.h @@ -418,6 +418,10 @@ private: void MarkWrittenBuffer(BufferId buffer_id, DAddr device_addr, u32 size); + void MarkWrittenBufferInPlace(DAddr device_addr, u32 size); + + void ForgetGpuModifiedRange(DAddr device_addr, u64 size); + [[nodiscard]] BufferId FindBuffer(DAddr device_addr, u32 size); void WaitForGpuFenceIfNeeded(Buffer& buffer); @@ -513,6 +517,7 @@ private: MemoryTracker memory_tracker; Common::RangeSet uncommitted_gpu_modified_ranges; Common::RangeSet gpu_modified_ranges; + Common::RangeSet in_place_gpu_written_ranges; std::deque> committed_gpu_modified_ranges; // Async Buffers