summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2020-04-15 16:36:14 -0400
committerGravatar Fernando Sahmkow2020-04-22 11:36:18 -0400
commit0649f0590047e8cc0b16a10dec5eb74938fef718 (patch)
treeb56cf7fb42c31f0012b063d356dc2b1eb1126a42
parentOpenGL: Guarantee writes to Buffers. (diff)
downloadyuzu-0649f0590047e8cc0b16a10dec5eb74938fef718.tar.gz
yuzu-0649f0590047e8cc0b16a10dec5eb74938fef718.tar.xz
yuzu-0649f0590047e8cc0b16a10dec5eb74938fef718.zip
QueryCache: Implement Async Flushes.
-rw-r--r--src/video_core/fence_manager.h18
-rw-r--r--src/video_core/query_cache.h50
-rw-r--r--src/video_core/renderer_opengl/gl_fence_manager.cpp8
-rw-r--r--src/video_core/renderer_opengl/gl_fence_manager.h7
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp6
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
52template <typename TFence, typename TTextureCache, typename TTBufferCache> 52template <typename TFence, typename TTextureCache, typename TTBufferCache, typename TQueryCache>
53class FenceManager { 53class FenceManager {
54public: 54public:
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
106protected: 112protected:
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
123private: 131private:
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
173protected: 213protected:
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
240template <class QueryCache, class HostCounter> 290template <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
47FenceManagerOpenGL::FenceManagerOpenGL(Core::System& system, VideoCore::RasterizerInterface& rasterizer, 47FenceManagerOpenGL::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
51Fence FenceManagerOpenGL::CreateFence(u32 value, bool is_stubbed) { 53Fence 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
34using Fence = std::shared_ptr<GLInnerFence>; 35using Fence = std::shared_ptr<GLInnerFence>;
35using GenericFenceManager = VideoCommon::FenceManager<Fence, TextureCacheOpenGL, OGLBufferCache>; 36using GenericFenceManager =
37 VideoCommon::FenceManager<Fence, TextureCacheOpenGL, OGLBufferCache, QueryCache>;
36 38
37class FenceManagerOpenGL final : public GenericFenceManager { 39class FenceManagerOpenGL final : public GenericFenceManager {
38public: 40public:
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
42protected: 45protected:
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