From 0649f0590047e8cc0b16a10dec5eb74938fef718 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Wed, 15 Apr 2020 16:36:14 -0400 Subject: QueryCache: Implement Async Flushes. --- src/video_core/fence_manager.h | 18 ++++++-- src/video_core/query_cache.h | 50 ++++++++++++++++++++++ .../renderer_opengl/gl_fence_manager.cpp | 8 ++-- src/video_core/renderer_opengl/gl_fence_manager.h | 7 ++- src/video_core/renderer_opengl/gl_rasterizer.cpp | 6 +-- 5 files changed, 77 insertions(+), 12 deletions(-) (limited to 'src/video_core') diff --git a/src/video_core/fence_manager.h b/src/video_core/fence_manager.h index 417cb113f..99a138b5b 100644 --- a/src/video_core/fence_manager.h +++ b/src/video_core/fence_manager.h @@ -49,15 +49,17 @@ protected: bool is_stubbed; }; -template +template 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()}; diff --git a/src/video_core/query_cache.h b/src/video_core/query_cache.h index 5ea2b01f2..1b1c23995 100644 --- a/src/video_core/query_cache.h +++ b/src/video_core/query_cache.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #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(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 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>(); + } + 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> cached_queries; std::array streams; + + std::shared_ptr> uncommited_flushes{}; + std::list>> commited_flushes; }; template diff --git a/src/video_core/renderer_opengl/gl_fence_manager.cpp b/src/video_core/renderer_opengl/gl_fence_manager.cpp index 579c03a1e..aa57a0ae0 100644 --- a/src/video_core/renderer_opengl/gl_fence_manager.cpp +++ b/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(value, is_stubbed); diff --git a/src/video_core/renderer_opengl/gl_fence_manager.h b/src/video_core/renderer_opengl/gl_fence_manager.h index ba48d2f84..c76e69cb8 100644 --- a/src/video_core/renderer_opengl/gl_fence_manager.h +++ b/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; -using GenericFenceManager = VideoCommon::FenceManager; +using GenericFenceManager = + VideoCommon::FenceManager; 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; diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index bc57d396e..6d3b5f3f4 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/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(); } -- cgit v1.2.3