BufferCache: Implement OnCPUWrite and SyncGuestHost
This commit is contained in:
parent
da8f17715d
commit
8b1eb44b3e
@ -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;
|
||||||
};
|
};
|
||||||
|
@ -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{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
@ -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) {
|
||||||
|
@ -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) {
|
||||||
|
Loading…
Reference in New Issue
Block a user