|
@@ -5,6 +5,7 @@
|
|
|
#pragma once
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <array>
|
|
#include <array>
|
|
|
|
|
+#include <list>
|
|
|
#include <memory>
|
|
#include <memory>
|
|
|
#include <mutex>
|
|
#include <mutex>
|
|
|
#include <unordered_map>
|
|
#include <unordered_map>
|
|
@@ -137,7 +138,9 @@ public:
|
|
|
});
|
|
});
|
|
|
for (auto& object : objects) {
|
|
for (auto& object : objects) {
|
|
|
if (object->IsModified() && object->IsRegistered()) {
|
|
if (object->IsModified() && object->IsRegistered()) {
|
|
|
|
|
+ mutex.unlock();
|
|
|
FlushMap(object);
|
|
FlushMap(object);
|
|
|
|
|
+ mutex.lock();
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -154,6 +157,30 @@ public:
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ void OnCPUWrite(VAddr addr, std::size_t size) {
|
|
|
|
|
+ std::lock_guard lock{mutex};
|
|
|
|
|
+
|
|
|
|
|
+ for (const auto& object : GetMapsInRange(addr, size)) {
|
|
|
|
|
+ if (object->IsMemoryMarked() && object->IsRegistered()) {
|
|
|
|
|
+ Unmark(object);
|
|
|
|
|
+ object->SetSyncPending(true);
|
|
|
|
|
+ marked_for_unregister.emplace_back(object);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void SyncGuestHost() {
|
|
|
|
|
+ std::lock_guard lock{mutex};
|
|
|
|
|
+
|
|
|
|
|
+ for (const auto& object : marked_for_unregister) {
|
|
|
|
|
+ if (object->IsRegistered()) {
|
|
|
|
|
+ object->SetSyncPending(false);
|
|
|
|
|
+ Unregister(object);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ marked_for_unregister.clear();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
virtual BufferType GetEmptyBuffer(std::size_t size) = 0;
|
|
virtual BufferType GetEmptyBuffer(std::size_t size) = 0;
|
|
|
|
|
|
|
|
protected:
|
|
protected:
|
|
@@ -196,17 +223,30 @@ protected:
|
|
|
const IntervalType interval{new_map->GetStart(), new_map->GetEnd()};
|
|
const IntervalType interval{new_map->GetStart(), new_map->GetEnd()};
|
|
|
mapped_addresses.insert({interval, new_map});
|
|
mapped_addresses.insert({interval, new_map});
|
|
|
rasterizer.UpdatePagesCachedCount(cpu_addr, size, 1);
|
|
rasterizer.UpdatePagesCachedCount(cpu_addr, size, 1);
|
|
|
|
|
+ new_map->SetMemoryMarked(true);
|
|
|
if (inherit_written) {
|
|
if (inherit_written) {
|
|
|
MarkRegionAsWritten(new_map->GetStart(), new_map->GetEnd() - 1);
|
|
MarkRegionAsWritten(new_map->GetStart(), new_map->GetEnd() - 1);
|
|
|
new_map->MarkAsWritten(true);
|
|
new_map->MarkAsWritten(true);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /// Unregisters an object from the cache
|
|
|
|
|
- void Unregister(MapInterval& map) {
|
|
|
|
|
|
|
+ void Unmark(const MapInterval& map) {
|
|
|
|
|
+ if (!map->IsMemoryMarked()) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
const std::size_t size = map->GetEnd() - map->GetStart();
|
|
const std::size_t size = map->GetEnd() - map->GetStart();
|
|
|
rasterizer.UpdatePagesCachedCount(map->GetStart(), size, -1);
|
|
rasterizer.UpdatePagesCachedCount(map->GetStart(), size, -1);
|
|
|
|
|
+ map->SetMemoryMarked(false);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /// Unregisters an object from the cache
|
|
|
|
|
+ void Unregister(const MapInterval& map) {
|
|
|
|
|
+ Unmark(map);
|
|
|
map->MarkAsRegistered(false);
|
|
map->MarkAsRegistered(false);
|
|
|
|
|
+ if (map->IsSyncPending()) {
|
|
|
|
|
+ marked_for_unregister.remove(map);
|
|
|
|
|
+ map->SetSyncPending(false);
|
|
|
|
|
+ }
|
|
|
if (map->IsWritten()) {
|
|
if (map->IsWritten()) {
|
|
|
UnmarkRegionAsWritten(map->GetStart(), map->GetEnd() - 1);
|
|
UnmarkRegionAsWritten(map->GetStart(), map->GetEnd() - 1);
|
|
|
}
|
|
}
|
|
@@ -479,6 +519,7 @@ private:
|
|
|
u64 modified_ticks = 0;
|
|
u64 modified_ticks = 0;
|
|
|
|
|
|
|
|
std::vector<u8> staging_buffer;
|
|
std::vector<u8> staging_buffer;
|
|
|
|
|
+ std::list<MapInterval> marked_for_unregister;
|
|
|
|
|
|
|
|
std::recursive_mutex mutex;
|
|
std::recursive_mutex mutex;
|
|
|
};
|
|
};
|