|
|
|
@ -5,6 +5,7 @@ |
|
|
|
#pragma once |
|
|
|
|
|
|
|
#include <array> |
|
|
|
#include <list> |
|
|
|
#include <memory> |
|
|
|
#include <mutex> |
|
|
|
#include <unordered_map> |
|
|
|
@ -137,7 +138,9 @@ public: |
|
|
|
}); |
|
|
|
for (auto& object : objects) { |
|
|
|
if (object->IsModified() && object->IsRegistered()) { |
|
|
|
mutex.unlock(); |
|
|
|
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; |
|
|
|
|
|
|
|
protected: |
|
|
|
@ -196,17 +223,30 @@ protected: |
|
|
|
const IntervalType interval{new_map->GetStart(), new_map->GetEnd()}; |
|
|
|
mapped_addresses.insert({interval, new_map}); |
|
|
|
rasterizer.UpdatePagesCachedCount(cpu_addr, size, 1); |
|
|
|
new_map->SetMemoryMarked(true); |
|
|
|
if (inherit_written) { |
|
|
|
MarkRegionAsWritten(new_map->GetStart(), new_map->GetEnd() - 1); |
|
|
|
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(); |
|
|
|
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); |
|
|
|
if (map->IsSyncPending()) { |
|
|
|
marked_for_unregister.remove(map); |
|
|
|
map->SetSyncPending(false); |
|
|
|
} |
|
|
|
if (map->IsWritten()) { |
|
|
|
UnmarkRegionAsWritten(map->GetStart(), map->GetEnd() - 1); |
|
|
|
} |
|
|
|
@ -479,6 +519,7 @@ private: |
|
|
|
u64 modified_ticks = 0; |
|
|
|
|
|
|
|
std::vector<u8> staging_buffer; |
|
|
|
std::list<MapInterval> marked_for_unregister; |
|
|
|
|
|
|
|
std::recursive_mutex mutex; |
|
|
|
}; |
|
|
|
|