BufferCache: Implement OnCPUWrite and SyncGuestHost
This commit is contained in:
		| @@ -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) { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user