summaryrefslogtreecommitdiff
path: root/src/video_core/query_cache.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core/query_cache.h')
-rw-r--r--src/video_core/query_cache.h37
1 files changed, 33 insertions, 4 deletions
diff --git a/src/video_core/query_cache.h b/src/video_core/query_cache.h
index 4c9151ce8..069032121 100644
--- a/src/video_core/query_cache.h
+++ b/src/video_core/query_cache.h
@@ -88,7 +88,8 @@ private:
88 std::shared_ptr<HostCounter> last; 88 std::shared_ptr<HostCounter> last;
89}; 89};
90 90
91template <class QueryCache, class CachedQuery, class CounterStream, class HostCounter> 91template <class QueryCache, class CachedQuery, class CounterStream, class HostCounter,
92 class QueryPool>
92class QueryCacheBase { 93class QueryCacheBase {
93public: 94public:
94 explicit QueryCacheBase(Core::System& system, VideoCore::RasterizerInterface& rasterizer) 95 explicit QueryCacheBase(Core::System& system, VideoCore::RasterizerInterface& rasterizer)
@@ -127,15 +128,25 @@ public:
127 128
128 /// Updates counters from GPU state. Expected to be called once per draw, clear or dispatch. 129 /// Updates counters from GPU state. Expected to be called once per draw, clear or dispatch.
129 void UpdateCounters() { 130 void UpdateCounters() {
131 std::unique_lock lock{mutex};
130 const auto& regs = system.GPU().Maxwell3D().regs; 132 const auto& regs = system.GPU().Maxwell3D().regs;
131 Stream(VideoCore::QueryType::SamplesPassed).Update(regs.samplecnt_enable); 133 Stream(VideoCore::QueryType::SamplesPassed).Update(regs.samplecnt_enable);
132 } 134 }
133 135
134 /// Resets a counter to zero. It doesn't disable the query after resetting. 136 /// Resets a counter to zero. It doesn't disable the query after resetting.
135 void ResetCounter(VideoCore::QueryType type) { 137 void ResetCounter(VideoCore::QueryType type) {
138 std::unique_lock lock{mutex};
136 Stream(type).Reset(); 139 Stream(type).Reset();
137 } 140 }
138 141
142 /// Disable all active streams. Expected to be called at the end of a command buffer.
143 void DisableStreams() {
144 std::unique_lock lock{mutex};
145 for (auto& stream : streams) {
146 stream.Update(false);
147 }
148 }
149
139 /// Returns a new host counter. 150 /// Returns a new host counter.
140 std::shared_ptr<HostCounter> Counter(std::shared_ptr<HostCounter> dependency, 151 std::shared_ptr<HostCounter> Counter(std::shared_ptr<HostCounter> dependency,
141 VideoCore::QueryType type) { 152 VideoCore::QueryType type) {
@@ -148,6 +159,9 @@ public:
148 return streams[static_cast<std::size_t>(type)]; 159 return streams[static_cast<std::size_t>(type)];
149 } 160 }
150 161
162protected:
163 std::array<QueryPool, VideoCore::NumQueryTypes> query_pools;
164
151private: 165private:
152 /// Flushes a memory range to guest memory and removes it from the cache. 166 /// Flushes a memory range to guest memory and removes it from the cache.
153 void FlushAndRemoveRegion(CacheAddr addr, std::size_t size) { 167 void FlushAndRemoveRegion(CacheAddr addr, std::size_t size) {
@@ -213,8 +227,16 @@ private:
213template <class QueryCache, class HostCounter> 227template <class QueryCache, class HostCounter>
214class HostCounterBase { 228class HostCounterBase {
215public: 229public:
216 explicit HostCounterBase(std::shared_ptr<HostCounter> dependency) 230 explicit HostCounterBase(std::shared_ptr<HostCounter> dependency_)
217 : dependency{std::move(dependency)} {} 231 : dependency{std::move(dependency_)}, depth{dependency ? (dependency->Depth() + 1) : 0} {
232 // Avoid nesting too many dependencies to avoid a stack overflow when these are deleted.
233 static constexpr u64 depth_threshold = 96;
234 if (depth > depth_threshold) {
235 depth = 0;
236 base_result = dependency->Query();
237 dependency = nullptr;
238 }
239 }
218 240
219 /// Returns the current value of the query. 241 /// Returns the current value of the query.
220 u64 Query() { 242 u64 Query() {
@@ -222,9 +244,10 @@ public:
222 return *result; 244 return *result;
223 } 245 }
224 246
225 u64 value = BlockingQuery(); 247 u64 value = BlockingQuery() + base_result;
226 if (dependency) { 248 if (dependency) {
227 value += dependency->Query(); 249 value += dependency->Query();
250 dependency = nullptr;
228 } 251 }
229 252
230 return *(result = value); 253 return *(result = value);
@@ -235,6 +258,10 @@ public:
235 return result.has_value(); 258 return result.has_value();
236 } 259 }
237 260
261 u64 Depth() const noexcept {
262 return depth;
263 }
264
238protected: 265protected:
239 /// Returns the value of query from the backend API blocking as needed. 266 /// Returns the value of query from the backend API blocking as needed.
240 virtual u64 BlockingQuery() const = 0; 267 virtual u64 BlockingQuery() const = 0;
@@ -242,6 +269,8 @@ protected:
242private: 269private:
243 std::shared_ptr<HostCounter> dependency; ///< Counter to add to this value. 270 std::shared_ptr<HostCounter> dependency; ///< Counter to add to this value.
244 std::optional<u64> result; ///< Filled with the already returned value. 271 std::optional<u64> result; ///< Filled with the already returned value.
272 u64 depth; ///< Number of nested dependencies.
273 u64 base_result = 0; ///< Equivalent to nested dependencies value.
245}; 274};
246 275
247template <class HostCounter> 276template <class HostCounter>