|
|
@ -6,6 +6,7 @@ |
|
|
|
|
|
|
|
|
#include <algorithm> |
|
|
#include <algorithm> |
|
|
#include <array> |
|
|
#include <array> |
|
|
|
|
|
#include <list> |
|
|
#include <memory> |
|
|
#include <memory> |
|
|
#include <mutex> |
|
|
#include <mutex> |
|
|
#include <set> |
|
|
#include <set> |
|
|
@ -62,6 +63,30 @@ public: |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void OnCPUWrite(CacheAddr addr, std::size_t size) { |
|
|
|
|
|
std::lock_guard lock{mutex}; |
|
|
|
|
|
|
|
|
|
|
|
for (const auto& surface : GetSurfacesInRegion(addr, size)) { |
|
|
|
|
|
if (surface->IsMemoryMarked()) { |
|
|
|
|
|
Unmark(surface); |
|
|
|
|
|
surface->SetSyncPending(true); |
|
|
|
|
|
marked_for_unregister.emplace_back(surface); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void SyncGuestHost() { |
|
|
|
|
|
std::lock_guard lock{mutex}; |
|
|
|
|
|
|
|
|
|
|
|
for (const auto& surface : marked_for_unregister) { |
|
|
|
|
|
if (surface->IsRegistered()) { |
|
|
|
|
|
surface->SetSyncPending(false); |
|
|
|
|
|
Unregister(surface); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
marked_for_unregister.clear(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Guarantees that rendertargets don't unregister themselves if the |
|
|
* Guarantees that rendertargets don't unregister themselves if the |
|
|
* collide. Protection is currently only done on 3D slices. |
|
|
* collide. Protection is currently only done on 3D slices. |
|
|
@ -85,7 +110,9 @@ public: |
|
|
return a->GetModificationTick() < b->GetModificationTick(); |
|
|
return a->GetModificationTick() < b->GetModificationTick(); |
|
|
}); |
|
|
}); |
|
|
for (const auto& surface : surfaces) { |
|
|
for (const auto& surface : surfaces) { |
|
|
|
|
|
mutex.unlock(); |
|
|
FlushSurface(surface); |
|
|
FlushSurface(surface); |
|
|
|
|
|
mutex.lock(); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -345,9 +372,20 @@ protected: |
|
|
surface->SetCpuAddr(*cpu_addr); |
|
|
surface->SetCpuAddr(*cpu_addr); |
|
|
RegisterInnerCache(surface); |
|
|
RegisterInnerCache(surface); |
|
|
surface->MarkAsRegistered(true); |
|
|
surface->MarkAsRegistered(true); |
|
|
|
|
|
surface->SetMemoryMarked(true); |
|
|
rasterizer.UpdatePagesCachedCount(*cpu_addr, size, 1); |
|
|
rasterizer.UpdatePagesCachedCount(*cpu_addr, size, 1); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void Unmark(TSurface surface) { |
|
|
|
|
|
if (!surface->IsMemoryMarked()) { |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
const std::size_t size = surface->GetSizeInBytes(); |
|
|
|
|
|
const VAddr cpu_addr = surface->GetCpuAddr(); |
|
|
|
|
|
rasterizer.UpdatePagesCachedCount(cpu_addr, size, -1); |
|
|
|
|
|
surface->SetMemoryMarked(false); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
void Unregister(TSurface surface) { |
|
|
void Unregister(TSurface surface) { |
|
|
if (guard_render_targets && surface->IsProtected()) { |
|
|
if (guard_render_targets && surface->IsProtected()) { |
|
|
return; |
|
|
return; |
|
|
@ -355,9 +393,11 @@ protected: |
|
|
if (!guard_render_targets && surface->IsRenderTarget()) { |
|
|
if (!guard_render_targets && surface->IsRenderTarget()) { |
|
|
ManageRenderTargetUnregister(surface); |
|
|
ManageRenderTargetUnregister(surface); |
|
|
} |
|
|
} |
|
|
const std::size_t size = surface->GetSizeInBytes(); |
|
|
|
|
|
const VAddr cpu_addr = surface->GetCpuAddr(); |
|
|
|
|
|
rasterizer.UpdatePagesCachedCount(cpu_addr, size, -1); |
|
|
|
|
|
|
|
|
Unmark(surface); |
|
|
|
|
|
if (surface->IsSyncPending()) { |
|
|
|
|
|
marked_for_unregister.remove(surface); |
|
|
|
|
|
surface->SetSyncPending(false); |
|
|
|
|
|
} |
|
|
UnregisterInnerCache(surface); |
|
|
UnregisterInnerCache(surface); |
|
|
surface->MarkAsRegistered(false); |
|
|
surface->MarkAsRegistered(false); |
|
|
ReserveSurface(surface->GetSurfaceParams(), surface); |
|
|
ReserveSurface(surface->GetSurfaceParams(), surface); |
|
|
@ -1150,6 +1190,8 @@ private: |
|
|
std::unordered_map<u32, TSurface> invalid_cache; |
|
|
std::unordered_map<u32, TSurface> invalid_cache; |
|
|
std::vector<u8> invalid_memory; |
|
|
std::vector<u8> invalid_memory; |
|
|
|
|
|
|
|
|
|
|
|
std::list<TSurface> marked_for_unregister; |
|
|
|
|
|
|
|
|
StagingCache staging_cache; |
|
|
StagingCache staging_cache; |
|
|
std::recursive_mutex mutex; |
|
|
std::recursive_mutex mutex; |
|
|
}; |
|
|
}; |
|
|
|