Parcourir la source

BufferCache: Implement OnCPUWrite and SyncGuestHost

Fernando Sahmkow il y a 6 ans
Parent
commit
8b1eb44b3e

+ 43 - 2
src/video_core/buffer_cache/buffer_cache.h

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

+ 18 - 0
src/video_core/buffer_cache/map_interval.h

@@ -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{};
 };
 };
 
 

+ 1 - 0
src/video_core/dma_pusher.cpp

@@ -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();
 
 

+ 1 - 1
src/video_core/gpu_thread.cpp

@@ -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) {

+ 2 - 2
src/video_core/renderer_opengl/gl_rasterizer.cpp

@@ -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) {

+ 2 - 2
src/video_core/renderer_vulkan/vk_rasterizer.cpp

@@ -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) {