From bcd348f2388cf944f2ac49364a8d13b47cc21456 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Tue, 11 Feb 2020 18:59:44 -0300 Subject: vk_query_cache: Implement generic query cache on Vulkan --- src/video_core/query_cache.h | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) (limited to 'src/video_core/query_cache.h') 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: std::shared_ptr last; }; -template +template class QueryCacheBase { public: explicit QueryCacheBase(Core::System& system, VideoCore::RasterizerInterface& rasterizer) @@ -127,15 +128,25 @@ public: /// Updates counters from GPU state. Expected to be called once per draw, clear or dispatch. void UpdateCounters() { + std::unique_lock lock{mutex}; const auto& regs = system.GPU().Maxwell3D().regs; Stream(VideoCore::QueryType::SamplesPassed).Update(regs.samplecnt_enable); } /// Resets a counter to zero. It doesn't disable the query after resetting. void ResetCounter(VideoCore::QueryType type) { + std::unique_lock lock{mutex}; Stream(type).Reset(); } + /// Disable all active streams. Expected to be called at the end of a command buffer. + void DisableStreams() { + std::unique_lock lock{mutex}; + for (auto& stream : streams) { + stream.Update(false); + } + } + /// Returns a new host counter. std::shared_ptr Counter(std::shared_ptr dependency, VideoCore::QueryType type) { @@ -148,6 +159,9 @@ public: return streams[static_cast(type)]; } +protected: + std::array query_pools; + private: /// Flushes a memory range to guest memory and removes it from the cache. void FlushAndRemoveRegion(CacheAddr addr, std::size_t size) { @@ -213,8 +227,16 @@ private: template class HostCounterBase { public: - explicit HostCounterBase(std::shared_ptr dependency) - : dependency{std::move(dependency)} {} + explicit HostCounterBase(std::shared_ptr dependency_) + : dependency{std::move(dependency_)}, depth{dependency ? (dependency->Depth() + 1) : 0} { + // Avoid nesting too many dependencies to avoid a stack overflow when these are deleted. + static constexpr u64 depth_threshold = 96; + if (depth > depth_threshold) { + depth = 0; + base_result = dependency->Query(); + dependency = nullptr; + } + } /// Returns the current value of the query. u64 Query() { @@ -222,9 +244,10 @@ public: return *result; } - u64 value = BlockingQuery(); + u64 value = BlockingQuery() + base_result; if (dependency) { value += dependency->Query(); + dependency = nullptr; } return *(result = value); @@ -235,6 +258,10 @@ public: return result.has_value(); } + u64 Depth() const noexcept { + return depth; + } + protected: /// Returns the value of query from the backend API blocking as needed. virtual u64 BlockingQuery() const = 0; @@ -242,6 +269,8 @@ protected: private: std::shared_ptr dependency; ///< Counter to add to this value. std::optional result; ///< Filled with the already returned value. + u64 depth; ///< Number of nested dependencies. + u64 base_result = 0; ///< Equivalent to nested dependencies value. }; template -- cgit v1.2.3