summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2019-11-26 18:52:15 -0300
committerGravatar ReinUsesLisp2020-02-14 17:33:13 -0300
commitaae8c180cbbf91ba12f53c37e81a97d4b3cc4ccd (patch)
tree560202675a073aa8e3863b4e17874fed27db8a6d /src
parentgl_rasterizer: Sort method declarations (diff)
downloadyuzu-aae8c180cbbf91ba12f53c37e81a97d4b3cc4ccd.tar.gz
yuzu-aae8c180cbbf91ba12f53c37e81a97d4b3cc4ccd.tar.xz
yuzu-aae8c180cbbf91ba12f53c37e81a97d4b3cc4ccd.zip
gl_query_cache: Implement host queries using a deferred cache
Instead of waiting immediately for executed commands, defer the query until the guest CPU reads it. This way we get closer to what the guest program is doing. To archive this we have to build a dependency queue, because host APIs (like OpenGL and Vulkan) use ranged queries instead of counters like NVN. Waiting for queries implicitly uses fences and this requires a command being queued, otherwise the driver will lock waiting until a timeout. To fix this when there are no commands queued, we explicitly call glFlush.
Diffstat (limited to 'src')
-rw-r--r--src/video_core/engines/maxwell_3d.cpp41
-rw-r--r--src/video_core/engines/maxwell_3d.h4
-rw-r--r--src/video_core/rasterizer_interface.h5
-rw-r--r--src/video_core/renderer_opengl/gl_query_cache.cpp201
-rw-r--r--src/video_core/renderer_opengl/gl_query_cache.h123
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp30
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h10
7 files changed, 328 insertions, 86 deletions
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index fe91ff6a0..9add2bc94 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -556,23 +556,13 @@ void Maxwell3D::ProcessQueryGet() {
556 // matches the current payload. 556 // matches the current payload.
557 UNIMPLEMENTED_MSG("Unimplemented query operation ACQUIRE"); 557 UNIMPLEMENTED_MSG("Unimplemented query operation ACQUIRE");
558 break; 558 break;
559 case Regs::QueryOperation::Counter: { 559 case Regs::QueryOperation::Counter:
560 u64 result; 560 if (const std::optional<u64> result = GetQueryResult()) {
561 switch (regs.query.query_get.select) { 561 // If the query returns an empty optional it means it's cached and deferred.
562 case Regs::QuerySelect::Zero: 562 // In this case we have a non-empty result, so we stamp it immediately.
563 result = 0; 563 StampQueryResult(*result, regs.query.query_get.short_query == 0);
564 break;
565 case Regs::QuerySelect::SamplesPassed:
566 result = rasterizer.Query(VideoCore::QueryType::SamplesPassed);
567 break;
568 default:
569 result = 1;
570 UNIMPLEMENTED_MSG("Unimplemented query select type {}",
571 static_cast<u32>(regs.query.query_get.select.Value()));
572 } 564 }
573 StampQueryResult(result, regs.query.query_get.short_query == 0);
574 break; 565 break;
575 }
576 case Regs::QueryOperation::Trap: 566 case Regs::QueryOperation::Trap:
577 UNIMPLEMENTED_MSG("Unimplemented query operation TRAP"); 567 UNIMPLEMENTED_MSG("Unimplemented query operation TRAP");
578 break; 568 break;
@@ -595,20 +585,20 @@ void Maxwell3D::ProcessQueryCondition() {
595 } 585 }
596 case Regs::ConditionMode::ResNonZero: { 586 case Regs::ConditionMode::ResNonZero: {
597 Regs::QueryCompare cmp; 587 Regs::QueryCompare cmp;
598 memory_manager.ReadBlockUnsafe(condition_address, &cmp, sizeof(cmp)); 588 memory_manager.ReadBlock(condition_address, &cmp, sizeof(cmp));
599 execute_on = cmp.initial_sequence != 0U && cmp.initial_mode != 0U; 589 execute_on = cmp.initial_sequence != 0U && cmp.initial_mode != 0U;
600 break; 590 break;
601 } 591 }
602 case Regs::ConditionMode::Equal: { 592 case Regs::ConditionMode::Equal: {
603 Regs::QueryCompare cmp; 593 Regs::QueryCompare cmp;
604 memory_manager.ReadBlockUnsafe(condition_address, &cmp, sizeof(cmp)); 594 memory_manager.ReadBlock(condition_address, &cmp, sizeof(cmp));
605 execute_on = 595 execute_on =
606 cmp.initial_sequence == cmp.current_sequence && cmp.initial_mode == cmp.current_mode; 596 cmp.initial_sequence == cmp.current_sequence && cmp.initial_mode == cmp.current_mode;
607 break; 597 break;
608 } 598 }
609 case Regs::ConditionMode::NotEqual: { 599 case Regs::ConditionMode::NotEqual: {
610 Regs::QueryCompare cmp; 600 Regs::QueryCompare cmp;
611 memory_manager.ReadBlockUnsafe(condition_address, &cmp, sizeof(cmp)); 601 memory_manager.ReadBlock(condition_address, &cmp, sizeof(cmp));
612 execute_on = 602 execute_on =
613 cmp.initial_sequence != cmp.current_sequence || cmp.initial_mode != cmp.current_mode; 603 cmp.initial_sequence != cmp.current_sequence || cmp.initial_mode != cmp.current_mode;
614 break; 604 break;
@@ -674,6 +664,21 @@ void Maxwell3D::DrawArrays() {
674 } 664 }
675} 665}
676 666
667std::optional<u64> Maxwell3D::GetQueryResult() {
668 switch (regs.query.query_get.select) {
669 case Regs::QuerySelect::Zero:
670 return 0;
671 case Regs::QuerySelect::SamplesPassed:
672 // Deferred.
673 rasterizer.Query(regs.query.QueryAddress(), VideoCore::QueryType::SamplesPassed);
674 return {};
675 default:
676 UNIMPLEMENTED_MSG("Unimplemented query select type {}",
677 static_cast<u32>(regs.query.query_get.select.Value()));
678 return 1;
679 }
680}
681
677void Maxwell3D::ProcessCBBind(std::size_t stage_index) { 682void Maxwell3D::ProcessCBBind(std::size_t stage_index) {
678 // Bind the buffer currently in CB_ADDRESS to the specified index in the desired shader stage. 683 // Bind the buffer currently in CB_ADDRESS to the specified index in the desired shader stage.
679 auto& shader = state.shader_stages[stage_index]; 684 auto& shader = state.shader_stages[stage_index];
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index d21f678ed..26939be3f 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -6,6 +6,7 @@
6 6
7#include <array> 7#include <array>
8#include <bitset> 8#include <bitset>
9#include <optional>
9#include <type_traits> 10#include <type_traits>
10#include <unordered_map> 11#include <unordered_map>
11#include <vector> 12#include <vector>
@@ -1462,6 +1463,9 @@ private:
1462 1463
1463 // Handles a instance drawcall from MME 1464 // Handles a instance drawcall from MME
1464 void StepInstance(MMEDrawMode expected_mode, u32 count); 1465 void StepInstance(MMEDrawMode expected_mode, u32 count);
1466
1467 /// Returns a query's value or an empty object if the value will be deferred through a cache.
1468 std::optional<u64> GetQueryResult();
1465}; 1469};
1466 1470
1467#define ASSERT_REG_POSITION(field_name, position) \ 1471#define ASSERT_REG_POSITION(field_name, position) \
diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h
index 2fc627539..a394f2d3e 100644
--- a/src/video_core/rasterizer_interface.h
+++ b/src/video_core/rasterizer_interface.h
@@ -20,6 +20,7 @@ namespace VideoCore {
20enum class QueryType { 20enum class QueryType {
21 SamplesPassed, 21 SamplesPassed,
22}; 22};
23constexpr std::size_t NumQueryTypes = 1;
23 24
24enum class LoadCallbackStage { 25enum class LoadCallbackStage {
25 Prepare, 26 Prepare,
@@ -48,8 +49,8 @@ public:
48 /// Resets the counter of a query 49 /// Resets the counter of a query
49 virtual void ResetCounter(QueryType type) = 0; 50 virtual void ResetCounter(QueryType type) = 0;
50 51
51 /// Returns the value of a GPU query 52 /// Records a GPU query and caches it
52 virtual u64 Query(QueryType type) = 0; 53 virtual void Query(GPUVAddr gpu_addr, QueryType type) = 0;
53 54
54 /// Notify rasterizer that all caches should be flushed to Switch memory 55 /// Notify rasterizer that all caches should be flushed to Switch memory
55 virtual void FlushAll() = 0; 56 virtual void FlushAll() = 0;
diff --git a/src/video_core/renderer_opengl/gl_query_cache.cpp b/src/video_core/renderer_opengl/gl_query_cache.cpp
index 1c7dc999a..8f0e8241d 100644
--- a/src/video_core/renderer_opengl/gl_query_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_query_cache.cpp
@@ -2,58 +2,203 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <cstring>
6#include <memory>
7#include <utility>
8#include <vector>
9
5#include <glad/glad.h> 10#include <glad/glad.h>
6 11
12#include "common/assert.h"
13#include "core/core.h"
14#include "video_core/engines/maxwell_3d.h"
15#include "video_core/memory_manager.h"
7#include "video_core/renderer_opengl/gl_query_cache.h" 16#include "video_core/renderer_opengl/gl_query_cache.h"
17#include "video_core/renderer_opengl/gl_rasterizer.h"
8 18
9namespace OpenGL { 19namespace OpenGL {
10 20
11HostCounter::HostCounter(GLenum target) { 21using VideoCore::QueryType;
12 query.Create(target); 22
23namespace {
24
25constexpr std::array<GLenum, VideoCore::NumQueryTypes> QueryTargets = {GL_SAMPLES_PASSED};
26
27constexpr GLenum GetTarget(QueryType type) {
28 return QueryTargets[static_cast<std::size_t>(type)];
13} 29}
14 30
15HostCounter::~HostCounter() = default; 31} // Anonymous namespace
32
33CounterStream::CounterStream(QueryCache& cache, QueryType type)
34 : cache{cache}, type{type}, target{GetTarget(type)} {}
16 35
17void HostCounter::UpdateState(bool enabled) { 36CounterStream::~CounterStream() = default;
37
38void CounterStream::Update(bool enabled, bool any_command_queued) {
18 if (enabled) { 39 if (enabled) {
19 Enable(); 40 if (!current) {
20 } else { 41 current = cache.GetHostCounter(last, type);
21 Disable(); 42 }
43 return;
22 } 44 }
45
46 if (current) {
47 EndQuery(any_command_queued);
48 }
49 last = std::exchange(current, nullptr);
23} 50}
24 51
25void HostCounter::Reset() { 52void CounterStream::Reset(bool any_command_queued) {
26 counter = 0; 53 if (current) {
27 Disable(); 54 EndQuery(any_command_queued);
55 }
56 current = nullptr;
57 last = nullptr;
28} 58}
29 59
30u64 HostCounter::Query() { 60std::shared_ptr<HostCounter> CounterStream::GetCurrent(bool any_command_queued) {
31 if (!is_beginned) { 61 if (!current) {
32 return counter; 62 return nullptr;
63 }
64 EndQuery(any_command_queued);
65 last = std::move(current);
66 current = cache.GetHostCounter(last, type);
67 return last;
68}
69
70void CounterStream::EndQuery(bool any_command_queued) {
71 if (!any_command_queued) {
72 // There are chances a query waited on without commands (glDraw, glClear, glDispatch). Not
73 // having any of these causes a lock. glFlush is considered a command, so we can safely wait
74 // for this. Insert to the OpenGL command stream a flush.
75 glFlush();
76 }
77 glEndQuery(target);
78}
79
80QueryCache::QueryCache(Core::System& system, RasterizerOpenGL& rasterizer)
81 : RasterizerCache{rasterizer}, system{system},
82 rasterizer{rasterizer}, streams{{CounterStream{*this, QueryType::SamplesPassed}}} {}
83
84QueryCache::~QueryCache() = default;
85
86void QueryCache::Query(GPUVAddr gpu_addr, QueryType type) {
87 auto& memory_manager = system.GPU().MemoryManager();
88 const auto host_ptr = memory_manager.GetPointer(gpu_addr);
89
90 auto query = TryGet(host_ptr);
91 if (!query) {
92 const auto cpu_addr = memory_manager.GpuToCpuAddress(gpu_addr);
93 ASSERT_OR_EXECUTE(cpu_addr, return;);
94
95 query = std::make_shared<CachedQuery>(type, *cpu_addr, host_ptr);
96 Register(query);
97 }
98
99 query->SetCounter(GetStream(type).GetCurrent(rasterizer.AnyCommandQueued()));
100 query->MarkAsModified(true, *this);
101}
102
103void QueryCache::UpdateCounters() {
104 auto& samples_passed = GetStream(QueryType::SamplesPassed);
105
106 const auto& regs = system.GPU().Maxwell3D().regs;
107 samples_passed.Update(regs.samplecnt_enable, rasterizer.AnyCommandQueued());
108}
109
110void QueryCache::ResetCounter(QueryType type) {
111 GetStream(type).Reset(rasterizer.AnyCommandQueued());
112}
113
114void QueryCache::Reserve(QueryType type, OGLQuery&& query) {
115 reserved_queries[static_cast<std::size_t>(type)].push_back(std::move(query));
116}
117
118std::shared_ptr<HostCounter> QueryCache::GetHostCounter(std::shared_ptr<HostCounter> dependency,
119 QueryType type) {
120 const auto type_index = static_cast<std::size_t>(type);
121 auto& reserve = reserved_queries[type_index];
122
123 if (reserve.empty()) {
124 return std::make_shared<HostCounter>(*this, std::move(dependency), type);
33 } 125 }
34 Disable();
35 u64 value;
36 glGetQueryObjectui64v(query.handle, GL_QUERY_RESULT, &value);
37 Enable();
38 126
39 counter += value; 127 auto counter = std::make_shared<HostCounter>(*this, std::move(dependency), type,
128 std::move(reserve.back()));
129 reserve.pop_back();
40 return counter; 130 return counter;
41} 131}
42 132
43void HostCounter::Enable() { 133void QueryCache::FlushObjectInner(const std::shared_ptr<CachedQuery>& counter_) {
44 if (is_beginned) { 134 auto& counter = *counter_;
45 return; 135 auto& stream = GetStream(counter.GetType());
136
137 // Waiting for a query while another query of the same target is enabled locks Nvidia's driver.
138 // To avoid this disable and re-enable keeping the dependency stream.
139 const bool is_enabled = stream.IsEnabled();
140 if (is_enabled) {
141 stream.Update(false, false);
142 }
143
144 counter.Flush();
145
146 if (is_enabled) {
147 stream.Update(true, false);
46 } 148 }
47 is_beginned = true;
48 glBeginQuery(GL_SAMPLES_PASSED, query.handle);
49} 149}
50 150
51void HostCounter::Disable() { 151CounterStream& QueryCache::GetStream(QueryType type) {
52 if (!is_beginned) { 152 return streams[static_cast<std::size_t>(type)];
53 return; 153}
154
155HostCounter::HostCounter(QueryCache& cache, std::shared_ptr<HostCounter> dependency, QueryType type)
156 : cache{cache}, type{type}, dependency{std::move(dependency)} {
157 const GLenum target = GetTarget(type);
158 query.Create(target);
159 glBeginQuery(target, query.handle);
160}
161
162HostCounter::HostCounter(QueryCache& cache, std::shared_ptr<HostCounter> dependency, QueryType type,
163 OGLQuery&& query_)
164 : cache{cache}, type{type}, dependency{std::move(dependency)}, query{std::move(query_)} {
165 glBeginQuery(GetTarget(type), query.handle);
166}
167
168HostCounter::~HostCounter() {
169 cache.Reserve(type, std::move(query));
170}
171
172u64 HostCounter::Query() {
173 if (query.handle == 0) {
174 return result;
175 }
176
177 glGetQueryObjectui64v(query.handle, GL_QUERY_RESULT, &result);
178
179 if (dependency) {
180 result += dependency->Query();
54 } 181 }
55 glEndQuery(GL_SAMPLES_PASSED); 182
56 is_beginned = false; 183 return result;
184}
185
186CachedQuery::CachedQuery(QueryType type, VAddr cpu_addr, u8* host_ptr)
187 : RasterizerCacheObject{host_ptr}, type{type}, cpu_addr{cpu_addr}, host_ptr{host_ptr} {}
188
189CachedQuery::~CachedQuery() = default;
190
191void CachedQuery::Flush() {
192 const u64 value = counter->Query();
193 std::memcpy(host_ptr, &value, sizeof(value));
194}
195
196void CachedQuery::SetCounter(std::shared_ptr<HostCounter> counter_) {
197 counter = std::move(counter_);
198}
199
200QueryType CachedQuery::GetType() const {
201 return type;
57} 202}
58 203
59} // namespace OpenGL 204} // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/gl_query_cache.h b/src/video_core/renderer_opengl/gl_query_cache.h
index 52c6546bf..91594b120 100644
--- a/src/video_core/renderer_opengl/gl_query_cache.h
+++ b/src/video_core/renderer_opengl/gl_query_cache.h
@@ -4,38 +4,131 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <array>
8#include <memory>
9#include <optional>
10#include <vector>
11
7#include <glad/glad.h> 12#include <glad/glad.h>
8 13
9#include "common/common_types.h" 14#include "common/common_types.h"
15#include "video_core/rasterizer_cache.h"
16#include "video_core/rasterizer_interface.h"
10#include "video_core/renderer_opengl/gl_resource_manager.h" 17#include "video_core/renderer_opengl/gl_resource_manager.h"
11 18
19namespace Core {
20class System;
21}
22
12namespace OpenGL { 23namespace OpenGL {
13 24
14class HostCounter final { 25class CachedQuery;
26class HostCounter;
27class RasterizerOpenGL;
28class QueryCache;
29
30class CounterStream final {
15public: 31public:
16 explicit HostCounter(GLenum target); 32 explicit CounterStream(QueryCache& cache, VideoCore::QueryType type);
17 ~HostCounter(); 33 ~CounterStream();
34
35 void Update(bool enabled, bool any_command_queued);
36
37 void Reset(bool any_command_queued);
38
39 std::shared_ptr<HostCounter> GetCurrent(bool any_command_queued);
40
41 bool IsEnabled() const {
42 return current != nullptr;
43 }
44
45private:
46 void EndQuery(bool any_command_queued);
47
48 QueryCache& cache;
49
50 std::shared_ptr<HostCounter> current;
51 std::shared_ptr<HostCounter> last;
52 VideoCore::QueryType type;
53 GLenum target;
54};
55
56class QueryCache final : public RasterizerCache<std::shared_ptr<CachedQuery>> {
57public:
58 explicit QueryCache(Core::System& system, RasterizerOpenGL& rasterizer);
59 ~QueryCache();
60
61 void Query(GPUVAddr gpu_addr, VideoCore::QueryType type);
62
63 void UpdateCounters();
64
65 void ResetCounter(VideoCore::QueryType type);
18 66
19 /// Enables or disables the counter as required. 67 void Reserve(VideoCore::QueryType type, OGLQuery&& query);
20 void UpdateState(bool enabled);
21 68
22 /// Resets the counter disabling it if needed. 69 std::shared_ptr<HostCounter> GetHostCounter(std::shared_ptr<HostCounter> dependency,
23 void Reset(); 70 VideoCore::QueryType type);
71
72protected:
73 void FlushObjectInner(const std::shared_ptr<CachedQuery>& counter) override;
74
75private:
76 CounterStream& GetStream(VideoCore::QueryType type);
77
78 Core::System& system;
79 RasterizerOpenGL& rasterizer;
80
81 std::array<CounterStream, VideoCore::NumQueryTypes> streams;
82 std::array<std::vector<OGLQuery>, VideoCore::NumQueryTypes> reserved_queries;
83};
84
85class HostCounter final {
86public:
87 explicit HostCounter(QueryCache& cache, std::shared_ptr<HostCounter> dependency,
88 VideoCore::QueryType type);
89 explicit HostCounter(QueryCache& cache, std::shared_ptr<HostCounter> dependency,
90 VideoCore::QueryType type, OGLQuery&& query);
91 ~HostCounter();
24 92
25 /// Returns the current value of the query. 93 /// Returns the current value of the query.
26 /// @note It may harm precision of future queries if the counter is not disabled.
27 u64 Query(); 94 u64 Query();
28 95
29private: 96private:
30 /// Enables the counter when disabled. 97 QueryCache& cache;
31 void Enable(); 98 VideoCore::QueryType type;
32 99
33 /// Disables the counter when enabled. 100 std::shared_ptr<HostCounter> dependency; ///< Counter queued before this one.
34 void Disable(); 101 OGLQuery query; ///< OpenGL query.
102 u64 result; ///< Added values of the counter.
103};
104
105class CachedQuery final : public RasterizerCacheObject {
106public:
107 explicit CachedQuery(VideoCore::QueryType type, VAddr cpu_addr, u8* host_ptr);
108 ~CachedQuery();
109
110 /// Writes the counter value to host memory.
111 void Flush();
112
113 /// Updates the counter this cached query registered in guest memory will write when requested.
114 void SetCounter(std::shared_ptr<HostCounter> counter);
35 115
36 OGLQuery query; ///< OpenGL query. 116 /// Returns the query type.
37 u64 counter{}; ///< Added values of the counter. 117 VideoCore::QueryType GetType() const;
38 bool is_beginned{}; ///< True when the OpenGL query is beginned. 118
119 VAddr GetCpuAddr() const override {
120 return cpu_addr;
121 }
122
123 std::size_t GetSizeInBytes() const override {
124 return sizeof(u64);
125 }
126
127private:
128 VideoCore::QueryType type;
129 VAddr cpu_addr; ///< Guest CPU address.
130 u8* host_ptr; ///< Writable host pointer.
131 std::shared_ptr<HostCounter> counter; ///< Host counter to query, owns the dependency tree.
39}; 132};
40 133
41} // namespace OpenGL 134} // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 652db705b..827f85884 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -25,6 +25,7 @@
25#include "video_core/engines/maxwell_3d.h" 25#include "video_core/engines/maxwell_3d.h"
26#include "video_core/engines/shader_type.h" 26#include "video_core/engines/shader_type.h"
27#include "video_core/memory_manager.h" 27#include "video_core/memory_manager.h"
28#include "video_core/renderer_opengl/gl_query_cache.h"
28#include "video_core/renderer_opengl/gl_rasterizer.h" 29#include "video_core/renderer_opengl/gl_rasterizer.h"
29#include "video_core/renderer_opengl/gl_shader_cache.h" 30#include "video_core/renderer_opengl/gl_shader_cache.h"
30#include "video_core/renderer_opengl/gl_shader_gen.h" 31#include "video_core/renderer_opengl/gl_shader_gen.h"
@@ -92,8 +93,8 @@ std::size_t GetConstBufferSize(const Tegra::Engines::ConstBufferInfo& buffer,
92RasterizerOpenGL::RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWindow& emu_window, 93RasterizerOpenGL::RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWindow& emu_window,
93 ScreenInfo& info) 94 ScreenInfo& info)
94 : RasterizerAccelerated{system.Memory()}, texture_cache{system, *this, device}, 95 : RasterizerAccelerated{system.Memory()}, texture_cache{system, *this, device},
95 shader_cache{*this, system, emu_window, device}, system{system}, screen_info{info}, 96 shader_cache{*this, system, emu_window, device}, query_cache{system, *this}, system{system},
96 buffer_cache{*this, system, device, STREAM_BUFFER_SIZE} { 97 screen_info{info}, buffer_cache{*this, system, device, STREAM_BUFFER_SIZE} {
97 shader_program_manager = std::make_unique<GLShader::ProgramManager>(); 98 shader_program_manager = std::make_unique<GLShader::ProgramManager>();
98 state.draw.shader_program = 0; 99 state.draw.shader_program = 0;
99 state.Apply(); 100 state.Apply();
@@ -548,9 +549,9 @@ void RasterizerOpenGL::Clear() {
548void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) { 549void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) {
549 MICROPROFILE_SCOPE(OpenGL_Drawing); 550 MICROPROFILE_SCOPE(OpenGL_Drawing);
550 auto& gpu = system.GPU().Maxwell3D(); 551 auto& gpu = system.GPU().Maxwell3D();
551
552 const auto& regs = gpu.regs; 552 const auto& regs = gpu.regs;
553 samples_passed.UpdateState(regs.samplecnt_enable); 553
554 query_cache.UpdateCounters();
554 555
555 SyncRasterizeEnable(state); 556 SyncRasterizeEnable(state);
556 SyncColorMask(); 557 SyncColorMask();
@@ -718,24 +719,11 @@ void RasterizerOpenGL::DispatchCompute(GPUVAddr code_addr) {
718} 719}
719 720
720void RasterizerOpenGL::ResetCounter(VideoCore::QueryType type) { 721void RasterizerOpenGL::ResetCounter(VideoCore::QueryType type) {
721 switch (type) { 722 query_cache.ResetCounter(type);
722 case VideoCore::QueryType::SamplesPassed:
723 samples_passed.Reset();
724 break;
725 default:
726 UNIMPLEMENTED_MSG("type={}", static_cast<u32>(type));
727 break;
728 }
729} 723}
730 724
731u64 RasterizerOpenGL::Query(VideoCore::QueryType type) { 725void RasterizerOpenGL::Query(GPUVAddr gpu_addr, VideoCore::QueryType type) {
732 switch (type) { 726 query_cache.Query(gpu_addr, type);
733 case VideoCore::QueryType::SamplesPassed:
734 return samples_passed.Query();
735 default:
736 UNIMPLEMENTED_MSG("type={}", static_cast<u32>(type));
737 return 1;
738 }
739} 727}
740 728
741void RasterizerOpenGL::FlushAll() {} 729void RasterizerOpenGL::FlushAll() {}
@@ -747,6 +735,7 @@ void RasterizerOpenGL::FlushRegion(CacheAddr addr, u64 size) {
747 } 735 }
748 texture_cache.FlushRegion(addr, size); 736 texture_cache.FlushRegion(addr, size);
749 buffer_cache.FlushRegion(addr, size); 737 buffer_cache.FlushRegion(addr, size);
738 query_cache.FlushRegion(addr, size);
750} 739}
751 740
752void RasterizerOpenGL::InvalidateRegion(CacheAddr addr, u64 size) { 741void RasterizerOpenGL::InvalidateRegion(CacheAddr addr, u64 size) {
@@ -757,6 +746,7 @@ void RasterizerOpenGL::InvalidateRegion(CacheAddr addr, u64 size) {
757 texture_cache.InvalidateRegion(addr, size); 746 texture_cache.InvalidateRegion(addr, size);
758 shader_cache.InvalidateRegion(addr, size); 747 shader_cache.InvalidateRegion(addr, size);
759 buffer_cache.InvalidateRegion(addr, size); 748 buffer_cache.InvalidateRegion(addr, size);
749 query_cache.InvalidateRegion(addr, size);
760} 750}
761 751
762void RasterizerOpenGL::FlushAndInvalidateRegion(CacheAddr addr, u64 size) { 752void RasterizerOpenGL::FlushAndInvalidateRegion(CacheAddr addr, u64 size) {
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index 857a6c073..4fb6811a7 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -63,7 +63,7 @@ public:
63 void Clear() override; 63 void Clear() override;
64 void DispatchCompute(GPUVAddr code_addr) override; 64 void DispatchCompute(GPUVAddr code_addr) override;
65 void ResetCounter(VideoCore::QueryType type) override; 65 void ResetCounter(VideoCore::QueryType type) override;
66 u64 Query(VideoCore::QueryType type) override; 66 void Query(GPUVAddr gpu_addr, VideoCore::QueryType type) override;
67 void FlushAll() override; 67 void FlushAll() override;
68 void FlushRegion(CacheAddr addr, u64 size) override; 68 void FlushRegion(CacheAddr addr, u64 size) override;
69 void InvalidateRegion(CacheAddr addr, u64 size) override; 69 void InvalidateRegion(CacheAddr addr, u64 size) override;
@@ -78,6 +78,11 @@ public:
78 void LoadDiskResources(const std::atomic_bool& stop_loading, 78 void LoadDiskResources(const std::atomic_bool& stop_loading,
79 const VideoCore::DiskResourceLoadCallback& callback) override; 79 const VideoCore::DiskResourceLoadCallback& callback) override;
80 80
81 /// Returns true when there are commands queued to the OpenGL server.
82 bool AnyCommandQueued() const {
83 return num_queued_commands > 0;
84 }
85
81private: 86private:
82 /// Configures the color and depth framebuffer states. 87 /// Configures the color and depth framebuffer states.
83 void ConfigureFramebuffers(); 88 void ConfigureFramebuffers();
@@ -207,6 +212,7 @@ private:
207 ShaderCacheOpenGL shader_cache; 212 ShaderCacheOpenGL shader_cache;
208 SamplerCacheOpenGL sampler_cache; 213 SamplerCacheOpenGL sampler_cache;
209 FramebufferCacheOpenGL framebuffer_cache; 214 FramebufferCacheOpenGL framebuffer_cache;
215 QueryCache query_cache;
210 216
211 Core::System& system; 217 Core::System& system;
212 ScreenInfo& screen_info; 218 ScreenInfo& screen_info;
@@ -224,8 +230,6 @@ private:
224 BindBuffersRangePushBuffer bind_ubo_pushbuffer{GL_UNIFORM_BUFFER}; 230 BindBuffersRangePushBuffer bind_ubo_pushbuffer{GL_UNIFORM_BUFFER};
225 BindBuffersRangePushBuffer bind_ssbo_pushbuffer{GL_SHADER_STORAGE_BUFFER}; 231 BindBuffersRangePushBuffer bind_ssbo_pushbuffer{GL_SHADER_STORAGE_BUFFER};
226 232
227 HostCounter samples_passed{GL_SAMPLES_PASSED};
228
229 /// Number of commands queued to the OpenGL driver. Reseted on flush. 233 /// Number of commands queued to the OpenGL driver. Reseted on flush.
230 std::size_t num_queued_commands = 0; 234 std::size_t num_queued_commands = 0;
231}; 235};