Просмотр исходного кода

Texture Cache: Implement OnCPUWrite and SyncGuestHost

Fernando Sahmkow 6 лет назад
Родитель
Сommit
a60a22d9c2
2 измененных файлов с 63 добавлено и 3 удалено
  1. 18 0
      src/video_core/texture_cache/surface_base.h
  2. 45 3
      src/video_core/texture_cache/texture_cache.h

+ 18 - 0
src/video_core/texture_cache/surface_base.h

@@ -192,6 +192,22 @@ public:
         index = index_;
         index = index_;
     }
     }
 
 
+    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;
+    }
+
     void MarkAsPicked(bool is_picked_) {
     void MarkAsPicked(bool is_picked_) {
         is_picked = is_picked_;
         is_picked = is_picked_;
     }
     }
@@ -303,6 +319,8 @@ private:
     bool is_target{};
     bool is_target{};
     bool is_registered{};
     bool is_registered{};
     bool is_picked{};
     bool is_picked{};
+    bool is_memory_marked{};
+    bool is_sync_pending{};
     u32 index{NO_RT};
     u32 index{NO_RT};
     u64 modification_tick{};
     u64 modification_tick{};
 };
 };

+ 45 - 3
src/video_core/texture_cache/texture_cache.h

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