|
|
@ -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();
|
|
|
|
Unmark(surface);
|
|
|
|
const VAddr cpu_addr = surface->GetCpuAddr();
|
|
|
|
if (surface->IsSyncPending()) {
|
|
|
|
rasterizer.UpdatePagesCachedCount(cpu_addr, size, -1);
|
|
|
|
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;
|
|
|
|
};
|
|
|
|
};
|
|
|
|