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.h63
-rw-r--r--src/video_core/buffer_cache/map_interval.h62
2 files changed, 76 insertions, 49 deletions
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h
index e36f85705..7c1737fe2 100644
--- a/src/video_core/buffer_cache/buffer_cache.h
+++ b/src/video_core/buffer_cache/buffer_cache.h
@@ -25,6 +25,8 @@ class RasterizerInterface;
25 25
26namespace VideoCommon { 26namespace VideoCommon {
27 27
28using MapInterval = std::shared_ptr<MapIntervalBase>;
29
28template <typename TBuffer, typename TBufferType, typename StreamBuffer> 30template <typename TBuffer, typename TBufferType, typename StreamBuffer>
29class BufferCache { 31class BufferCache {
30public: 32public:
@@ -90,7 +92,9 @@ public:
90 92
91 std::vector<MapInterval> objects = GetMapsInRange(addr, size); 93 std::vector<MapInterval> objects = GetMapsInRange(addr, size);
92 for (auto& object : objects) { 94 for (auto& object : objects) {
93 Unregister(object); 95 if (object->IsRegistered()) {
96 Unregister(object);
97 }
94 } 98 }
95 } 99 }
96 100
@@ -120,51 +124,54 @@ protected:
120 std::size_t dst_offset, std::size_t size) = 0; 124 std::size_t dst_offset, std::size_t size) = 0;
121 125
122 /// Register an object into the cache 126 /// Register an object into the cache
123 void Register(const MapInterval& new_interval, const GPUVAddr gpu_addr) { 127 void Register(const MapInterval& new_map) {
124 const CacheAddr cache_ptr = new_interval.start; 128 const CacheAddr cache_ptr = new_map->GetStart();
125 const std::size_t size = new_interval.end - new_interval.start;
126 const std::optional<VAddr> cpu_addr = 129 const std::optional<VAddr> cpu_addr =
127 system.GPU().MemoryManager().GpuToCpuAddress(gpu_addr); 130 system.GPU().MemoryManager().GpuToCpuAddress(new_map->GetGpuAddress());
128 if (!cache_ptr || !cpu_addr) { 131 if (!cache_ptr || !cpu_addr) {
129 LOG_CRITICAL(HW_GPU, "Failed to register buffer with unmapped gpu_address 0x{:016x}", 132 LOG_CRITICAL(HW_GPU, "Failed to register buffer with unmapped gpu_address 0x{:016x}",
130 gpu_addr); 133 new_map->GetGpuAddress());
131 return; 134 return;
132 } 135 }
133 const IntervalType interval{new_interval.start, new_interval.end}; 136 const std::size_t size = new_map->GetEnd() - new_map->GetStart();
134 mapped_addresses.insert(interval); 137 new_map->SetCpuAddress(*cpu_addr);
135 map_storage[new_interval] = MapInfo{gpu_addr, *cpu_addr}; 138 new_map->MarkAsRegistered(true);
136 139 const IntervalType interval{new_map->GetStart(), new_map->GetEnd()};
140 mapped_addresses.insert({interval, new_map});
137 rasterizer.UpdatePagesCachedCount(*cpu_addr, size, 1); 141 rasterizer.UpdatePagesCachedCount(*cpu_addr, size, 1);
138 } 142 }
139 143
140 /// Unregisters an object from the cache 144 /// Unregisters an object from the cache
141 void Unregister(const MapInterval& interval) { 145 void Unregister(MapInterval& map) {
142 const MapInfo info = map_storage[interval]; 146 const std::size_t size = map->GetEnd() - map->GetStart();
143 const std::size_t size = interval.end - interval.start; 147 rasterizer.UpdatePagesCachedCount(map->GetCpuAddress(), size, -1);
144 rasterizer.UpdatePagesCachedCount(info.cpu_addr, size, -1); 148 map->MarkAsRegistered(false);
145 const IntervalType delete_interval{interval.start, interval.end}; 149 const IntervalType delete_interval{map->GetStart(), map->GetEnd()};
146 mapped_addresses.erase(delete_interval); 150 mapped_addresses.erase(delete_interval);
147 map_storage.erase(interval);
148 } 151 }
149 152
150private: 153private:
154 MapInterval CreateMap(const CacheAddr start, const CacheAddr end, const GPUVAddr gpu_addr) {
155 return std::make_shared<MapIntervalBase>(start, end, gpu_addr);
156 }
157
151 void MapAddress(const TBuffer& block, const GPUVAddr gpu_addr, const CacheAddr cache_addr, 158 void MapAddress(const TBuffer& block, const GPUVAddr gpu_addr, const CacheAddr cache_addr,
152 const std::size_t size) { 159 const std::size_t size) {
153 160
154 std::vector<MapInterval> overlaps = GetMapsInRange(cache_addr, size); 161 std::vector<MapInterval> overlaps = GetMapsInRange(cache_addr, size);
155 if (overlaps.empty()) { 162 if (overlaps.empty()) {
156 const CacheAddr cache_addr_end = cache_addr + size; 163 const CacheAddr cache_addr_end = cache_addr + size;
157 MapInterval new_interval{cache_addr, cache_addr_end}; 164 MapInterval new_map = CreateMap(cache_addr, cache_addr_end, gpu_addr);
158 u8* host_ptr = FromCacheAddr(cache_addr); 165 u8* host_ptr = FromCacheAddr(cache_addr);
159 UploadBlockData(block, block->GetOffset(cache_addr), size, host_ptr); 166 UploadBlockData(block, block->GetOffset(cache_addr), size, host_ptr);
160 Register(new_interval, gpu_addr); 167 Register(new_map);
161 return; 168 return;
162 } 169 }
163 170
164 const CacheAddr cache_addr_end = cache_addr + size; 171 const CacheAddr cache_addr_end = cache_addr + size;
165 if (overlaps.size() == 1) { 172 if (overlaps.size() == 1) {
166 const MapInterval& current_map = overlaps[0]; 173 const MapInterval& current_map = overlaps[0];
167 if (current_map.IsInside(cache_addr, cache_addr_end)) { 174 if (current_map->IsInside(cache_addr, cache_addr_end)) {
168 return; 175 return;
169 } 176 }
170 } 177 }
@@ -172,25 +179,25 @@ private:
172 CacheAddr new_end = cache_addr_end; 179 CacheAddr new_end = cache_addr_end;
173 // Calculate new buffer parameters 180 // Calculate new buffer parameters
174 for (auto& overlap : overlaps) { 181 for (auto& overlap : overlaps) {
175 new_start = std::min(overlap.start, new_start); 182 new_start = std::min(overlap->GetStart(), new_start);
176 new_end = std::max(overlap.end, new_end); 183 new_end = std::max(overlap->GetEnd(), new_end);
177 } 184 }
178 GPUVAddr new_gpu_addr = gpu_addr + new_start - cache_addr; 185 GPUVAddr new_gpu_addr = gpu_addr + new_start - cache_addr;
179 for (auto& overlap : overlaps) { 186 for (auto& overlap : overlaps) {
180 Unregister(overlap); 187 Unregister(overlap);
181 } 188 }
182 UpdateBlock(block, new_start, new_end, overlaps); 189 UpdateBlock(block, new_start, new_end, overlaps);
183 MapInterval new_interval{new_start, new_end}; 190 MapInterval new_map = CreateMap(new_start, new_end, new_gpu_addr);
184 Register(new_interval, new_gpu_addr); 191 Register(new_map);
185 } 192 }
186 193
187 void UpdateBlock(const TBuffer& block, CacheAddr start, CacheAddr end, 194 void UpdateBlock(const TBuffer& block, CacheAddr start, CacheAddr end,
188 std::vector<MapInterval>& overlaps) { 195 std::vector<MapInterval>& overlaps) {
189 const IntervalType base_interval{start, end}; 196 const IntervalType base_interval{start, end};
190 IntervalCache interval_set{}; 197 IntervalSet interval_set{};
191 interval_set.add(base_interval); 198 interval_set.add(base_interval);
192 for (auto& overlap : overlaps) { 199 for (auto& overlap : overlaps) {
193 const IntervalType subtract{overlap.start, overlap.end}; 200 const IntervalType subtract{overlap->GetStart(), overlap->GetEnd()};
194 interval_set.subtract(subtract); 201 interval_set.subtract(subtract);
195 } 202 }
196 for (auto& interval : interval_set) { 203 for (auto& interval : interval_set) {
@@ -210,7 +217,7 @@ private:
210 std::vector<MapInterval> objects{}; 217 std::vector<MapInterval> objects{};
211 const IntervalType interval{addr, addr + size}; 218 const IntervalType interval{addr, addr + size};
212 for (auto& pair : boost::make_iterator_range(mapped_addresses.equal_range(interval))) { 219 for (auto& pair : boost::make_iterator_range(mapped_addresses.equal_range(interval))) {
213 objects.emplace_back(pair.lower(), pair.upper()); 220 objects.push_back(pair.second);
214 } 221 }
215 222
216 return objects; 223 return objects;
@@ -322,10 +329,10 @@ private:
322 u64 buffer_offset = 0; 329 u64 buffer_offset = 0;
323 u64 buffer_offset_base = 0; 330 u64 buffer_offset_base = 0;
324 331
325 using IntervalCache = boost::icl::interval_set<CacheAddr>; 332 using IntervalSet = boost::icl::interval_set<CacheAddr>;
333 using IntervalCache = boost::icl::interval_map<CacheAddr, MapInterval>;
326 using IntervalType = typename IntervalCache::interval_type; 334 using IntervalType = typename IntervalCache::interval_type;
327 IntervalCache mapped_addresses{}; 335 IntervalCache mapped_addresses{};
328 std::unordered_map<MapInterval, MapInfo> map_storage;
329 336
330 static constexpr u64 block_page_bits{24}; 337 static constexpr u64 block_page_bits{24};
331 static constexpr u64 block_page_size{1 << block_page_bits}; 338 static constexpr u64 block_page_size{1 << block_page_bits};
diff --git a/src/video_core/buffer_cache/map_interval.h b/src/video_core/buffer_cache/map_interval.h
index c1cd52ca4..a01eddf49 100644
--- a/src/video_core/buffer_cache/map_interval.h
+++ b/src/video_core/buffer_cache/map_interval.h
@@ -4,45 +4,65 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <boost/functional/hash.hpp>
8#include "common/common_types.h" 7#include "common/common_types.h"
9#include "video_core/gpu.h" 8#include "video_core/gpu.h"
10 9
11namespace VideoCommon { 10namespace VideoCommon {
12 11
13struct MapInterval { 12class MapIntervalBase {
14 MapInterval(const CacheAddr start, const CacheAddr end) : start{start}, end{end} {} 13public:
15 CacheAddr start; 14 MapIntervalBase(const CacheAddr start, const CacheAddr end, const GPUVAddr gpu_addr)
16 CacheAddr end; 15 : start{start}, end{end}, gpu_addr{gpu_addr} {}
16
17 void SetCpuAddress(VAddr new_cpu_addr) {
18 cpu_addr = new_cpu_addr;
19 }
20
21 VAddr GetCpuAddress() const {
22 return cpu_addr;
23 }
24
25 GPUVAddr GetGpuAddress() const {
26 return gpu_addr;
27 }
28
17 bool IsInside(const CacheAddr other_start, const CacheAddr other_end) const { 29 bool IsInside(const CacheAddr other_start, const CacheAddr other_end) const {
18 return (start <= other_start && other_end <= end); 30 return (start <= other_start && other_end <= end);
19 } 31 }
20 32
21 bool operator==(const MapInterval& rhs) const { 33 bool operator==(const MapIntervalBase& rhs) const {
22 return std::tie(start, end) == std::tie(rhs.start, rhs.end); 34 return std::tie(start, end) == std::tie(rhs.start, rhs.end);
23 } 35 }
24 36
25 bool operator!=(const MapInterval& rhs) const { 37 bool operator!=(const MapIntervalBase& rhs) const {
26 return !operator==(rhs); 38 return !operator==(rhs);
27 } 39 }
28};
29 40
30struct MapInfo { 41 void MarkAsRegistered(const bool registered) {
31 GPUVAddr gpu_addr; 42 is_registered = registered;
32 VAddr cpu_addr; 43 }
33};
34 44
35} // namespace VideoCommon 45 bool IsRegistered() const {
46 return is_registered;
47 }
36 48
37namespace std { 49 CacheAddr GetStart() const {
50 return start;
51 }
38 52
39template <> 53 CacheAddr GetEnd() const {
40struct hash<VideoCommon::MapInterval> { 54 return end;
41 std::size_t operator()(const VideoCommon::MapInterval& k) const noexcept {
42 std::size_t a = std::hash<CacheAddr>()(k.start);
43 boost::hash_combine(a, std::hash<CacheAddr>()(k.end));
44 return a;
45 } 55 }
56
57private:
58 CacheAddr start;
59 CacheAddr end;
60 GPUVAddr gpu_addr;
61 VAddr cpu_addr{};
62 bool is_write{};
63 bool is_modified{};
64 bool is_registered{};
65 u64 ticks{};
46}; 66};
47 67
48} // namespace std 68} // namespace VideoCommon