diff options
Diffstat (limited to 'src/video_core/buffer_cache')
| -rw-r--r-- | src/video_core/buffer_cache/buffer_cache.h | 45 | ||||
| -rw-r--r-- | src/video_core/buffer_cache/map_interval.h | 18 |
2 files changed, 61 insertions, 2 deletions
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 83e7a1cde..5b14d52e2 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include <list> | ||
| 8 | #include <memory> | 9 | #include <memory> |
| 9 | #include <mutex> | 10 | #include <mutex> |
| 10 | #include <unordered_map> | 11 | #include <unordered_map> |
| @@ -137,7 +138,9 @@ public: | |||
| 137 | }); | 138 | }); |
| 138 | for (auto& object : objects) { | 139 | for (auto& object : objects) { |
| 139 | if (object->IsModified() && object->IsRegistered()) { | 140 | if (object->IsModified() && object->IsRegistered()) { |
| 141 | mutex.unlock(); | ||
| 140 | FlushMap(object); | 142 | FlushMap(object); |
| 143 | mutex.lock(); | ||
| 141 | } | 144 | } |
| 142 | } | 145 | } |
| 143 | } | 146 | } |
| @@ -154,6 +157,30 @@ public: | |||
| 154 | } | 157 | } |
| 155 | } | 158 | } |
| 156 | 159 | ||
| 160 | void OnCPUWrite(VAddr addr, std::size_t size) { | ||
| 161 | std::lock_guard lock{mutex}; | ||
| 162 | |||
| 163 | for (const auto& object : GetMapsInRange(addr, size)) { | ||
| 164 | if (object->IsMemoryMarked() && object->IsRegistered()) { | ||
| 165 | Unmark(object); | ||
| 166 | object->SetSyncPending(true); | ||
| 167 | marked_for_unregister.emplace_back(object); | ||
| 168 | } | ||
| 169 | } | ||
| 170 | } | ||
| 171 | |||
| 172 | void SyncGuestHost() { | ||
| 173 | std::lock_guard lock{mutex}; | ||
| 174 | |||
| 175 | for (const auto& object : marked_for_unregister) { | ||
| 176 | if (object->IsRegistered()) { | ||
| 177 | object->SetSyncPending(false); | ||
| 178 | Unregister(object); | ||
| 179 | } | ||
| 180 | } | ||
| 181 | marked_for_unregister.clear(); | ||
| 182 | } | ||
| 183 | |||
| 157 | virtual BufferType GetEmptyBuffer(std::size_t size) = 0; | 184 | virtual BufferType GetEmptyBuffer(std::size_t size) = 0; |
| 158 | 185 | ||
| 159 | protected: | 186 | protected: |
| @@ -196,17 +223,30 @@ protected: | |||
| 196 | const IntervalType interval{new_map->GetStart(), new_map->GetEnd()}; | 223 | const IntervalType interval{new_map->GetStart(), new_map->GetEnd()}; |
| 197 | mapped_addresses.insert({interval, new_map}); | 224 | mapped_addresses.insert({interval, new_map}); |
| 198 | rasterizer.UpdatePagesCachedCount(cpu_addr, size, 1); | 225 | rasterizer.UpdatePagesCachedCount(cpu_addr, size, 1); |
| 226 | new_map->SetMemoryMarked(true); | ||
| 199 | if (inherit_written) { | 227 | if (inherit_written) { |
| 200 | MarkRegionAsWritten(new_map->GetStart(), new_map->GetEnd() - 1); | 228 | MarkRegionAsWritten(new_map->GetStart(), new_map->GetEnd() - 1); |
| 201 | new_map->MarkAsWritten(true); | 229 | new_map->MarkAsWritten(true); |
| 202 | } | 230 | } |
| 203 | } | 231 | } |
| 204 | 232 | ||
| 205 | /// Unregisters an object from the cache | 233 | void Unmark(const MapInterval& map) { |
| 206 | void Unregister(MapInterval& map) { | 234 | if (!map->IsMemoryMarked()) { |
| 235 | return; | ||
| 236 | } | ||
| 207 | const std::size_t size = map->GetEnd() - map->GetStart(); | 237 | const std::size_t size = map->GetEnd() - map->GetStart(); |
| 208 | rasterizer.UpdatePagesCachedCount(map->GetStart(), size, -1); | 238 | rasterizer.UpdatePagesCachedCount(map->GetStart(), size, -1); |
| 239 | map->SetMemoryMarked(false); | ||
| 240 | } | ||
| 241 | |||
| 242 | /// Unregisters an object from the cache | ||
| 243 | void Unregister(const MapInterval& map) { | ||
| 244 | Unmark(map); | ||
| 209 | map->MarkAsRegistered(false); | 245 | map->MarkAsRegistered(false); |
| 246 | if (map->IsSyncPending()) { | ||
| 247 | marked_for_unregister.remove(map); | ||
| 248 | map->SetSyncPending(false); | ||
| 249 | } | ||
| 210 | if (map->IsWritten()) { | 250 | if (map->IsWritten()) { |
| 211 | UnmarkRegionAsWritten(map->GetStart(), map->GetEnd() - 1); | 251 | UnmarkRegionAsWritten(map->GetStart(), map->GetEnd() - 1); |
| 212 | } | 252 | } |
| @@ -479,6 +519,7 @@ private: | |||
| 479 | u64 modified_ticks = 0; | 519 | u64 modified_ticks = 0; |
| 480 | 520 | ||
| 481 | std::vector<u8> staging_buffer; | 521 | std::vector<u8> staging_buffer; |
| 522 | std::list<MapInterval> marked_for_unregister; | ||
| 482 | 523 | ||
| 483 | std::recursive_mutex mutex; | 524 | std::recursive_mutex mutex; |
| 484 | }; | 525 | }; |
diff --git a/src/video_core/buffer_cache/map_interval.h b/src/video_core/buffer_cache/map_interval.h index b0956029d..29d8b26f3 100644 --- a/src/video_core/buffer_cache/map_interval.h +++ b/src/video_core/buffer_cache/map_interval.h | |||
| @@ -46,6 +46,22 @@ public: | |||
| 46 | return is_registered; | 46 | return is_registered; |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | void SetMemoryMarked(bool is_memory_marked_) { | ||
| 50 | is_memory_marked = is_memory_marked_; | ||
| 51 | } | ||
| 52 | |||
| 53 | bool IsMemoryMarked() const { | ||
| 54 | return is_memory_marked; | ||
| 55 | } | ||
| 56 | |||
| 57 | void SetSyncPending(bool is_sync_pending_) { | ||
| 58 | is_sync_pending = is_sync_pending_; | ||
| 59 | } | ||
| 60 | |||
| 61 | bool IsSyncPending() const { | ||
| 62 | return is_sync_pending; | ||
| 63 | } | ||
| 64 | |||
| 49 | VAddr GetStart() const { | 65 | VAddr GetStart() const { |
| 50 | return start; | 66 | return start; |
| 51 | } | 67 | } |
| @@ -83,6 +99,8 @@ private: | |||
| 83 | bool is_written{}; | 99 | bool is_written{}; |
| 84 | bool is_modified{}; | 100 | bool is_modified{}; |
| 85 | bool is_registered{}; | 101 | bool is_registered{}; |
| 102 | bool is_memory_marked{}; | ||
| 103 | bool is_sync_pending{}; | ||
| 86 | u64 ticks{}; | 104 | u64 ticks{}; |
| 87 | }; | 105 | }; |
| 88 | 106 | ||