diff options
| -rw-r--r-- | src/video_core/fence_manager.h | 18 | ||||
| -rw-r--r-- | src/video_core/query_cache.h | 50 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_fence_manager.cpp | 8 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_fence_manager.h | 7 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 6 |
5 files changed, 77 insertions, 12 deletions
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: | |||
| 49 | bool is_stubbed; | 49 | bool is_stubbed; |
| 50 | }; | 50 | }; |
| 51 | 51 | ||
| 52 | template <typename TFence, typename TTextureCache, typename TTBufferCache> | 52 | template <typename TFence, typename TTextureCache, typename TTBufferCache, typename TQueryCache> |
| 53 | class FenceManager { | 53 | class FenceManager { |
| 54 | public: | 54 | public: |
| 55 | void SignalSemaphore(GPUVAddr addr, u32 value) { | 55 | void SignalSemaphore(GPUVAddr addr, u32 value) { |
| 56 | TryReleasePendingFences(); | 56 | TryReleasePendingFences(); |
| 57 | bool should_flush = texture_cache.HasUncommitedFlushes(); | 57 | bool should_flush = texture_cache.HasUncommitedFlushes(); |
| 58 | should_flush |= buffer_cache.HasUncommitedFlushes(); | 58 | should_flush |= buffer_cache.HasUncommitedFlushes(); |
| 59 | should_flush |= query_cache.HasUncommitedFlushes(); | ||
| 59 | texture_cache.CommitAsyncFlushes(); | 60 | texture_cache.CommitAsyncFlushes(); |
| 60 | buffer_cache.CommitAsyncFlushes(); | 61 | buffer_cache.CommitAsyncFlushes(); |
| 62 | query_cache.CommitAsyncFlushes(); | ||
| 61 | TFence new_fence = CreateFence(addr, value, !should_flush); | 63 | TFence new_fence = CreateFence(addr, value, !should_flush); |
| 62 | fences.push(new_fence); | 64 | fences.push(new_fence); |
| 63 | QueueFence(new_fence); | 65 | QueueFence(new_fence); |
| @@ -71,8 +73,10 @@ public: | |||
| 71 | TryReleasePendingFences(); | 73 | TryReleasePendingFences(); |
| 72 | bool should_flush = texture_cache.HasUncommitedFlushes(); | 74 | bool should_flush = texture_cache.HasUncommitedFlushes(); |
| 73 | should_flush |= buffer_cache.HasUncommitedFlushes(); | 75 | should_flush |= buffer_cache.HasUncommitedFlushes(); |
| 76 | should_flush |= query_cache.HasUncommitedFlushes(); | ||
| 74 | texture_cache.CommitAsyncFlushes(); | 77 | texture_cache.CommitAsyncFlushes(); |
| 75 | buffer_cache.CommitAsyncFlushes(); | 78 | buffer_cache.CommitAsyncFlushes(); |
| 79 | query_cache.CommitAsyncFlushes(); | ||
| 76 | TFence new_fence = CreateFence(value, !should_flush); | 80 | TFence new_fence = CreateFence(value, !should_flush); |
| 77 | fences.push(new_fence); | 81 | fences.push(new_fence); |
| 78 | QueueFence(new_fence); | 82 | QueueFence(new_fence); |
| @@ -87,11 +91,13 @@ public: | |||
| 87 | TFence& current_fence = fences.front(); | 91 | TFence& current_fence = fences.front(); |
| 88 | bool should_wait = texture_cache.ShouldWaitAsyncFlushes(); | 92 | bool should_wait = texture_cache.ShouldWaitAsyncFlushes(); |
| 89 | should_wait |= buffer_cache.ShouldWaitAsyncFlushes(); | 93 | should_wait |= buffer_cache.ShouldWaitAsyncFlushes(); |
| 94 | should_wait |= query_cache.ShouldWaitAsyncFlushes(); | ||
| 90 | if (should_wait) { | 95 | if (should_wait) { |
| 91 | WaitFence(current_fence); | 96 | WaitFence(current_fence); |
| 92 | } | 97 | } |
| 93 | texture_cache.PopAsyncFlushes(); | 98 | texture_cache.PopAsyncFlushes(); |
| 94 | buffer_cache.PopAsyncFlushes(); | 99 | buffer_cache.PopAsyncFlushes(); |
| 100 | query_cache.PopAsyncFlushes(); | ||
| 95 | auto& gpu{system.GPU()}; | 101 | auto& gpu{system.GPU()}; |
| 96 | if (current_fence->IsSemaphore()) { | 102 | if (current_fence->IsSemaphore()) { |
| 97 | auto& memory_manager{gpu.MemoryManager()}; | 103 | auto& memory_manager{gpu.MemoryManager()}; |
| @@ -105,9 +111,10 @@ public: | |||
| 105 | 111 | ||
| 106 | protected: | 112 | protected: |
| 107 | FenceManager(Core::System& system, VideoCore::RasterizerInterface& rasterizer, | 113 | FenceManager(Core::System& system, VideoCore::RasterizerInterface& rasterizer, |
| 108 | TTextureCache& texture_cache, TTBufferCache& buffer_cache) | 114 | TTextureCache& texture_cache, TTBufferCache& buffer_cache, |
| 109 | : system{system}, rasterizer{rasterizer}, texture_cache{texture_cache}, buffer_cache{ | 115 | TQueryCache& query_cache) |
| 110 | buffer_cache} {} | 116 | : system{system}, rasterizer{rasterizer}, texture_cache{texture_cache}, |
| 117 | buffer_cache{buffer_cache}, query_cache{query_cache} {} | ||
| 111 | 118 | ||
| 112 | virtual TFence CreateFence(u32 value, bool is_stubbed) = 0; | 119 | virtual TFence CreateFence(u32 value, bool is_stubbed) = 0; |
| 113 | virtual TFence CreateFence(GPUVAddr addr, u32 value, bool is_stubbed) = 0; | 120 | virtual TFence CreateFence(GPUVAddr addr, u32 value, bool is_stubbed) = 0; |
| @@ -119,6 +126,7 @@ protected: | |||
| 119 | VideoCore::RasterizerInterface& rasterizer; | 126 | VideoCore::RasterizerInterface& rasterizer; |
| 120 | TTextureCache& texture_cache; | 127 | TTextureCache& texture_cache; |
| 121 | TTBufferCache& buffer_cache; | 128 | TTBufferCache& buffer_cache; |
| 129 | TQueryCache& query_cache; | ||
| 122 | 130 | ||
| 123 | private: | 131 | private: |
| 124 | void TryReleasePendingFences() { | 132 | void TryReleasePendingFences() { |
| @@ -126,11 +134,13 @@ private: | |||
| 126 | TFence& current_fence = fences.front(); | 134 | TFence& current_fence = fences.front(); |
| 127 | bool should_wait = texture_cache.ShouldWaitAsyncFlushes(); | 135 | bool should_wait = texture_cache.ShouldWaitAsyncFlushes(); |
| 128 | should_wait |= buffer_cache.ShouldWaitAsyncFlushes(); | 136 | should_wait |= buffer_cache.ShouldWaitAsyncFlushes(); |
| 137 | should_wait |= query_cache.ShouldWaitAsyncFlushes(); | ||
| 129 | if (should_wait && !IsFenceSignaled(current_fence)) { | 138 | if (should_wait && !IsFenceSignaled(current_fence)) { |
| 130 | return; | 139 | return; |
| 131 | } | 140 | } |
| 132 | texture_cache.PopAsyncFlushes(); | 141 | texture_cache.PopAsyncFlushes(); |
| 133 | buffer_cache.PopAsyncFlushes(); | 142 | buffer_cache.PopAsyncFlushes(); |
| 143 | query_cache.PopAsyncFlushes(); | ||
| 134 | auto& gpu{system.GPU()}; | 144 | auto& gpu{system.GPU()}; |
| 135 | if (current_fence->IsSemaphore()) { | 145 | if (current_fence->IsSemaphore()) { |
| 136 | auto& memory_manager{gpu.MemoryManager()}; | 146 | 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 @@ | |||
| 12 | #include <mutex> | 12 | #include <mutex> |
| 13 | #include <optional> | 13 | #include <optional> |
| 14 | #include <unordered_map> | 14 | #include <unordered_map> |
| 15 | #include <unordered_set> | ||
| 15 | #include <vector> | 16 | #include <vector> |
| 16 | 17 | ||
| 17 | #include "common/assert.h" | 18 | #include "common/assert.h" |
| @@ -130,6 +131,7 @@ public: | |||
| 130 | } | 131 | } |
| 131 | 132 | ||
| 132 | query->BindCounter(Stream(type).Current(), timestamp); | 133 | query->BindCounter(Stream(type).Current(), timestamp); |
| 134 | AsyncFlushQuery(cpu_addr); | ||
| 133 | } | 135 | } |
| 134 | 136 | ||
| 135 | /// Updates counters from GPU state. Expected to be called once per draw, clear or dispatch. | 137 | /// Updates counters from GPU state. Expected to be called once per draw, clear or dispatch. |
| @@ -170,6 +172,44 @@ public: | |||
| 170 | return streams[static_cast<std::size_t>(type)]; | 172 | return streams[static_cast<std::size_t>(type)]; |
| 171 | } | 173 | } |
| 172 | 174 | ||
| 175 | void CommitAsyncFlushes() { | ||
| 176 | commited_flushes.push_back(uncommited_flushes); | ||
| 177 | uncommited_flushes.reset(); | ||
| 178 | } | ||
| 179 | |||
| 180 | bool HasUncommitedFlushes() { | ||
| 181 | if (uncommited_flushes) { | ||
| 182 | return true; | ||
| 183 | } | ||
| 184 | return false; | ||
| 185 | } | ||
| 186 | |||
| 187 | bool ShouldWaitAsyncFlushes() { | ||
| 188 | if (commited_flushes.empty()) { | ||
| 189 | return false; | ||
| 190 | } | ||
| 191 | auto& flush_list = commited_flushes.front(); | ||
| 192 | if (!flush_list) { | ||
| 193 | return false; | ||
| 194 | } | ||
| 195 | return true; | ||
| 196 | } | ||
| 197 | |||
| 198 | void PopAsyncFlushes() { | ||
| 199 | if (commited_flushes.empty()) { | ||
| 200 | return; | ||
| 201 | } | ||
| 202 | auto& flush_list = commited_flushes.front(); | ||
| 203 | if (!flush_list) { | ||
| 204 | commited_flushes.pop_front(); | ||
| 205 | return; | ||
| 206 | } | ||
| 207 | for (VAddr query_address : *flush_list) { | ||
| 208 | FlushAndRemoveRegion(query_address, 4); | ||
| 209 | } | ||
| 210 | commited_flushes.pop_front(); | ||
| 211 | } | ||
| 212 | |||
| 173 | protected: | 213 | protected: |
| 174 | std::array<QueryPool, VideoCore::NumQueryTypes> query_pools; | 214 | std::array<QueryPool, VideoCore::NumQueryTypes> query_pools; |
| 175 | 215 | ||
| @@ -224,6 +264,13 @@ private: | |||
| 224 | return found != std::end(contents) ? &*found : nullptr; | 264 | return found != std::end(contents) ? &*found : nullptr; |
| 225 | } | 265 | } |
| 226 | 266 | ||
| 267 | void AsyncFlushQuery(VAddr addr) { | ||
| 268 | if (!uncommited_flushes) { | ||
| 269 | uncommited_flushes = std::make_shared<std::unordered_set<VAddr>>(); | ||
| 270 | } | ||
| 271 | uncommited_flushes->insert(addr); | ||
| 272 | } | ||
| 273 | |||
| 227 | static constexpr std::uintptr_t PAGE_SIZE = 4096; | 274 | static constexpr std::uintptr_t PAGE_SIZE = 4096; |
| 228 | static constexpr unsigned PAGE_SHIFT = 12; | 275 | static constexpr unsigned PAGE_SHIFT = 12; |
| 229 | 276 | ||
| @@ -235,6 +282,9 @@ private: | |||
| 235 | std::unordered_map<u64, std::vector<CachedQuery>> cached_queries; | 282 | std::unordered_map<u64, std::vector<CachedQuery>> cached_queries; |
| 236 | 283 | ||
| 237 | std::array<CounterStream, VideoCore::NumQueryTypes> streams; | 284 | std::array<CounterStream, VideoCore::NumQueryTypes> streams; |
| 285 | |||
| 286 | std::shared_ptr<std::unordered_set<VAddr>> uncommited_flushes{}; | ||
| 287 | std::list<std::shared_ptr<std::unordered_set<VAddr>>> commited_flushes; | ||
| 238 | }; | 288 | }; |
| 239 | 289 | ||
| 240 | template <class QueryCache, class HostCounter> | 290 | template <class QueryCache, class HostCounter> |
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() { | |||
| 44 | ; | 44 | ; |
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | FenceManagerOpenGL::FenceManagerOpenGL(Core::System& system, VideoCore::RasterizerInterface& rasterizer, | 47 | FenceManagerOpenGL::FenceManagerOpenGL(Core::System& system, |
| 48 | TextureCacheOpenGL& texture_cache, OGLBufferCache& buffer_cache) | 48 | VideoCore::RasterizerInterface& rasterizer, |
| 49 | : GenericFenceManager(system, rasterizer, texture_cache, buffer_cache) {} | 49 | TextureCacheOpenGL& texture_cache, |
| 50 | OGLBufferCache& buffer_cache, QueryCache& query_cache) | ||
| 51 | : GenericFenceManager(system, rasterizer, texture_cache, buffer_cache, query_cache) {} | ||
| 50 | 52 | ||
| 51 | Fence FenceManagerOpenGL::CreateFence(u32 value, bool is_stubbed) { | 53 | Fence FenceManagerOpenGL::CreateFence(u32 value, bool is_stubbed) { |
| 52 | return std::make_shared<GLInnerFence>(value, is_stubbed); | 54 | return std::make_shared<GLInnerFence>(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 @@ | |||
| 10 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 11 | #include "video_core/fence_manager.h" | 11 | #include "video_core/fence_manager.h" |
| 12 | #include "video_core/renderer_opengl/gl_buffer_cache.h" | 12 | #include "video_core/renderer_opengl/gl_buffer_cache.h" |
| 13 | #include "video_core/renderer_opengl/gl_query_cache.h" | ||
| 13 | #include "video_core/renderer_opengl/gl_resource_manager.h" | 14 | #include "video_core/renderer_opengl/gl_resource_manager.h" |
| 14 | #include "video_core/renderer_opengl/gl_texture_cache.h" | 15 | #include "video_core/renderer_opengl/gl_texture_cache.h" |
| 15 | 16 | ||
| @@ -32,12 +33,14 @@ private: | |||
| 32 | }; | 33 | }; |
| 33 | 34 | ||
| 34 | using Fence = std::shared_ptr<GLInnerFence>; | 35 | using Fence = std::shared_ptr<GLInnerFence>; |
| 35 | using GenericFenceManager = VideoCommon::FenceManager<Fence, TextureCacheOpenGL, OGLBufferCache>; | 36 | using GenericFenceManager = |
| 37 | VideoCommon::FenceManager<Fence, TextureCacheOpenGL, OGLBufferCache, QueryCache>; | ||
| 36 | 38 | ||
| 37 | class FenceManagerOpenGL final : public GenericFenceManager { | 39 | class FenceManagerOpenGL final : public GenericFenceManager { |
| 38 | public: | 40 | public: |
| 39 | FenceManagerOpenGL(Core::System& system, VideoCore::RasterizerInterface& rasterizer, | 41 | FenceManagerOpenGL(Core::System& system, VideoCore::RasterizerInterface& rasterizer, |
| 40 | TextureCacheOpenGL& texture_cache, OGLBufferCache& buffer_cache); | 42 | TextureCacheOpenGL& texture_cache, OGLBufferCache& buffer_cache, |
| 43 | QueryCache& query_cache); | ||
| 41 | 44 | ||
| 42 | protected: | 45 | protected: |
| 43 | Fence CreateFence(u32 value, bool is_stubbed) override; | 46 | 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 | |||
| 101 | : RasterizerAccelerated{system.Memory()}, texture_cache{system, *this, device, state_tracker}, | 101 | : RasterizerAccelerated{system.Memory()}, texture_cache{system, *this, device, state_tracker}, |
| 102 | shader_cache{*this, system, emu_window, device}, query_cache{system, *this}, system{system}, | 102 | shader_cache{*this, system, emu_window, device}, query_cache{system, *this}, system{system}, |
| 103 | screen_info{info}, program_manager{program_manager}, state_tracker{state_tracker}, | 103 | screen_info{info}, program_manager{program_manager}, state_tracker{state_tracker}, |
| 104 | buffer_cache{*this, system, device, STREAM_BUFFER_SIZE}, fence_manager{system, *this, | 104 | buffer_cache{*this, system, device, STREAM_BUFFER_SIZE}, fence_manager{ |
| 105 | texture_cache, | 105 | system, *this, texture_cache, |
| 106 | buffer_cache} { | 106 | buffer_cache, query_cache} { |
| 107 | CheckExtensions(); | 107 | CheckExtensions(); |
| 108 | } | 108 | } |
| 109 | 109 | ||