summaryrefslogtreecommitdiff
path: root/src/video_core/buffer_cache
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core/buffer_cache')
-rw-r--r--src/video_core/buffer_cache/buffer_cache.h81
1 files 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 {
71 71
72 struct Empty {}; 72 struct Empty {};
73 73
74 struct OverlapResult {
75 std::vector<BufferId> ids;
76 VAddr begin;
77 VAddr end;
78 };
79
74 struct Binding { 80 struct Binding {
75 VAddr cpu_addr{}; 81 VAddr cpu_addr{};
76 u32 size{}; 82 u32 size{};
@@ -220,6 +226,10 @@ private:
220 226
221 [[nodiscard]] BufferId FindBuffer(VAddr cpu_addr, u32 size); 227 [[nodiscard]] BufferId FindBuffer(VAddr cpu_addr, u32 size);
222 228
229 [[nodiscard]] OverlapResult ResolveOverlaps(VAddr cpu_addr, u32 wanted_size);
230
231 void JoinOverlap(BufferId new_buffer_id, BufferId overlap_id);
232
223 [[nodiscard]] BufferId CreateBuffer(VAddr cpu_addr, u32 wanted_size); 233 [[nodiscard]] BufferId CreateBuffer(VAddr cpu_addr, u32 wanted_size);
224 234
225 void Register(BufferId buffer_id); 235 void Register(BufferId buffer_id);
@@ -988,12 +998,12 @@ BufferId BufferCache<P>::FindBuffer(VAddr cpu_addr, u32 size) {
988} 998}
989 999
990template <class P> 1000template <class P>
991BufferId BufferCache<P>::CreateBuffer(VAddr cpu_addr, u32 wanted_size) { 1001typename BufferCache<P>::OverlapResult BufferCache<P>::ResolveOverlaps(VAddr cpu_addr,
1002 u32 wanted_size) {
992 std::vector<BufferId> overlap_ids; 1003 std::vector<BufferId> overlap_ids;
993 VAddr cpu_addr_begin = cpu_addr; 1004 VAddr begin = cpu_addr;
994 VAddr cpu_addr_end = cpu_addr + wanted_size; 1005 VAddr end = cpu_addr + wanted_size;
995 for (; cpu_addr >> PAGE_BITS < Common::DivCeil(cpu_addr_end, PAGE_SIZE); 1006 for (; cpu_addr >> PAGE_BITS < Common::DivCeil(end, PAGE_SIZE); cpu_addr += PAGE_SIZE) {
996 cpu_addr += PAGE_SIZE) {
997 const BufferId overlap_id = page_table[cpu_addr >> PAGE_BITS]; 1007 const BufferId overlap_id = page_table[cpu_addr >> PAGE_BITS];
998 if (!overlap_id) { 1008 if (!overlap_id) {
999 continue; 1009 continue;
@@ -1005,35 +1015,48 @@ BufferId BufferCache<P>::CreateBuffer(VAddr cpu_addr, u32 wanted_size) {
1005 overlap.Pick(); 1015 overlap.Pick();
1006 overlap_ids.push_back(overlap_id); 1016 overlap_ids.push_back(overlap_id);
1007 const VAddr overlap_cpu_addr = overlap.CpuAddr(); 1017 const VAddr overlap_cpu_addr = overlap.CpuAddr();
1008 if (overlap_cpu_addr < cpu_addr_begin) { 1018 if (overlap_cpu_addr < begin) {
1009 cpu_addr = cpu_addr_begin = overlap_cpu_addr; 1019 cpu_addr = begin = overlap_cpu_addr;
1010 } 1020 }
1011 cpu_addr_end = std::max(cpu_addr_end, overlap_cpu_addr + overlap.SizeBytes()); 1021 end = std::max(end, overlap_cpu_addr + overlap.SizeBytes());
1012 } 1022 }
1013 const u32 size = static_cast<u32>(cpu_addr_end - cpu_addr_begin); 1023 return OverlapResult{
1014 const BufferId new_buffer_id = slot_buffers.insert(runtime, rasterizer, cpu_addr_begin, size); 1024 .ids = std::move(overlap_ids),
1015 Buffer& new_buffer = slot_buffers[new_buffer_id]; 1025 .begin = begin,
1026 .end = end,
1027 };
1028}
1016 1029
1017 for (const BufferId overlap_id : overlap_ids) { 1030template <class P>
1018 Buffer& overlap = slot_buffers[overlap_id]; 1031void BufferCache<P>::JoinOverlap(BufferId new_buffer_id, BufferId overlap_id) {
1019 overlap.Unpick(); 1032 Buffer& new_buffer = slot_buffers[new_buffer_id];
1033 Buffer& overlap = slot_buffers[overlap_id];
1020 1034
1021 std::vector<BufferCopy> copies; 1035 std::vector<BufferCopy> copies;
1022 const size_t dst_base_offset = overlap.CpuAddr() - new_buffer.CpuAddr(); 1036 const size_t dst_base_offset = overlap.CpuAddr() - new_buffer.CpuAddr();
1023 overlap.ForEachDownloadRange([&](u64 begin, u64 range_size) { 1037 overlap.ForEachDownloadRange([&](u64 begin, u64 range_size) {
1024 copies.push_back(BufferCopy{ 1038 copies.push_back(BufferCopy{
1025 .src_offset = begin, 1039 .src_offset = begin,
1026 .dst_offset = dst_base_offset + begin, 1040 .dst_offset = dst_base_offset + begin,
1027 .size = range_size, 1041 .size = range_size,
1028 });
1029 new_buffer.UnmarkRegionAsCpuModified(begin, range_size);
1030 new_buffer.MarkRegionAsGpuModified(begin, range_size);
1031 }); 1042 });
1032 if (!copies.empty()) { 1043 new_buffer.UnmarkRegionAsCpuModified(begin, range_size);
1033 runtime.CopyBuffer(slot_buffers[new_buffer_id], overlap, copies); 1044 new_buffer.MarkRegionAsGpuModified(begin, range_size);
1034 } 1045 });
1035 ReplaceBufferDownloads(overlap_id, new_buffer_id); 1046 if (!copies.empty()) {
1036 DeleteBuffer(overlap_id); 1047 runtime.CopyBuffer(slot_buffers[new_buffer_id], overlap, copies);
1048 }
1049 ReplaceBufferDownloads(overlap_id, new_buffer_id);
1050 DeleteBuffer(overlap_id);
1051}
1052
1053template <class P>
1054BufferId BufferCache<P>::CreateBuffer(VAddr cpu_addr, u32 wanted_size) {
1055 const OverlapResult overlap = ResolveOverlaps(cpu_addr, wanted_size);
1056 const u32 size = static_cast<u32>(overlap.end - overlap.begin);
1057 const BufferId new_buffer_id = slot_buffers.insert(runtime, rasterizer, overlap.begin, size);
1058 for (const BufferId overlap_id : overlap.ids) {
1059 JoinOverlap(new_buffer_id, overlap_id);
1037 } 1060 }
1038 Register(new_buffer_id); 1061 Register(new_buffer_id);
1039 return new_buffer_id; 1062 return new_buffer_id;