BufferCache: Implement OnCPUWrite and SyncGuestHost

This commit is contained in:
Fernando Sahmkow 2020-02-16 10:08:07 -04:00
parent da8f17715d
commit 8b1eb44b3e
6 changed files with 67 additions and 7 deletions

View file

@ -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 Unmark(const MapInterval& map) {
void Unregister(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;
}; };

View file

@ -46,6 +46,22 @@ public:
return is_registered; return is_registered;
} }
void SetMemoryMarked(bool is_memory_marked_) {
is_memory_marked = is_memory_marked_;
}
bool IsMemoryMarked() const {
return is_memory_marked;
}
void SetSyncPending(bool is_sync_pending_) {
is_sync_pending = is_sync_pending_;
}
bool IsSyncPending() const {
return is_sync_pending;
}
VAddr GetStart() const { VAddr GetStart() const {
return start; return start;
} }
@ -83,6 +99,8 @@ private:
bool is_written{}; bool is_written{};
bool is_modified{}; bool is_modified{};
bool is_registered{}; bool is_registered{};
bool is_memory_marked{};
bool is_sync_pending{};
u64 ticks{}; u64 ticks{};
}; };

View file

@ -21,6 +21,7 @@ MICROPROFILE_DEFINE(DispatchCalls, "GPU", "Execute command buffer", MP_RGB(128,
void DmaPusher::DispatchCalls() { void DmaPusher::DispatchCalls() {
MICROPROFILE_SCOPE(DispatchCalls); MICROPROFILE_SCOPE(DispatchCalls);
gpu.SyncGuestHost();
// On entering GPU code, assume all memory may be touched by the ARM core. // On entering GPU code, assume all memory may be touched by the ARM core.
gpu.Maxwell3D().OnMemoryWrite(); gpu.Maxwell3D().OnMemoryWrite();

View file

@ -78,7 +78,7 @@ void ThreadManager::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
} }
void ThreadManager::FlushRegion(VAddr addr, u64 size) { void ThreadManager::FlushRegion(VAddr addr, u64 size) {
PushCommand(FlushRegionCommand(addr, size)); system.Renderer().Rasterizer().FlushRegion(addr, size);
} }
void ThreadManager::InvalidateRegion(VAddr addr, u64 size) { void ThreadManager::InvalidateRegion(VAddr addr, u64 size) {

View file

@ -667,13 +667,13 @@ void RasterizerOpenGL::OnCPUWrite(VAddr addr, u64 size) {
} }
texture_cache.OnCPUWrite(addr, size); texture_cache.OnCPUWrite(addr, size);
shader_cache.InvalidateRegion(addr, size); shader_cache.InvalidateRegion(addr, size);
buffer_cache.InvalidateRegion(addr, size); buffer_cache.OnCPUWrite(addr, size);
} }
void RasterizerOpenGL::SyncGuestHost() { void RasterizerOpenGL::SyncGuestHost() {
MICROPROFILE_SCOPE(OpenGL_CacheManagement); MICROPROFILE_SCOPE(OpenGL_CacheManagement);
texture_cache.SyncGuestHost(); texture_cache.SyncGuestHost();
// buffer_cache.SyncGuestHost(); buffer_cache.SyncGuestHost();
} }
void RasterizerOpenGL::FlushAndInvalidateRegion(VAddr addr, u64 size) { void RasterizerOpenGL::FlushAndInvalidateRegion(VAddr addr, u64 size) {

View file

@ -530,12 +530,12 @@ void RasterizerVulkan::OnCPUWrite(VAddr addr, u64 size) {
} }
texture_cache.OnCPUWrite(addr, size); texture_cache.OnCPUWrite(addr, size);
pipeline_cache.InvalidateRegion(addr, size); pipeline_cache.InvalidateRegion(addr, size);
buffer_cache.InvalidateRegion(addr, size); buffer_cache.OnCPUWrite(addr, size);
} }
void RasterizerVulkan::SyncGuestHost() { void RasterizerVulkan::SyncGuestHost() {
texture_cache.SyncGuestHost(); texture_cache.SyncGuestHost();
// buffer_cache.SyncGuestHost(); buffer_cache.SyncGuestHost();
} }
void RasterizerVulkan::FlushAndInvalidateRegion(VAddr addr, u64 size) { void RasterizerVulkan::FlushAndInvalidateRegion(VAddr addr, u64 size) {