summaryrefslogtreecommitdiff
path: root/src/video_core/query_cache
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2023-08-06 09:38:16 +0200
committerGravatar Fernando Sahmkow2023-09-23 23:05:30 +0200
commit282ae8fa51e060e6d4ef026b734aa871b1b9331e (patch)
tree3bc4603b6add0582315dc65544f1986427e4182d /src/video_core/query_cache
parentQueryCache: Implement dependant queries. (diff)
downloadyuzu-282ae8fa51e060e6d4ef026b734aa871b1b9331e.tar.gz
yuzu-282ae8fa51e060e6d4ef026b734aa871b1b9331e.tar.xz
yuzu-282ae8fa51e060e6d4ef026b734aa871b1b9331e.zip
Query Cache: address issues
Diffstat (limited to 'src/video_core/query_cache')
-rw-r--r--src/video_core/query_cache/bank_base.h16
-rw-r--r--src/video_core/query_cache/query_base.h44
-rw-r--r--src/video_core/query_cache/query_cache.h66
-rw-r--r--src/video_core/query_cache/query_cache_base.h8
-rw-r--r--src/video_core/query_cache/query_stream.h22
5 files changed, 85 insertions, 71 deletions
diff --git a/src/video_core/query_cache/bank_base.h b/src/video_core/query_cache/bank_base.h
index 4246a609d..420927091 100644
--- a/src/video_core/query_cache/bank_base.h
+++ b/src/video_core/query_cache/bank_base.h
@@ -7,21 +7,19 @@
7#include <deque> 7#include <deque>
8#include <utility> 8#include <utility>
9 9
10
11#include "common/common_types.h" 10#include "common/common_types.h"
12 11
13namespace VideoCommon { 12namespace VideoCommon {
14 13
15class BankBase { 14class BankBase {
16protected: 15protected:
17 const size_t base_bank_size; 16 const size_t base_bank_size{};
18 size_t bank_size; 17 size_t bank_size{};
19 std::atomic<size_t> references; 18 std::atomic<size_t> references{};
20 size_t current_slot; 19 size_t current_slot{};
21 20
22public: 21public:
23 BankBase(size_t bank_size_) 22 explicit BankBase(size_t bank_size_) : base_bank_size{bank_size_}, bank_size(bank_size_) {}
24 : base_bank_size{bank_size_}, bank_size(bank_size_), references(0), current_slot(0) {}
25 23
26 virtual ~BankBase() = default; 24 virtual ~BankBase() = default;
27 25
@@ -58,11 +56,11 @@ public:
58 bank_size = current_slot; 56 bank_size = current_slot;
59 } 57 }
60 58
61 constexpr bool IsClosed() { 59 bool IsClosed() const {
62 return current_slot >= bank_size; 60 return current_slot >= bank_size;
63 } 61 }
64 62
65 bool IsDead() { 63 bool IsDead() const {
66 return IsClosed() && references == 0; 64 return IsClosed() && references == 0;
67 } 65 }
68}; 66};
diff --git a/src/video_core/query_cache/query_base.h b/src/video_core/query_cache/query_base.h
index 0ae23af9f..993a13eac 100644
--- a/src/video_core/query_cache/query_base.h
+++ b/src/video_core/query_cache/query_base.h
@@ -9,28 +9,28 @@
9namespace VideoCommon { 9namespace VideoCommon {
10 10
11enum class QueryFlagBits : u32 { 11enum class QueryFlagBits : u32 {
12 HasTimestamp = 1 << 0, ///< Indicates if this query has a tiemstamp. 12 HasTimestamp = 1 << 0, ///< Indicates if this query has a timestamp.
13 IsFinalValueSynced = 1 << 1, ///< Indicates if the query has been synced in the host 13 IsFinalValueSynced = 1 << 1, ///< Indicates if the query has been synced in the host
14 IsHostSynced = 1 << 2, ///< Indicates if the query has been synced in the host 14 IsHostSynced = 1 << 2, ///< Indicates if the query has been synced in the host
15 IsGuestSynced = 1 << 3, ///< Indicates if the query has been synced with the guest. 15 IsGuestSynced = 1 << 3, ///< Indicates if the query has been synced with the guest.
16 IsHostManaged = 1 << 4, ///< Indicates if this query points to a host query 16 IsHostManaged = 1 << 4, ///< Indicates if this query points to a host query
17 IsRewritten = 1 << 5, ///< Indicates if this query was rewritten by another query 17 IsRewritten = 1 << 5, ///< Indicates if this query was rewritten by another query
18 IsInvalidated = 1 << 6, ///< Indicates the value of th query has been nullified. 18 IsInvalidated = 1 << 6, ///< Indicates the value of th query has been nullified.
19 IsOrphan = 1 << 7, ///< Indicates the query has not been set by a guest query. 19 IsOrphan = 1 << 7, ///< Indicates the query has not been set by a guest query.
20 IsFence = 1 << 8, ///< Indicates the query is a fence. 20 IsFence = 1 << 8, ///< Indicates the query is a fence.
21 IsQueuedForAsyncFlush = 1 <<9,///< Indicates that the query can be flushed at any moment 21 IsQueuedForAsyncFlush = 1 << 9, ///< Indicates that the query can be flushed at any moment
22}; 22};
23DECLARE_ENUM_FLAG_OPERATORS(QueryFlagBits) 23DECLARE_ENUM_FLAG_OPERATORS(QueryFlagBits)
24 24
25class QueryBase { 25class QueryBase {
26public: 26public:
27 VAddr guest_address; 27 VAddr guest_address{};
28 QueryFlagBits flags; 28 QueryFlagBits flags{};
29 u64 value; 29 u64 value{};
30 30
31protected: 31protected:
32 // Default constructor 32 // Default constructor
33 QueryBase() : guest_address(0), flags{}, value{} {} 33 QueryBase() = default;
34 34
35 // Parameterized constructor 35 // Parameterized constructor
36 QueryBase(VAddr address, QueryFlagBits flags_, u64 value_) 36 QueryBase(VAddr address, QueryFlagBits flags_, u64 value_)
@@ -51,23 +51,21 @@ public:
51class HostQueryBase : public QueryBase { 51class HostQueryBase : public QueryBase {
52public: 52public:
53 // Default constructor 53 // Default constructor
54 HostQueryBase() 54 HostQueryBase() : QueryBase(0, QueryFlagBits::IsHostManaged | QueryFlagBits::IsOrphan, 0) {}
55 : QueryBase(0, QueryFlagBits::IsHostManaged | QueryFlagBits::IsOrphan, 0), start_bank_id{},
56 size_banks{}, start_slot{}, size_slots{} {}
57 55
58 // Parameterized constructor 56 // Parameterized constructor
59 HostQueryBase(bool isLong, VAddr address) 57 HostQueryBase(bool has_timestamp, VAddr address)
60 : QueryBase(address, QueryFlagBits::IsHostManaged, 0), start_bank_id{}, size_banks{}, 58 : QueryBase(address, QueryFlagBits::IsHostManaged, 0), start_bank_id{}, size_banks{},
61 start_slot{}, size_slots{} { 59 start_slot{}, size_slots{} {
62 if (isLong) { 60 if (has_timestamp) {
63 flags |= QueryFlagBits::HasTimestamp; 61 flags |= QueryFlagBits::HasTimestamp;
64 } 62 }
65 } 63 }
66 64
67 u32 start_bank_id; 65 u32 start_bank_id{};
68 u32 size_banks; 66 u32 size_banks{};
69 size_t start_slot; 67 size_t start_slot{};
70 size_t size_slots; 68 size_t size_slots{};
71}; 69};
72 70
73} // namespace VideoCommon \ No newline at end of file 71} // namespace VideoCommon \ No newline at end of file
diff --git a/src/video_core/query_cache/query_cache.h b/src/video_core/query_cache/query_cache.h
index f1393d5c7..042af053c 100644
--- a/src/video_core/query_cache/query_cache.h
+++ b/src/video_core/query_cache/query_cache.h
@@ -54,7 +54,7 @@ public:
54 return new_id; 54 return new_id;
55 } 55 }
56 56
57 bool HasPendingSync() override { 57 bool HasPendingSync() const override {
58 return !pending_sync.empty(); 58 return !pending_sync.empty();
59 } 59 }
60 60
@@ -71,8 +71,10 @@ public:
71 continue; 71 continue;
72 } 72 }
73 query.flags |= QueryFlagBits::IsHostSynced; 73 query.flags |= QueryFlagBits::IsHostSynced;
74 sync_values.emplace_back(query.guest_address, query.value, 74 sync_values.emplace_back(SyncValuesStruct{
75 True(query.flags & QueryFlagBits::HasTimestamp) ? 8 : 4); 75 .address = query.guest_address,
76 .value = query.value,
77 .size = static_cast<u64>(True(query.flags & QueryFlagBits::HasTimestamp) ? 8 : 4)});
76 } 78 }
77 pending_sync.clear(); 79 pending_sync.clear();
78 if (sync_values.size() > 0) { 80 if (sync_values.size() > 0) {
@@ -90,15 +92,20 @@ class StubStreamer : public GuestStreamer<Traits> {
90public: 92public:
91 using RuntimeType = typename Traits::RuntimeType; 93 using RuntimeType = typename Traits::RuntimeType;
92 94
93 StubStreamer(size_t id_, RuntimeType& runtime_) : GuestStreamer<Traits>(id_, runtime_) {} 95 StubStreamer(size_t id_, RuntimeType& runtime_, u32 stub_value_)
96 : GuestStreamer<Traits>(id_, runtime_), stub_value{stub_value_} {}
94 97
95 ~StubStreamer() override = default; 98 ~StubStreamer() override = default;
96 99
97 size_t WriteCounter(VAddr address, bool has_timestamp, [[maybe_unused]] u32 value, 100 size_t WriteCounter(VAddr address, bool has_timestamp, [[maybe_unused]] u32 value,
98 std::optional<u32> subreport = std::nullopt) override { 101 std::optional<u32> subreport = std::nullopt) override {
99 size_t new_id = GuestStreamer<Traits>::WriteCounter(address, has_timestamp, 1U, subreport); 102 size_t new_id =
103 GuestStreamer<Traits>::WriteCounter(address, has_timestamp, stub_value, subreport);
100 return new_id; 104 return new_id;
101 } 105 }
106
107private:
108 u32 stub_value;
102}; 109};
103 110
104template <typename Traits> 111template <typename Traits>
@@ -113,7 +120,7 @@ struct QueryCacheBase<Traits>::QueryCacheBaseImpl {
113 for (size_t i = 0; i < static_cast<size_t>(QueryType::MaxQueryTypes); i++) { 120 for (size_t i = 0; i < static_cast<size_t>(QueryType::MaxQueryTypes); i++) {
114 streamers[i] = runtime.GetStreamerInterface(static_cast<QueryType>(i)); 121 streamers[i] = runtime.GetStreamerInterface(static_cast<QueryType>(i));
115 if (streamers[i]) { 122 if (streamers[i]) {
116 streamer_mask |= 1ULL << i; 123 streamer_mask |= 1ULL << streamers[i]->GetId();
117 } 124 }
118 } 125 }
119 } 126 }
@@ -152,7 +159,7 @@ struct QueryCacheBase<Traits>::QueryCacheBaseImpl {
152 QueryCacheBase<Traits>* owner; 159 QueryCacheBase<Traits>* owner;
153 VideoCore::RasterizerInterface& rasterizer; 160 VideoCore::RasterizerInterface& rasterizer;
154 Core::Memory::Memory& cpu_memory; 161 Core::Memory::Memory& cpu_memory;
155 Traits::RuntimeType& runtime; 162 RuntimeType& runtime;
156 Tegra::GPU& gpu; 163 Tegra::GPU& gpu;
157 std::array<StreamerInterface*, static_cast<size_t>(QueryType::MaxQueryTypes)> streamers; 164 std::array<StreamerInterface*, static_cast<size_t>(QueryType::MaxQueryTypes)> streamers;
158 u64 streamer_mask; 165 u64 streamer_mask;
@@ -223,15 +230,11 @@ void QueryCacheBase<Traits>::CounterReport(GPUVAddr addr, QueryType counter_type
223 const bool is_fence = True(flags & QueryPropertiesFlags::IsAFence); 230 const bool is_fence = True(flags & QueryPropertiesFlags::IsAFence);
224 size_t streamer_id = static_cast<size_t>(counter_type); 231 size_t streamer_id = static_cast<size_t>(counter_type);
225 auto* streamer = impl->streamers[streamer_id]; 232 auto* streamer = impl->streamers[streamer_id];
226 if (!streamer) [[unlikely]] { 233 if (streamer == nullptr) [[unlikely]] {
227 if (has_timestamp) { 234 counter_type = QueryType::Payload;
228 u64 timestamp = impl->gpu.GetTicks(); 235 payload = 1U;
229 gpu_memory->Write<u64>(addr + 8, timestamp); 236 streamer_id = static_cast<size_t>(counter_type);
230 gpu_memory->Write<u64>(addr, 1ULL); 237 streamer = impl->streamers[streamer_id];
231 } else {
232 gpu_memory->Write<u32>(addr, 1U);
233 }
234 return;
235 } 238 }
236 auto cpu_addr_opt = gpu_memory->GpuToCpuAddress(addr); 239 auto cpu_addr_opt = gpu_memory->GpuToCpuAddress(addr);
237 if (!cpu_addr_opt) [[unlikely]] { 240 if (!cpu_addr_opt) [[unlikely]] {
@@ -403,12 +406,6 @@ bool QueryCacheBase<Traits>::AccelerateHostConditionalRendering() {
403 impl->runtime.EndHostConditionalRendering(); 406 impl->runtime.EndHostConditionalRendering();
404 return false; 407 return false;
405 } 408 }
406 /*if (!Settings::IsGPULevelHigh()) {
407 impl->runtime.EndHostConditionalRendering();
408 return gpu_memory->IsMemoryDirty(regs.render_enable.Address(), 24,
409 VideoCommon::CacheType::BufferCache |
410 VideoCommon::CacheType::QueryCache);
411 }*/
412 const ComparisonMode mode = static_cast<ComparisonMode>(regs.render_enable.mode); 409 const ComparisonMode mode = static_cast<ComparisonMode>(regs.render_enable.mode);
413 const GPUVAddr address = regs.render_enable.Address(); 410 const GPUVAddr address = regs.render_enable.Address();
414 switch (mode) { 411 switch (mode) {
@@ -442,6 +439,9 @@ bool QueryCacheBase<Traits>::AccelerateHostConditionalRendering() {
442// Async downloads 439// Async downloads
443template <typename Traits> 440template <typename Traits>
444void QueryCacheBase<Traits>::CommitAsyncFlushes() { 441void QueryCacheBase<Traits>::CommitAsyncFlushes() {
442 // Make sure to have the results synced in Host.
443 NotifyWFI();
444
445 u64 mask{}; 445 u64 mask{};
446 { 446 {
447 std::scoped_lock lk(impl->flush_guard); 447 std::scoped_lock lk(impl->flush_guard);
@@ -458,8 +458,19 @@ void QueryCacheBase<Traits>::CommitAsyncFlushes() {
458 if (mask == 0) { 458 if (mask == 0) {
459 return; 459 return;
460 } 460 }
461 impl->ForEachStreamerIn(mask, 461 u64 ran_mask = ~mask;
462 [](StreamerInterface* streamer) { streamer->PushUnsyncedQueries(); }); 462 while (mask) {
463 impl->ForEachStreamerIn(mask, [&mask, &ran_mask](StreamerInterface* streamer) {
464 u64 dep_mask = streamer->GetDependentMask();
465 if ((dep_mask & ~ran_mask) != 0) {
466 return;
467 }
468 u64 index = streamer->GetId();
469 ran_mask |= (1ULL << index);
470 mask &= ~(1ULL << index);
471 streamer->PushUnsyncedQueries();
472 });
473 }
463} 474}
464 475
465template <typename Traits> 476template <typename Traits>
@@ -489,13 +500,11 @@ void QueryCacheBase<Traits>::PopAsyncFlushes() {
489 if (mask == 0) { 500 if (mask == 0) {
490 return; 501 return;
491 } 502 }
492 u64 ran_mask = 0; 503 u64 ran_mask = ~mask;
493 u64 next_phase = 0;
494 while (mask) { 504 while (mask) {
495 impl->ForEachStreamerIn(mask, [&mask, &ran_mask, &next_phase](StreamerInterface* streamer) { 505 impl->ForEachStreamerIn(mask, [&mask, &ran_mask](StreamerInterface* streamer) {
496 u64 dep_mask = streamer->GetDependenceMask(); 506 u64 dep_mask = streamer->GetDependenceMask();
497 if ((dep_mask & ~ran_mask) != 0) { 507 if ((dep_mask & ~ran_mask) != 0) {
498 next_phase |= dep_mask;
499 return; 508 return;
500 } 509 }
501 u64 index = streamer->GetId(); 510 u64 index = streamer->GetId();
@@ -503,7 +512,6 @@ void QueryCacheBase<Traits>::PopAsyncFlushes() {
503 mask &= ~(1ULL << index); 512 mask &= ~(1ULL << index);
504 streamer->PopUnsyncedQueries(); 513 streamer->PopUnsyncedQueries();
505 }); 514 });
506 ran_mask |= next_phase;
507 } 515 }
508} 516}
509 517
diff --git a/src/video_core/query_cache/query_cache_base.h b/src/video_core/query_cache/query_cache_base.h
index 55f508dd1..07be421c6 100644
--- a/src/video_core/query_cache/query_cache_base.h
+++ b/src/video_core/query_cache/query_cache_base.h
@@ -47,7 +47,7 @@ public:
47 BitField<0, 27, u32> query_id; 47 BitField<0, 27, u32> query_id;
48 u32 raw; 48 u32 raw;
49 49
50 std::pair<size_t, size_t> unpack() { 50 std::pair<size_t, size_t> unpack() const {
51 return {static_cast<size_t>(stream_id.Value()), static_cast<size_t>(query_id.Value())}; 51 return {static_cast<size_t>(stream_id.Value()), static_cast<size_t>(query_id.Value())};
52 } 52 }
53 }; 53 };
@@ -73,7 +73,7 @@ public:
73 } 73 }
74 } 74 }
75 75
76 static u64 BuildMask(std::span<QueryType> types) { 76 static u64 BuildMask(std::span<const QueryType> types) {
77 u64 mask = 0; 77 u64 mask = 0;
78 for (auto query_type : types) { 78 for (auto query_type : types) {
79 mask |= 1ULL << (static_cast<u64>(query_type)); 79 mask |= 1ULL << (static_cast<u64>(query_type));
@@ -160,7 +160,7 @@ protected:
160 } 160 }
161 } 161 }
162 162
163 using ContentCache = typename std::unordered_map<u64, std::unordered_map<u32, QueryLocation>>; 163 using ContentCache = std::unordered_map<u64, std::unordered_map<u32, QueryLocation>>;
164 164
165 void InvalidateQuery(QueryLocation location); 165 void InvalidateQuery(QueryLocation location);
166 bool IsQueryDirty(QueryLocation location); 166 bool IsQueryDirty(QueryLocation location);
@@ -175,7 +175,7 @@ protected:
175 friend struct QueryCacheBaseImpl; 175 friend struct QueryCacheBaseImpl;
176 friend RuntimeType; 176 friend RuntimeType;
177 177
178 std::unique_ptr<struct QueryCacheBaseImpl> impl; 178 std::unique_ptr<QueryCacheBaseImpl> impl;
179}; 179};
180 180
181} // namespace VideoCommon \ No newline at end of file 181} // namespace VideoCommon \ No newline at end of file
diff --git a/src/video_core/query_cache/query_stream.h b/src/video_core/query_cache/query_stream.h
index 0e9275565..e7aac955b 100644
--- a/src/video_core/query_cache/query_stream.h
+++ b/src/video_core/query_cache/query_stream.h
@@ -16,7 +16,7 @@ namespace VideoCommon {
16 16
17class StreamerInterface { 17class StreamerInterface {
18public: 18public:
19 StreamerInterface(size_t id_, u64 dependance_mask_ = 0) : id{id_}, dependance_mask{dependance_mask_} {} 19 explicit StreamerInterface(size_t id_) : id{id_}, dependence_mask{}, dependent_mask{} {}
20 virtual ~StreamerInterface() = default; 20 virtual ~StreamerInterface() = default;
21 21
22 virtual QueryBase* GetQuery(size_t id) = 0; 22 virtual QueryBase* GetQuery(size_t id) = 0;
@@ -37,7 +37,7 @@ public:
37 /* Do Nothing */ 37 /* Do Nothing */
38 } 38 }
39 39
40 virtual bool HasPendingSync() { 40 virtual bool HasPendingSync() const {
41 return false; 41 return false;
42 } 42 }
43 43
@@ -52,7 +52,7 @@ public:
52 virtual size_t WriteCounter(VAddr address, bool has_timestamp, u32 value, 52 virtual size_t WriteCounter(VAddr address, bool has_timestamp, u32 value,
53 std::optional<u32> subreport = std::nullopt) = 0; 53 std::optional<u32> subreport = std::nullopt) = 0;
54 54
55 virtual bool HasUnsyncedQueries() { 55 virtual bool HasUnsyncedQueries() const {
56 return false; 56 return false;
57 } 57 }
58 58
@@ -71,18 +71,28 @@ public:
71 } 71 }
72 72
73 u64 GetDependenceMask() const { 73 u64 GetDependenceMask() const {
74 return dependance_mask; 74 return dependence_mask;
75 }
76
77 u64 GetDependentMask() const {
78 return dependence_mask;
75 } 79 }
76 80
77protected: 81protected:
82 void MakeDependent(StreamerInterface* depend_on) {
83 dependence_mask |= 1ULL << depend_on->id;
84 depend_on->dependent_mask |= 1ULL << id;
85 }
86
78 const size_t id; 87 const size_t id;
79 const u64 dependance_mask; 88 u64 dependence_mask;
89 u64 dependent_mask;
80}; 90};
81 91
82template <typename QueryType> 92template <typename QueryType>
83class SimpleStreamer : public StreamerInterface { 93class SimpleStreamer : public StreamerInterface {
84public: 94public:
85 SimpleStreamer(size_t id_, u64 dependance_mask_ = 0) : StreamerInterface{id_, dependance_mask_} {} 95 explicit SimpleStreamer(size_t id_) : StreamerInterface{id_} {}
86 virtual ~SimpleStreamer() = default; 96 virtual ~SimpleStreamer() = default;
87 97
88protected: 98protected: