Kaynağa Gözat

QueryCache: Implement Async Flushes.

Fernando Sahmkow 6 yıl önce
ebeveyn
işleme
0649f05900

+ 14 - 4
src/video_core/fence_manager.h

@@ -49,15 +49,17 @@ protected:
     bool is_stubbed;
 };
 
-template <typename TFence, typename TTextureCache, typename TTBufferCache>
+template <typename TFence, typename TTextureCache, typename TTBufferCache, typename TQueryCache>
 class FenceManager {
 public:
     void SignalSemaphore(GPUVAddr addr, u32 value) {
         TryReleasePendingFences();
         bool should_flush = texture_cache.HasUncommitedFlushes();
         should_flush |= buffer_cache.HasUncommitedFlushes();
+        should_flush |= query_cache.HasUncommitedFlushes();
         texture_cache.CommitAsyncFlushes();
         buffer_cache.CommitAsyncFlushes();
+        query_cache.CommitAsyncFlushes();
         TFence new_fence = CreateFence(addr, value, !should_flush);
         fences.push(new_fence);
         QueueFence(new_fence);
@@ -71,8 +73,10 @@ public:
         TryReleasePendingFences();
         bool should_flush = texture_cache.HasUncommitedFlushes();
         should_flush |= buffer_cache.HasUncommitedFlushes();
+        should_flush |= query_cache.HasUncommitedFlushes();
         texture_cache.CommitAsyncFlushes();
         buffer_cache.CommitAsyncFlushes();
+        query_cache.CommitAsyncFlushes();
         TFence new_fence = CreateFence(value, !should_flush);
         fences.push(new_fence);
         QueueFence(new_fence);
@@ -87,11 +91,13 @@ public:
             TFence& current_fence = fences.front();
             bool should_wait = texture_cache.ShouldWaitAsyncFlushes();
             should_wait |= buffer_cache.ShouldWaitAsyncFlushes();
+            should_wait |= query_cache.ShouldWaitAsyncFlushes();
             if (should_wait) {
                 WaitFence(current_fence);
             }
             texture_cache.PopAsyncFlushes();
             buffer_cache.PopAsyncFlushes();
+            query_cache.PopAsyncFlushes();
             auto& gpu{system.GPU()};
             if (current_fence->IsSemaphore()) {
                 auto& memory_manager{gpu.MemoryManager()};
@@ -105,9 +111,10 @@ public:
 
 protected:
     FenceManager(Core::System& system, VideoCore::RasterizerInterface& rasterizer,
-                 TTextureCache& texture_cache, TTBufferCache& buffer_cache)
-        : system{system}, rasterizer{rasterizer}, texture_cache{texture_cache}, buffer_cache{
-                                                                                    buffer_cache} {}
+                 TTextureCache& texture_cache, TTBufferCache& buffer_cache,
+                 TQueryCache& query_cache)
+        : system{system}, rasterizer{rasterizer}, texture_cache{texture_cache},
+          buffer_cache{buffer_cache}, query_cache{query_cache} {}
 
     virtual TFence CreateFence(u32 value, bool is_stubbed) = 0;
     virtual TFence CreateFence(GPUVAddr addr, u32 value, bool is_stubbed) = 0;
@@ -119,6 +126,7 @@ protected:
     VideoCore::RasterizerInterface& rasterizer;
     TTextureCache& texture_cache;
     TTBufferCache& buffer_cache;
+    TQueryCache& query_cache;
 
 private:
     void TryReleasePendingFences() {
@@ -126,11 +134,13 @@ private:
             TFence& current_fence = fences.front();
             bool should_wait = texture_cache.ShouldWaitAsyncFlushes();
             should_wait |= buffer_cache.ShouldWaitAsyncFlushes();
+            should_wait |= query_cache.ShouldWaitAsyncFlushes();
             if (should_wait && !IsFenceSignaled(current_fence)) {
                 return;
             }
             texture_cache.PopAsyncFlushes();
             buffer_cache.PopAsyncFlushes();
+            query_cache.PopAsyncFlushes();
             auto& gpu{system.GPU()};
             if (current_fence->IsSemaphore()) {
                 auto& memory_manager{gpu.MemoryManager()};

+ 50 - 0
src/video_core/query_cache.h

@@ -12,6 +12,7 @@
 #include <mutex>
 #include <optional>
 #include <unordered_map>
+#include <unordered_set>
 #include <vector>
 
 #include "common/assert.h"
@@ -130,6 +131,7 @@ public:
         }
 
         query->BindCounter(Stream(type).Current(), timestamp);
+        AsyncFlushQuery(cpu_addr);
     }
 
     /// Updates counters from GPU state. Expected to be called once per draw, clear or dispatch.
@@ -170,6 +172,44 @@ public:
         return streams[static_cast<std::size_t>(type)];
     }
 
+    void CommitAsyncFlushes() {
+        commited_flushes.push_back(uncommited_flushes);
+        uncommited_flushes.reset();
+    }
+
+    bool HasUncommitedFlushes() {
+        if (uncommited_flushes) {
+            return true;
+        }
+        return false;
+    }
+
+    bool ShouldWaitAsyncFlushes() {
+        if (commited_flushes.empty()) {
+            return false;
+        }
+        auto& flush_list = commited_flushes.front();
+        if (!flush_list) {
+            return false;
+        }
+        return true;
+    }
+
+    void PopAsyncFlushes() {
+        if (commited_flushes.empty()) {
+            return;
+        }
+        auto& flush_list = commited_flushes.front();
+        if (!flush_list) {
+            commited_flushes.pop_front();
+            return;
+        }
+        for (VAddr query_address : *flush_list) {
+            FlushAndRemoveRegion(query_address, 4);
+        }
+        commited_flushes.pop_front();
+    }
+
 protected:
     std::array<QueryPool, VideoCore::NumQueryTypes> query_pools;
 
@@ -224,6 +264,13 @@ private:
         return found != std::end(contents) ? &*found : nullptr;
     }
 
+    void AsyncFlushQuery(VAddr addr) {
+        if (!uncommited_flushes) {
+            uncommited_flushes = std::make_shared<std::unordered_set<VAddr>>();
+        }
+        uncommited_flushes->insert(addr);
+    }
+
     static constexpr std::uintptr_t PAGE_SIZE = 4096;
     static constexpr unsigned PAGE_SHIFT = 12;
 
@@ -235,6 +282,9 @@ private:
     std::unordered_map<u64, std::vector<CachedQuery>> cached_queries;
 
     std::array<CounterStream, VideoCore::NumQueryTypes> streams;
+
+    std::shared_ptr<std::unordered_set<VAddr>> uncommited_flushes{};
+    std::list<std::shared_ptr<std::unordered_set<VAddr>>> commited_flushes;
 };
 
 template <class QueryCache, class HostCounter>

+ 5 - 3
src/video_core/renderer_opengl/gl_fence_manager.cpp

@@ -44,9 +44,11 @@ void GLInnerFence::Wait() {
         ;
 }
 
-FenceManagerOpenGL::FenceManagerOpenGL(Core::System& system, VideoCore::RasterizerInterface& rasterizer,
-                               TextureCacheOpenGL& texture_cache, OGLBufferCache& buffer_cache)
-    : GenericFenceManager(system, rasterizer, texture_cache, buffer_cache) {}
+FenceManagerOpenGL::FenceManagerOpenGL(Core::System& system,
+                                       VideoCore::RasterizerInterface& rasterizer,
+                                       TextureCacheOpenGL& texture_cache,
+                                       OGLBufferCache& buffer_cache, QueryCache& query_cache)
+    : GenericFenceManager(system, rasterizer, texture_cache, buffer_cache, query_cache) {}
 
 Fence FenceManagerOpenGL::CreateFence(u32 value, bool is_stubbed) {
     return std::make_shared<GLInnerFence>(value, is_stubbed);

+ 5 - 2
src/video_core/renderer_opengl/gl_fence_manager.h

@@ -10,6 +10,7 @@
 #include "common/common_types.h"
 #include "video_core/fence_manager.h"
 #include "video_core/renderer_opengl/gl_buffer_cache.h"
+#include "video_core/renderer_opengl/gl_query_cache.h"
 #include "video_core/renderer_opengl/gl_resource_manager.h"
 #include "video_core/renderer_opengl/gl_texture_cache.h"
 
@@ -32,12 +33,14 @@ private:
 };
 
 using Fence = std::shared_ptr<GLInnerFence>;
-using GenericFenceManager = VideoCommon::FenceManager<Fence, TextureCacheOpenGL, OGLBufferCache>;
+using GenericFenceManager =
+    VideoCommon::FenceManager<Fence, TextureCacheOpenGL, OGLBufferCache, QueryCache>;
 
 class FenceManagerOpenGL final : public GenericFenceManager {
 public:
     FenceManagerOpenGL(Core::System& system, VideoCore::RasterizerInterface& rasterizer,
-                       TextureCacheOpenGL& texture_cache, OGLBufferCache& buffer_cache);
+                       TextureCacheOpenGL& texture_cache, OGLBufferCache& buffer_cache,
+                       QueryCache& query_cache);
 
 protected:
     Fence CreateFence(u32 value, bool is_stubbed) override;

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

@@ -101,9 +101,9 @@ RasterizerOpenGL::RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWind
     : RasterizerAccelerated{system.Memory()}, texture_cache{system, *this, device, state_tracker},
       shader_cache{*this, system, emu_window, device}, query_cache{system, *this}, system{system},
       screen_info{info}, program_manager{program_manager}, state_tracker{state_tracker},
-      buffer_cache{*this, system, device, STREAM_BUFFER_SIZE}, fence_manager{system, *this,
-                                                                             texture_cache,
-                                                                             buffer_cache} {
+      buffer_cache{*this, system, device, STREAM_BUFFER_SIZE}, fence_manager{
+                                                                   system, *this, texture_cache,
+                                                                   buffer_cache, query_cache} {
     CheckExtensions();
 }