Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(109)

Side by Side Diff: gpu/command_buffer/service/query_manager.cc

Issue 9694025: Add support for GL_COMMANDS_ISSUED_CHROMIUM fence like query. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: add cast for std::min Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "gpu/command_buffer/service/query_manager.h" 5 #include "gpu/command_buffer/service/query_manager.h"
6 #include "base/atomicops.h" 6 #include "base/atomicops.h"
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/time.h"
8 #include "gpu/command_buffer/common/gles2_cmd_format.h" 9 #include "gpu/command_buffer/common/gles2_cmd_format.h"
9 #include "gpu/command_buffer/service/common_decoder.h" 10 #include "gpu/command_buffer/service/common_decoder.h"
10 11
11 namespace gpu { 12 namespace gpu {
12 namespace gles2 { 13 namespace gles2 {
13 14
14 QueryManager::QueryManager() 15 class AllSamplesPassedQuery : public QueryManager::Query {
15 : query_count_(0) { 16 public:
17 AllSamplesPassedQuery(
18 QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset,
19 GLuint service_id);
20 virtual ~AllSamplesPassedQuery();
21 virtual bool Begin() OVERRIDE;
22 virtual bool End(uint32 submit_count) OVERRIDE;
23 virtual bool Process() OVERRIDE;
24 virtual void Destroy(bool have_context) OVERRIDE;
25
26 private:
27 // Service side query id.
28 GLuint service_id_;
29 };
30
31 AllSamplesPassedQuery::AllSamplesPassedQuery(
32 QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset,
33 GLuint service_id)
34 : Query(manager, target, shm_id, shm_offset),
35 service_id_(service_id) {
36 }
37
38 AllSamplesPassedQuery::~AllSamplesPassedQuery() {
39 }
40
41 void AllSamplesPassedQuery::Destroy(bool have_context) {
42 if (have_context && !IsDeleted()) {
43 glDeleteQueriesARB(1, &service_id_);
44 MarkAsDeleted();
45 }
46 }
47
48 bool AllSamplesPassedQuery::Begin() {
49 BeginQueryHelper(target(), service_id_);
50 return true;
51 }
52
53 bool AllSamplesPassedQuery::End(uint32 submit_count) {
54 EndQueryHelper(target());
55 return AddToPendingQueue(submit_count);
56 }
57
58 bool AllSamplesPassedQuery::Process() {
59 GLuint available = 0;
60 glGetQueryObjectuivARB(
61 service_id_, GL_QUERY_RESULT_AVAILABLE_EXT, &available);
62 if (!available) {
63 return true;
64 }
65 GLuint result = 0;
66 glGetQueryObjectuivARB(
67 service_id_, GL_QUERY_RESULT_EXT, &result);
68
69 return MarkAsCompleted(result);
70 }
71
72 class CommandsIssuedQuery : public QueryManager::Query {
73 public:
74 CommandsIssuedQuery(
75 QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset);
76 virtual ~CommandsIssuedQuery();
77
78 virtual bool Begin() OVERRIDE;
79 virtual bool End(uint32 submit_count) OVERRIDE;
80 virtual bool Process() OVERRIDE;
81 virtual void Destroy(bool have_context) OVERRIDE;
82
83 private:
84 base::TimeTicks begin_time_;
85 };
86
87 CommandsIssuedQuery::CommandsIssuedQuery(
88 QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset)
89 : Query(manager, target, shm_id, shm_offset) {
90 }
91
92 CommandsIssuedQuery::~CommandsIssuedQuery() {
93 }
94
95 bool CommandsIssuedQuery::Process() {
96 NOTREACHED();
97 return true;
98 }
99
100 bool CommandsIssuedQuery::Begin() {
101 begin_time_ = base::TimeTicks::HighResNow();
102 return true;
103 }
104
105 bool CommandsIssuedQuery::End(uint32 submit_count) {
106 base::TimeDelta elapsed = base::TimeTicks::HighResNow() - begin_time_;
107 MarkAsPending(submit_count);
108 return MarkAsCompleted(
109 std::min(elapsed.InMicroseconds(), static_cast<int64>(0xFFFFFFFFL)));
110 }
111
112 void CommandsIssuedQuery::Destroy(bool /* have_context */) {
113 if (!IsDeleted()) {
114 MarkAsDeleted();
115 }
116 }
117
118 QueryManager::QueryManager(
119 CommonDecoder* decoder,
120 bool use_arb_occlusion_query2_for_occlusion_query_boolean)
121 : decoder_(decoder),
122 use_arb_occlusion_query2_for_occlusion_query_boolean_(
123 use_arb_occlusion_query2_for_occlusion_query_boolean),
124 query_count_(0) {
16 } 125 }
17 126
18 QueryManager::~QueryManager() { 127 QueryManager::~QueryManager() {
19 DCHECK(queries_.empty()); 128 DCHECK(queries_.empty());
20 129
21 // If this triggers, that means something is keeping a reference to 130 // If this triggers, that means something is keeping a reference to
22 // a Query belonging to this. 131 // a Query belonging to this.
23 CHECK_EQ(query_count_, 0u); 132 CHECK_EQ(query_count_, 0u);
24 } 133 }
25 134
26 void QueryManager::Destroy(bool have_context) { 135 void QueryManager::Destroy(bool have_context) {
27 pending_queries_.clear(); 136 pending_queries_.clear();
28 while (!queries_.empty()) { 137 while (!queries_.empty()) {
29 Query* query = queries_.begin()->second; 138 Query* query = queries_.begin()->second;
30 if (have_context) { 139 query->Destroy(have_context);
31 if (!query->IsDeleted()) {
32 GLuint service_id = query->service_id();
33 glDeleteQueriesARB(1, &service_id);
34 query->MarkAsDeleted();
35 }
36 }
37 queries_.erase(queries_.begin()); 140 queries_.erase(queries_.begin());
38 } 141 }
39 } 142 }
40 143
41 QueryManager::Query* QueryManager::CreateQuery( 144 QueryManager::Query* QueryManager::CreateQuery(
42 GLuint client_id, 145 GLenum target, GLuint client_id, int32 shm_id, uint32 shm_offset) {
43 GLuint service_id) { 146 Query::Ref query;
44 Query::Ref query(new Query(this, service_id)); 147 switch (target) {
148 case GL_COMMANDS_ISSUED_CHROMIUM:
149 query = new CommandsIssuedQuery(this, target, shm_id, shm_offset);
150 break;
151 default: {
152 GLuint service_id = 0;
153 glGenQueriesARB(1, &service_id);
154 DCHECK_NE(0u, service_id);
155 query = new AllSamplesPassedQuery(
156 this, target, shm_id, shm_offset, service_id);
157 break;
158 }
159 }
45 std::pair<QueryMap::iterator, bool> result = 160 std::pair<QueryMap::iterator, bool> result =
46 queries_.insert(std::make_pair(client_id, query)); 161 queries_.insert(std::make_pair(client_id, query));
47 DCHECK(result.second); 162 DCHECK(result.second);
48 return query.get(); 163 return query.get();
49 } 164 }
50 165
51 QueryManager::Query* QueryManager::GetQuery( 166 QueryManager::Query* QueryManager::GetQuery(
52 GLuint client_id) { 167 GLuint client_id) {
53 QueryMap::iterator it = queries_.find(client_id); 168 QueryMap::iterator it = queries_.find(client_id);
54 return it != queries_.end() ? it->second : NULL; 169 return it != queries_.end() ? it->second : NULL;
(...skipping 10 matching lines...) Expand all
65 } 180 }
66 181
67 void QueryManager::StartTracking(QueryManager::Query* /* query */) { 182 void QueryManager::StartTracking(QueryManager::Query* /* query */) {
68 ++query_count_; 183 ++query_count_;
69 } 184 }
70 185
71 void QueryManager::StopTracking(QueryManager::Query* /* query */) { 186 void QueryManager::StopTracking(QueryManager::Query* /* query */) {
72 --query_count_; 187 --query_count_;
73 } 188 }
74 189
190 void QueryManager::BeginQueryHelper(GLenum target, GLuint id) {
191 // ARB_occlusion_query2 does not have a GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT
192 // target.
193 if (use_arb_occlusion_query2_for_occlusion_query_boolean_) {
194 target = GL_ANY_SAMPLES_PASSED_EXT;
195 }
196 glBeginQueryARB(target, id);
197 }
198
199 void QueryManager::EndQueryHelper(GLenum target) {
200 // ARB_occlusion_query2 does not have a GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT
201 // target.
202 if (use_arb_occlusion_query2_for_occlusion_query_boolean_) {
203 target = GL_ANY_SAMPLES_PASSED_EXT;
204 }
205 glEndQueryARB(target);
206 }
207
75 QueryManager::Query::Query( 208 QueryManager::Query::Query(
76 QueryManager* manager, 209 QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset)
77 GLuint service_id)
78 : manager_(manager), 210 : manager_(manager),
79 service_id_(service_id), 211 target_(target),
80 target_(0), 212 shm_id_(shm_id),
81 shm_id_(0), 213 shm_offset_(shm_offset),
82 shm_offset_(0),
83 submit_count_(0), 214 submit_count_(0),
84 pending_(false) { 215 pending_(false),
216 deleted_(false) {
85 DCHECK(manager); 217 DCHECK(manager);
86 manager_->StartTracking(this); 218 manager_->StartTracking(this);
87 } 219 }
88 220
89 QueryManager::Query::~Query() { 221 QueryManager::Query::~Query() {
90 if (manager_) { 222 if (manager_) {
91 manager_->StopTracking(this); 223 manager_->StopTracking(this);
92 manager_ = NULL; 224 manager_ = NULL;
93 } 225 }
94 } 226 }
95 227
96 void QueryManager::Query::Initialize( 228 bool QueryManager::Query::MarkAsCompleted(GLuint result) {
97 GLenum target, int32 shm_id, uint32 shm_offset) { 229 DCHECK(pending_);
98 DCHECK(!IsInitialized()); 230 QuerySync* sync = manager_->decoder_->GetSharedMemoryAs<QuerySync*>(
99 target_ = target; 231 shm_id_, shm_offset_, sizeof(*sync));
100 shm_id_ = shm_id; 232 if (!sync) {
101 shm_offset_ = shm_offset; 233 return false;
234 }
235
236 pending_ = false;
237 sync->result = result;
238 // Need a MemoryBarrier here so that sync->result is written before
239 // sync->process_count.
240 base::subtle::MemoryBarrier();
241 sync->process_count = submit_count_;
242
243 return true;
102 } 244 }
103 245
104 bool QueryManager::GetClientId(GLuint service_id, GLuint* client_id) const { 246 bool QueryManager::ProcessPendingQueries() {
105 DCHECK(client_id); 247 while (!pending_queries_.empty()) {
106 // This doesn't need to be fast. It's only used during slow queries. 248 Query* query = pending_queries_.front().get();
107 for (QueryMap::const_iterator it = queries_.begin(); 249 if (!query->Process()) {
108 it != queries_.end(); ++it) { 250 return false;
109 if (it->second->service_id() == service_id) { 251 }
110 *client_id = it->first; 252 if (query->pending()) {
111 return true; 253 return true;
112 } 254 }
113 }
114 return false;
115 }
116
117 bool QueryManager::ProcessPendingQueries(CommonDecoder* decoder) {
118 DCHECK(decoder);
119 while (!pending_queries_.empty()) {
120 Query* query = pending_queries_.front().get();
121 GLuint available = 0;
122 glGetQueryObjectuivARB(
123 query->service_id(), GL_QUERY_RESULT_AVAILABLE_EXT, &available);
124 if (!available) {
125 return true;
126 }
127 GLuint result = 0;
128 glGetQueryObjectuivARB(
129 query->service_id(), GL_QUERY_RESULT_EXT, &result);
130 QuerySync* sync = decoder->GetSharedMemoryAs<QuerySync*>(
131 query->shm_id(), query->shm_offset(), sizeof(*sync));
132 if (!sync) {
133 return false;
134 }
135
136 sync->result = result;
137 // Need a MemoryBarrier here so that sync->result is written before
138 // sync->process_count.
139 base::subtle::MemoryBarrier();
140 sync->process_count = query->submit_count();
141
142 query->MarkAsCompleted();
143 pending_queries_.pop_front(); 255 pending_queries_.pop_front();
144 } 256 }
145 257
146 return true; 258 return true;
147 } 259 }
148 260
149 bool QueryManager::HavePendingQueries() { 261 bool QueryManager::HavePendingQueries() {
150 return !pending_queries_.empty(); 262 return !pending_queries_.empty();
151 } 263 }
152 264
153 void QueryManager::AddPendingQuery(Query* query, uint32 submit_count) { 265 bool QueryManager::AddPendingQuery(Query* query, uint32 submit_count) {
154 DCHECK(query); 266 DCHECK(query);
155 DCHECK(query->IsInitialized());
156 DCHECK(!query->IsDeleted()); 267 DCHECK(!query->IsDeleted());
157 RemovePendingQuery(query); 268 if (!RemovePendingQuery(query)) {
269 return false;
270 }
158 query->MarkAsPending(submit_count); 271 query->MarkAsPending(submit_count);
159 pending_queries_.push_back(query); 272 pending_queries_.push_back(query);
273 return true;
160 } 274 }
161 275
162 void QueryManager::RemovePendingQuery(Query* query) { 276 bool QueryManager::RemovePendingQuery(Query* query) {
163 DCHECK(query); 277 DCHECK(query);
164 if (query->pending()) { 278 if (query->pending()) {
165 // TODO(gman): Speed this up if this is a common operation. This would only 279 // TODO(gman): Speed this up if this is a common operation. This would only
166 // happen if you do being/end begin/end on the same query without waiting 280 // happen if you do being/end begin/end on the same query without waiting
167 // for the first one to finish. 281 // for the first one to finish.
168 for (QueryQueue::iterator it = pending_queries_.begin(); 282 for (QueryQueue::iterator it = pending_queries_.begin();
169 it != pending_queries_.end(); ++it) { 283 it != pending_queries_.end(); ++it) {
170 if (it->get() == query) { 284 if (it->get() == query) {
171 pending_queries_.erase(it); 285 pending_queries_.erase(it);
172 break; 286 break;
173 } 287 }
174 } 288 }
175 query->MarkAsCompleted(); 289 if (!query->MarkAsCompleted(0)) {
290 return false;
291 }
176 } 292 }
293 return true;
294 }
295
296 bool QueryManager::BeginQuery(Query* query) {
297 DCHECK(query);
298 if (!RemovePendingQuery(query)) {
299 return false;
300 }
301 return query->Begin();
302 }
303
304 bool QueryManager::EndQuery(Query* query, uint32 submit_count) {
305 DCHECK(query);
306 if (!RemovePendingQuery(query)) {
307 return false;
308 }
309 return query->End(submit_count);
177 } 310 }
178 311
179 } // namespace gles2 312 } // namespace gles2
180 } // namespace gpu 313 } // namespace gpu
181 314
182 315
OLDNEW
« no previous file with comments | « gpu/command_buffer/service/query_manager.h ('k') | gpu/command_buffer/service/query_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698