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

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

Issue 509723002: Added support for GPU Tracing on mobile devices which support it. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixed another gpu tracer unittest issue Created 6 years, 3 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
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/gpu_tracer.h" 5 #include "gpu/command_buffer/service/gpu_tracer.h"
6 6
7 #include <deque> 7 #include <deque>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/debug/trace_event.h" 10 #include "base/debug/trace_event.h"
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
52 start_time); 52 start_time);
53 TRACE_EVENT_COPY_END_WITH_ID_TID_AND_TIMESTAMP0( 53 TRACE_EVENT_COPY_END_WITH_ID_TID_AND_TIMESTAMP0(
54 TRACE_DISABLED_BY_DEFAULT("gpu.device"), 54 TRACE_DISABLED_BY_DEFAULT("gpu.device"),
55 name.c_str(), 55 name.c_str(),
56 local_trace_id_, 56 local_trace_id_,
57 named_thread_.thread_id(), 57 named_thread_.thread_id(),
58 end_time); 58 end_time);
59 ++local_trace_id_; 59 ++local_trace_id_;
60 } 60 }
61 61
62 GPUTrace::GPUTrace(const std::string& name)
63 : name_(name),
64 outputter_(NULL),
65 offset_(0),
66 end_time_(0),
67 end_requested_(false),
68 enabled_(false) {
69 }
70
71 GPUTrace::GPUTrace(scoped_refptr<Outputter> outputter, 62 GPUTrace::GPUTrace(scoped_refptr<Outputter> outputter,
72 const std::string& name, 63 const std::string& name,
73 int64 offset) 64 int64 offset,
65 GpuTracerType tracer_type)
74 : name_(name), 66 : name_(name),
75 outputter_(outputter), 67 outputter_(outputter),
76 offset_(offset), 68 offset_(offset),
77 start_time_(0), 69 start_time_(0),
78 end_time_(0), 70 end_time_(0),
79 end_requested_(false), 71 tracer_type_(tracer_type),
80 enabled_(true) { 72 end_requested_(false) {
81 glGenQueries(2, queries_); 73 memset(queries_, 0, sizeof(queries_));
74 switch (tracer_type_) {
75 case kTracerTypeARBTimer:
76 case kTracerTypeDisjointTimer:
77 glGenQueriesARB(2, queries_);
78 break;
79
80 default:
81 tracer_type_ = kTracerTypeInvalid;
82 }
82 } 83 }
83 84
84 GPUTrace::~GPUTrace() { 85 GPUTrace::~GPUTrace() {
85 if (enabled_) 86 switch (tracer_type_) {
86 glDeleteQueries(2, queries_); 87 case kTracerTypeInvalid:
88 break;
89
90 case kTracerTypeARBTimer:
91 case kTracerTypeDisjointTimer:
92 glDeleteQueriesARB(2, queries_);
93 break;
94 }
87 } 95 }
88 96
89 void GPUTrace::Start() { 97 void GPUTrace::Start() {
90 TRACE_EVENT_COPY_ASYNC_BEGIN0( 98 TRACE_EVENT_COPY_ASYNC_BEGIN0(
91 TRACE_DISABLED_BY_DEFAULT("gpu.service"), name().c_str(), this); 99 TRACE_DISABLED_BY_DEFAULT("gpu.service"), name().c_str(), this);
92 if (enabled_) { 100
93 glQueryCounter(queries_[0], GL_TIMESTAMP); 101 switch (tracer_type_) {
102 case kTracerTypeInvalid:
103 break;
104
105 case kTracerTypeARBTimer:
106 glQueryCounter(queries_[0], GL_TIMESTAMP);
107 break;
108 case kTracerTypeDisjointTimer:
109 glQueryCounter(queries_[0], GL_TIMESTAMP_EXT);
piman 2014/09/02 18:41:44 nit: GL_TIMESTAMP_EXT and GL_TIMESTAMP have the sa
David Yen 2014/09/02 18:45:36 I noticed that as well, but I wanted to follow the
David Yen 2014/09/02 22:03:55 Done.
110 break;
94 } 111 }
95 } 112 }
96 113
97 void GPUTrace::End() { 114 void GPUTrace::End() {
98 if (enabled_) { 115 end_requested_ = true;
99 glQueryCounter(queries_[1], GL_TIMESTAMP); 116 switch (tracer_type_) {
100 end_requested_ = true; 117 case kTracerTypeInvalid:
118 break;
119
120 case kTracerTypeARBTimer:
121 glQueryCounter(queries_[1], GL_TIMESTAMP);
122 break;
123 case kTracerTypeDisjointTimer:
124 glQueryCounter(queries_[1], GL_TIMESTAMP_EXT);
piman 2014/09/02 18:41:44 nit: same here
David Yen 2014/09/02 22:03:55 Done.
125 break;
101 } 126 }
102 127
103 TRACE_EVENT_COPY_ASYNC_END0( 128 TRACE_EVENT_COPY_ASYNC_END0(
104 TRACE_DISABLED_BY_DEFAULT("gpu.service"), name().c_str(), this); 129 TRACE_DISABLED_BY_DEFAULT("gpu.service"), name().c_str(), this);
105 } 130 }
106 131
107 bool GPUTrace::IsAvailable() { 132 bool GPUTrace::IsAvailable() {
108 if (!enabled_) 133 if (tracer_type_ != kTracerTypeInvalid) {
109 return true; 134 if (!end_requested_)
110 else if (!end_requested_) 135 return false;
111 return false;
112 136
113 GLint done = 0; 137 GLint done = 0;
114 glGetQueryObjectiv(queries_[1], GL_QUERY_RESULT_AVAILABLE, &done); 138
115 return !!done; 139 switch (tracer_type_) {
140 case kTracerTypeARBTimer:
141 glGetQueryObjectiv(queries_[1], GL_QUERY_RESULT_AVAILABLE, &done);
142 break;
143
144 case kTracerTypeDisjointTimer:
145 glGetQueryObjectivARB(queries_[1], GL_QUERY_RESULT_AVAILABLE_EXT,
146 &done);
piman 2014/09/02 18:41:44 Same here with GL_QUERY_RESULT_AVAILABLE_EXT vs GL
David Yen 2014/09/02 22:03:55 Done.
147 break;
148
149 default:
150 done = 1;
151 break;
152 }
153
154 return !!done;
155 }
156
157 return true;
116 } 158 }
117 159
118 void GPUTrace::Process() { 160 void GPUTrace::Process() {
119 if (!enabled_) 161 if (tracer_type_ == kTracerTypeInvalid)
120 return; 162 return;
121 163
122 DCHECK(IsAvailable()); 164 DCHECK(IsAvailable());
123 165
124 GLuint64 timestamp; 166 GLuint64 begin_stamp = 0;
167 GLuint64 end_stamp = 0;
125 168
126 // TODO(dsinclair): It's possible for the timer to wrap during the start/end. 169 // TODO(dsinclair): It's possible for the timer to wrap during the start/end.
127 // We need to detect if the end is less then the start and correct for the 170 // We need to detect if the end is less then the start and correct for the
128 // wrapping. 171 // wrapping.
129 glGetQueryObjectui64v(queries_[0], GL_QUERY_RESULT, &timestamp); 172 switch (tracer_type_) {
130 start_time_ = (timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_; 173 case kTracerTypeARBTimer:
174 glGetQueryObjectui64v(queries_[0], GL_QUERY_RESULT, &begin_stamp);
175 glGetQueryObjectui64v(queries_[1], GL_QUERY_RESULT, &end_stamp);
176 break;
177 case kTracerTypeDisjointTimer:
178 glGetQueryObjectui64vEXT(queries_[0], GL_QUERY_RESULT_EXT, &begin_stamp);
179 glGetQueryObjectui64vEXT(queries_[1], GL_QUERY_RESULT_EXT, &end_stamp);
piman 2014/09/02 18:41:44 nit: can we collapse those as well?
David Yen 2014/09/02 18:45:36 When I collapsed these, it actually started to cra
David Yen 2014/09/02 22:03:55 Re-did this and the crashing no longer happens, mu
180 break;
131 181
132 glGetQueryObjectui64v(queries_[1], GL_QUERY_RESULT, &timestamp); 182 default:
133 end_time_ = (timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_; 183 return;
184 }
134 185
135 glDeleteQueries(2, queries_); 186 start_time_ = (begin_stamp / base::Time::kNanosecondsPerMicrosecond) +
187 offset_;
188 end_time_ = (end_stamp / base::Time::kNanosecondsPerMicrosecond) + offset_;
136 outputter_->Trace(name(), start_time_, end_time_); 189 outputter_->Trace(name(), start_time_, end_time_);
137 } 190 }
138 191
139 GPUTracer::GPUTracer(gles2::GLES2Decoder* decoder) 192 GPUTracer::GPUTracer(gles2::GLES2Decoder* decoder)
140 : gpu_trace_srv_category(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED( 193 : gpu_trace_srv_category(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
141 TRACE_DISABLED_BY_DEFAULT("gpu.service"))), 194 TRACE_DISABLED_BY_DEFAULT("gpu.service"))),
142 gpu_trace_dev_category(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED( 195 gpu_trace_dev_category(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
143 TRACE_DISABLED_BY_DEFAULT("gpu.device"))), 196 TRACE_DISABLED_BY_DEFAULT("gpu.device"))),
144 decoder_(decoder), 197 decoder_(decoder),
145 timer_offset_(0), 198 timer_offset_(0),
146 last_tracer_source_(kTraceGroupInvalid), 199 last_tracer_source_(kTraceGroupInvalid),
147 enabled_(false), 200 tracer_type_(kTracerTypeInvalid),
148 gpu_timing_synced_(false), 201 gpu_timing_synced_(false),
149 gpu_executing_(false), 202 gpu_executing_(false),
150 process_posted_(false) { 203 process_posted_(false) {
151 if (gfx::g_driver_gl.ext.b_GL_ARB_timer_query) { 204 if (gfx::g_driver_gl.ext.b_GL_EXT_disjoint_timer_query) {
205 tracer_type_ = kTracerTypeDisjointTimer;
206 outputter_ = TraceOutputter::Create("GL_EXT_disjoint_timer_query");
207 } else if (gfx::g_driver_gl.ext.b_GL_ARB_timer_query) {
208 tracer_type_ = kTracerTypeARBTimer;
152 outputter_ = TraceOutputter::Create("GL_ARB_timer_query"); 209 outputter_ = TraceOutputter::Create("GL_ARB_timer_query");
153 enabled_ = true;
154 } 210 }
155 } 211 }
156 212
157 GPUTracer::~GPUTracer() { 213 GPUTracer::~GPUTracer() {
158 } 214 }
159 215
160 bool GPUTracer::BeginDecoding() { 216 bool GPUTracer::BeginDecoding() {
161 if (enabled_) {
162 if (*gpu_trace_dev_category) {
163 // Make sure timing is synced before tracing
164 if (!gpu_timing_synced_) {
165 CalculateTimerOffset();
166 gpu_timing_synced_ = true;
167 }
168 } else {
169 // If GPU device category is off, invalidate timing sync
170 gpu_timing_synced_ = false;
171 }
172 }
173
174 if (gpu_executing_) 217 if (gpu_executing_)
175 return false; 218 return false;
176 219
220 CalculateTimerOffset();
177 gpu_executing_ = true; 221 gpu_executing_ = true;
178 222
179 if (IsTracing()) { 223 if (IsTracing()) {
224 // Reset disjoint bit for the disjoint timer.
225 if (tracer_type_ == kTracerTypeDisjointTimer) {
226 GLint disjoint_value = 0;
227 glGetIntegerv(GL_GPU_DISJOINT_EXT, &disjoint_value);
228 }
229
180 // Begin a Trace for all active markers 230 // Begin a Trace for all active markers
181 for (int n = 0; n < NUM_TRACER_SOURCES; n++) { 231 for (int n = 0; n < NUM_TRACER_SOURCES; n++) {
182 for (size_t i = 0; i < markers_[n].size(); i++) { 232 for (size_t i = 0; i < markers_[n].size(); i++) {
183 markers_[n][i].trace_ = CreateTrace(markers_[n][i].name_); 233 markers_[n][i].trace_ = CreateTrace(markers_[n][i].name_);
184 markers_[n][i].trace_->Start(); 234 markers_[n][i].trace_->Start();
185 } 235 }
186 } 236 }
187 } 237 }
188 return true; 238 return true;
189 } 239 }
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
265 const std::string& GPUTracer::CurrentName() const { 315 const std::string& GPUTracer::CurrentName() const {
266 if (last_tracer_source_ >= 0 && 316 if (last_tracer_source_ >= 0 &&
267 last_tracer_source_ < NUM_TRACER_SOURCES && 317 last_tracer_source_ < NUM_TRACER_SOURCES &&
268 !markers_[last_tracer_source_].empty()) { 318 !markers_[last_tracer_source_].empty()) {
269 return markers_[last_tracer_source_].back().name_; 319 return markers_[last_tracer_source_].back().name_;
270 } 320 }
271 return base::EmptyString(); 321 return base::EmptyString();
272 } 322 }
273 323
274 scoped_refptr<GPUTrace> GPUTracer::CreateTrace(const std::string& name) { 324 scoped_refptr<GPUTrace> GPUTracer::CreateTrace(const std::string& name) {
275 if (enabled_ && *gpu_trace_dev_category) 325 GpuTracerType tracer_type = *gpu_trace_dev_category ? tracer_type_ :
276 return new GPUTrace(outputter_, name, timer_offset_); 326 kTracerTypeInvalid;
277 else 327
278 return new GPUTrace(name); 328 return new GPUTrace(outputter_, name, timer_offset_, tracer_type);
279 } 329 }
280 330
281 void GPUTracer::Process() { 331 void GPUTracer::Process() {
282 process_posted_ = false; 332 process_posted_ = false;
283 ProcessTraces(); 333 ProcessTraces();
284 IssueProcessTask(); 334 IssueProcessTask();
285 } 335 }
286 336
287 void GPUTracer::ProcessTraces() { 337 void GPUTracer::ProcessTraces() {
288 if (!enabled_) { 338 if (tracer_type_ == kTracerTypeInvalid) {
289 while (!traces_.empty() && traces_.front()->IsAvailable()) { 339 traces_.clear();
290 traces_.front()->Process();
291 traces_.pop_front();
292 }
293 return; 340 return;
294 } 341 }
295 342
296 TRACE_EVENT0("gpu", "GPUTracer::ProcessTraces"); 343 TRACE_EVENT0("gpu", "GPUTracer::ProcessTraces");
297 344
298 // Make owning decoder's GL context current 345 // Make owning decoder's GL context current
299 if (!decoder_->MakeCurrent()) { 346 if (!decoder_->MakeCurrent()) {
300 // Skip subsequent GL calls if MakeCurrent fails 347 // Skip subsequent GL calls if MakeCurrent fails
301 traces_.clear(); 348 traces_.clear();
302 return; 349 return;
303 } 350 }
304 351
352 // Check if disjoint operation has occurred, discard ongoing traces if so.
353 if (tracer_type_ == kTracerTypeDisjointTimer) {
354 GLint disjoint_value = 0;
355 glGetIntegerv(GL_GPU_DISJOINT_EXT, &disjoint_value);
356 if (disjoint_value)
357 traces_.clear();
358 }
359
305 while (!traces_.empty() && traces_.front()->IsAvailable()) { 360 while (!traces_.empty() && traces_.front()->IsAvailable()) {
306 traces_.front()->Process(); 361 traces_.front()->Process();
307 traces_.pop_front(); 362 traces_.pop_front();
308 } 363 }
309 364
310 // Clear pending traces if there were are any errors 365 // Clear pending traces if there were are any errors
311 GLenum err = glGetError(); 366 GLenum err = glGetError();
312 if (err != GL_NO_ERROR) 367 if (err != GL_NO_ERROR)
313 traces_.clear(); 368 traces_.clear();
314 } 369 }
315 370
316 void GPUTracer::CalculateTimerOffset() { 371 void GPUTracer::CalculateTimerOffset() {
317 if (enabled_) { 372 if (tracer_type_ != kTracerTypeInvalid) {
373 // If GPU device category is off, invalidate timing sync.
374 if (*gpu_trace_dev_category == '\0') {
375 gpu_timing_synced_ = false;
376 return;
377 }
378
379 if (gpu_timing_synced_)
380 return;
381
318 TRACE_EVENT0("gpu", "GPUTracer::CalculateTimerOffset"); 382 TRACE_EVENT0("gpu", "GPUTracer::CalculateTimerOffset");
319 383
320 // NOTE(vmiura): It would be better to use glGetInteger64v, however 384 // NOTE(vmiura): It would be better to use glGetInteger64v, however
321 // it's not available everywhere. 385 // it's not available everywhere.
322 GLuint64 gl_now = 0; 386 GLuint64 gl_now = 0;
323 GLuint query; 387 GLuint query;
324 glFinish(); 388 GLint disjoint_value = 0;
325 glGenQueries(1, &query); 389
326 glQueryCounter(query, GL_TIMESTAMP); 390 switch (tracer_type_) {
327 glFinish(); 391 case kTracerTypeARBTimer:
328 glGetQueryObjectui64v(query, GL_QUERY_RESULT, &gl_now); 392 glFinish();
393 glGenQueriesARB(1, &query);
394 glQueryCounter(query, GL_TIMESTAMP);
395 glFinish();
396
397 glGetQueryObjectui64v(query, GL_QUERY_RESULT, &gl_now);
398 glDeleteQueriesARB(1, &query);
399 break;
400
401 case kTracerTypeDisjointTimer:
402 // Clear the disjoint bit before we do any queries.
403 glGetIntegerv(GL_GPU_DISJOINT_EXT, &disjoint_value);
404
405 glFinish();
406 glGenQueriesARB(1, &query);
407 glQueryCounter(query, GL_TIMESTAMP_EXT);
408 glFinish();
409
410 glGetQueryObjectui64vEXT(query, GL_QUERY_RESULT_EXT, &gl_now);
411 glDeleteQueriesARB(1, &query);
412
413 // Discard results if disjoint operation has occurred.
414 glGetIntegerv(GL_GPU_DISJOINT_EXT, &disjoint_value);
415 if (disjoint_value)
416 return;
417
418 break;
419
420 default:
421 break;
422 }
423
329 base::TimeTicks system_now = base::TimeTicks::NowFromSystemTraceTime(); 424 base::TimeTicks system_now = base::TimeTicks::NowFromSystemTraceTime();
330 425
331 gl_now /= base::Time::kNanosecondsPerMicrosecond; 426 gl_now /= base::Time::kNanosecondsPerMicrosecond;
332 timer_offset_ = system_now.ToInternalValue() - gl_now; 427 timer_offset_ = system_now.ToInternalValue() - gl_now;
333 glDeleteQueries(1, &query); 428 gpu_timing_synced_ = true;
334 } 429 }
335 } 430 }
336 431
337 void GPUTracer::IssueProcessTask() { 432 void GPUTracer::IssueProcessTask() {
338 if (traces_.empty() || process_posted_) 433 if (traces_.empty() || process_posted_)
339 return; 434 return;
340 435
341 process_posted_ = true; 436 process_posted_ = true;
342 base::MessageLoop::current()->PostDelayedTask( 437 base::MessageLoop::current()->PostDelayedTask(
343 FROM_HERE, 438 FROM_HERE,
344 base::Bind(&GPUTracer::Process, base::AsWeakPtr(this)), 439 base::Bind(&GPUTracer::Process, base::AsWeakPtr(this)),
345 base::TimeDelta::FromMilliseconds(kProcessInterval)); 440 base::TimeDelta::FromMilliseconds(kProcessInterval));
346 } 441 }
347 442
348 } // namespace gles2 443 } // namespace gles2
349 } // namespace gpu 444 } // namespace gpu
OLDNEW
« no previous file with comments | « gpu/command_buffer/service/gpu_tracer.h ('k') | gpu/command_buffer/service/gpu_tracer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698