From ec9354d6d92f4190d06dfb6b86e0098fa0108eac Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Mon, 18 Jan 2021 00:56:59 -0300 Subject: [PATCH] buffer_cache: Split CreateBuffer in separate functions Allow adding functionality to each function without making CreateBuffer more complex. --- src/video_core/buffer_cache/buffer_cache.h | 81 ++++++++++++++-------- 1 file changed, 52 insertions(+), 29 deletions(-) diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index bd8507610..3c44c3b39 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -71,6 +71,12 @@ class BufferCache { struct Empty {}; + struct OverlapResult { + std::vector ids; + VAddr begin; + VAddr end; + }; + struct Binding { VAddr cpu_addr{}; u32 size{}; @@ -220,6 +226,10 @@ private: [[nodiscard]] BufferId FindBuffer(VAddr cpu_addr, u32 size); + [[nodiscard]] OverlapResult ResolveOverlaps(VAddr cpu_addr, u32 wanted_size); + + void JoinOverlap(BufferId new_buffer_id, BufferId overlap_id); + [[nodiscard]] BufferId CreateBuffer(VAddr cpu_addr, u32 wanted_size); void Register(BufferId buffer_id); @@ -988,12 +998,12 @@ BufferId BufferCache

::FindBuffer(VAddr cpu_addr, u32 size) { } template -BufferId BufferCache

::CreateBuffer(VAddr cpu_addr, u32 wanted_size) { +typename BufferCache

::OverlapResult BufferCache

::ResolveOverlaps(VAddr cpu_addr, + u32 wanted_size) { std::vector overlap_ids; - VAddr cpu_addr_begin = cpu_addr; - VAddr cpu_addr_end = cpu_addr + wanted_size; - for (; cpu_addr >> PAGE_BITS < Common::DivCeil(cpu_addr_end, PAGE_SIZE); - cpu_addr += PAGE_SIZE) { + VAddr begin = cpu_addr; + VAddr end = cpu_addr + wanted_size; + for (; cpu_addr >> PAGE_BITS < Common::DivCeil(end, PAGE_SIZE); cpu_addr += PAGE_SIZE) { const BufferId overlap_id = page_table[cpu_addr >> PAGE_BITS]; if (!overlap_id) { continue; @@ -1005,35 +1015,48 @@ BufferId BufferCache

::CreateBuffer(VAddr cpu_addr, u32 wanted_size) { overlap.Pick(); overlap_ids.push_back(overlap_id); const VAddr overlap_cpu_addr = overlap.CpuAddr(); - if (overlap_cpu_addr < cpu_addr_begin) { - cpu_addr = cpu_addr_begin = overlap_cpu_addr; + if (overlap_cpu_addr < begin) { + cpu_addr = begin = overlap_cpu_addr; } - cpu_addr_end = std::max(cpu_addr_end, overlap_cpu_addr + overlap.SizeBytes()); + end = std::max(end, overlap_cpu_addr + overlap.SizeBytes()); } - const u32 size = static_cast(cpu_addr_end - cpu_addr_begin); - const BufferId new_buffer_id = slot_buffers.insert(runtime, rasterizer, cpu_addr_begin, size); + return OverlapResult{ + .ids = std::move(overlap_ids), + .begin = begin, + .end = end, + }; +} + +template +void BufferCache

::JoinOverlap(BufferId new_buffer_id, BufferId overlap_id) { Buffer& new_buffer = slot_buffers[new_buffer_id]; + Buffer& overlap = slot_buffers[overlap_id]; - for (const BufferId overlap_id : overlap_ids) { - Buffer& overlap = slot_buffers[overlap_id]; - overlap.Unpick(); - - std::vector copies; - const size_t dst_base_offset = overlap.CpuAddr() - new_buffer.CpuAddr(); - overlap.ForEachDownloadRange([&](u64 begin, u64 range_size) { - copies.push_back(BufferCopy{ - .src_offset = begin, - .dst_offset = dst_base_offset + begin, - .size = range_size, - }); - new_buffer.UnmarkRegionAsCpuModified(begin, range_size); - new_buffer.MarkRegionAsGpuModified(begin, range_size); + std::vector copies; + const size_t dst_base_offset = overlap.CpuAddr() - new_buffer.CpuAddr(); + overlap.ForEachDownloadRange([&](u64 begin, u64 range_size) { + copies.push_back(BufferCopy{ + .src_offset = begin, + .dst_offset = dst_base_offset + begin, + .size = range_size, }); - if (!copies.empty()) { - runtime.CopyBuffer(slot_buffers[new_buffer_id], overlap, copies); - } - ReplaceBufferDownloads(overlap_id, new_buffer_id); - DeleteBuffer(overlap_id); + new_buffer.UnmarkRegionAsCpuModified(begin, range_size); + new_buffer.MarkRegionAsGpuModified(begin, range_size); + }); + if (!copies.empty()) { + runtime.CopyBuffer(slot_buffers[new_buffer_id], overlap, copies); + } + ReplaceBufferDownloads(overlap_id, new_buffer_id); + DeleteBuffer(overlap_id); +} + +template +BufferId BufferCache

::CreateBuffer(VAddr cpu_addr, u32 wanted_size) { + const OverlapResult overlap = ResolveOverlaps(cpu_addr, wanted_size); + const u32 size = static_cast(overlap.end - overlap.begin); + const BufferId new_buffer_id = slot_buffers.insert(runtime, rasterizer, overlap.begin, size); + for (const BufferId overlap_id : overlap.ids) { + JoinOverlap(new_buffer_id, overlap_id); } Register(new_buffer_id); return new_buffer_id;