Просмотр исходного кода

buffer_cache: Split CreateBuffer in separate functions

Allow adding functionality to each function without making CreateBuffer
more complex.
ReinUsesLisp 5 лет назад
Родитель
Сommit
ec9354d6d9
1 измененных файлов с 52 добавлено и 29 удалено
  1. 52 29
      src/video_core/buffer_cache/buffer_cache.h

+ 52 - 29
src/video_core/buffer_cache/buffer_cache.h

@@ -71,6 +71,12 @@ class BufferCache {
 
     struct Empty {};
 
+    struct OverlapResult {
+        std::vector<BufferId> 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<P>::FindBuffer(VAddr cpu_addr, u32 size) {
 }
 
 template <class P>
-BufferId BufferCache<P>::CreateBuffer(VAddr cpu_addr, u32 wanted_size) {
+typename BufferCache<P>::OverlapResult BufferCache<P>::ResolveOverlaps(VAddr cpu_addr,
+                                                                       u32 wanted_size) {
     std::vector<BufferId> 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<P>::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<u32>(cpu_addr_end - cpu_addr_begin);
-    const BufferId new_buffer_id = slot_buffers.insert(runtime, rasterizer, cpu_addr_begin, size);
-    Buffer& new_buffer = slot_buffers[new_buffer_id];
+    return OverlapResult{
+        .ids = std::move(overlap_ids),
+        .begin = begin,
+        .end = end,
+    };
+}
 
-    for (const BufferId overlap_id : overlap_ids) {
-        Buffer& overlap = slot_buffers[overlap_id];
-        overlap.Unpick();
+template <class P>
+void BufferCache<P>::JoinOverlap(BufferId new_buffer_id, BufferId overlap_id) {
+    Buffer& new_buffer = slot_buffers[new_buffer_id];
+    Buffer& overlap = slot_buffers[overlap_id];
 
-        std::vector<BufferCopy> 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<BufferCopy> 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 <class P>
+BufferId BufferCache<P>::CreateBuffer(VAddr cpu_addr, u32 wanted_size) {
+    const OverlapResult overlap = ResolveOverlaps(cpu_addr, wanted_size);
+    const u32 size = static_cast<u32>(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;