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

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

Issue 904743002: gpu: Extract the gpu timing code from gpu_tracer. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix cl.exe warning: 'const unsigned char' : forcing value to bool 'true' or 'false' Created 5 years, 10 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/strings/string_util.h" 10 #include "base/strings/string_util.h"
11 #include "base/time/time.h" 11 #include "base/time/time.h"
12 #include "base/trace_event/trace_event.h" 12 #include "base/trace_event/trace_event.h"
13 #include "gpu/command_buffer/common/gles2_cmd_utils.h" 13 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
14 #include "gpu/command_buffer/service/context_group.h" 14 #include "gpu/command_buffer/service/context_group.h"
15 #include "ui/gl/gl_version_info.h" 15 #include "ui/gl/gl_version_info.h"
16 16
17 namespace gpu { 17 namespace gpu {
18 namespace gles2 { 18 namespace gles2 {
19 19
20 static const unsigned int kProcessInterval = 16; 20 static const unsigned int kProcessInterval = 16;
21 static TraceOutputter* g_outputter_thread = NULL; 21 static TraceOutputter* g_outputter_thread = NULL;
22 22
23 CPUTime::CPUTime() {
24 }
25
26 int64 CPUTime::GetCurrentTime() {
27 return base::TimeTicks::NowFromSystemTraceTime().ToInternalValue();
28 }
29
30 CPUTime::~CPUTime() {
31 }
32
33 TraceMarker::TraceMarker(const std::string& category, const std::string& name) 23 TraceMarker::TraceMarker(const std::string& category, const std::string& name)
34 : category_(category), 24 : category_(category),
35 name_(name), 25 name_(name),
36 trace_(NULL) { 26 trace_(NULL) {
37 } 27 }
38 28
39 TraceMarker::~TraceMarker() { 29 TraceMarker::~TraceMarker() {
40 } 30 }
41 31
42 scoped_refptr<TraceOutputter> TraceOutputter::Create(const std::string& name) { 32 scoped_refptr<TraceOutputter> TraceOutputter::Create(const std::string& name) {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
83 name.c_str(), "gl_category", category.c_str()); 73 name.c_str(), "gl_category", category.c_str());
84 } 74 }
85 75
86 void TraceOutputter::TraceServiceEnd(const std::string& category, 76 void TraceOutputter::TraceServiceEnd(const std::string& category,
87 const std::string& name) { 77 const std::string& name) {
88 TRACE_EVENT_COPY_END1(TRACE_DISABLED_BY_DEFAULT("gpu.service"), 78 TRACE_EVENT_COPY_END1(TRACE_DISABLED_BY_DEFAULT("gpu.service"),
89 name.c_str(), "gl_category", category.c_str()); 79 name.c_str(), "gl_category", category.c_str());
90 } 80 }
91 81
92 GPUTrace::GPUTrace(scoped_refptr<Outputter> outputter, 82 GPUTrace::GPUTrace(scoped_refptr<Outputter> outputter,
93 scoped_refptr<CPUTime> cpu_time, 83 gpu::GPUTiming* gpu_timing,
94 const std::string& category, 84 const std::string& category,
95 const std::string& name, 85 const std::string& name,
96 int64 offset, 86 const bool enabled)
97 GpuTracerType tracer_type)
98 : category_(category), 87 : category_(category),
99 name_(name), 88 name_(name),
100 outputter_(outputter), 89 outputter_(outputter),
101 cpu_time_(cpu_time), 90 enabled_(enabled) {
102 offset_(offset), 91 if (gpu_timing->IsAvailable()) {
103 start_time_(0), 92 gpu_timer_.reset(new GPUTimer(gpu_timing));
104 end_time_(0),
105 tracer_type_(tracer_type),
106 end_requested_(false) {
107 memset(queries_, 0, sizeof(queries_));
108 switch (tracer_type_) {
109 case kTracerTypeARBTimer:
110 case kTracerTypeDisjointTimer:
111 glGenQueriesARB(2, queries_);
112 break;
113
114 default:
115 tracer_type_ = kTracerTypeInvalid;
116 } 93 }
117 } 94 }
118 95
119 GPUTrace::~GPUTrace() { 96 GPUTrace::~GPUTrace() {
120 switch (tracer_type_) {
121 case kTracerTypeInvalid:
122 break;
123
124 case kTracerTypeARBTimer:
125 case kTracerTypeDisjointTimer:
126 glDeleteQueriesARB(2, queries_);
127 break;
128 }
129 } 97 }
130 98
131 void GPUTrace::Start(bool trace_service) { 99 void GPUTrace::Start(bool trace_service) {
132 if (trace_service) { 100 if (trace_service) {
133 outputter_->TraceServiceBegin(category_, name_); 101 outputter_->TraceServiceBegin(category_, name_);
134 } 102 }
135 103 if (gpu_timer_.get()) {
136 switch (tracer_type_) { 104 gpu_timer_->Start();
137 case kTracerTypeInvalid:
138 break;
139
140 case kTracerTypeDisjointTimer:
141 // For the disjoint timer, GPU idle time does not seem to increment the
142 // internal counter. We must calculate the offset before any query.
143 // glGetInteger64v is supported under ES3 which we check for before using
144 // the kTracerTypeDisjointTimer.
145 {
146 GLint64 gl_now = 0;
147 glGetInteger64v(GL_TIMESTAMP, &gl_now);
148 offset_ = cpu_time_->GetCurrentTime() -
149 gl_now / base::Time::kNanosecondsPerMicrosecond;
150 }
151 // Intentionally fall through to kTracerTypeARBTimer case.xs
152 case kTracerTypeARBTimer:
153 // GL_TIMESTAMP and GL_TIMESTAMP_EXT both have the same value.
154 glQueryCounter(queries_[0], GL_TIMESTAMP);
155 break;
156 } 105 }
157 } 106 }
158 107
159 void GPUTrace::End(bool tracing_service) { 108 void GPUTrace::End(bool tracing_service) {
160 end_requested_ = true; 109 if (gpu_timer_.get()) {
161 switch (tracer_type_) { 110 gpu_timer_->End();
162 case kTracerTypeInvalid:
163 break;
164
165 case kTracerTypeARBTimer:
166 case kTracerTypeDisjointTimer:
167 // GL_TIMESTAMP and GL_TIMESTAMP_EXT both have the same value.
168 glQueryCounter(queries_[1], GL_TIMESTAMP);
169 break;
170 } 111 }
171
172 if (tracing_service) { 112 if (tracing_service) {
173 outputter_->TraceServiceEnd(category_, name_); 113 outputter_->TraceServiceEnd(category_, name_);
174 } 114 }
175 } 115 }
176 116
177 bool GPUTrace::IsAvailable() { 117 bool GPUTrace::IsAvailable() {
178 if (tracer_type_ != kTracerTypeInvalid) { 118 return !gpu_timer_.get() || gpu_timer_->IsAvailable();
179 if (!end_requested_)
180 return false;
181
182 GLint done = 0;
183 glGetQueryObjectivARB(queries_[1], GL_QUERY_RESULT_AVAILABLE, &done);
184 return !!done;
185 }
186
187 return true;
188 } 119 }
189 120
190 void GPUTrace::Process() { 121 void GPUTrace::Process() {
191 if (tracer_type_ == kTracerTypeInvalid) 122 if (gpu_timer_.get()) {
192 return; 123 DCHECK(IsAvailable());
193 124
194 DCHECK(IsAvailable()); 125 int64 start = 0;
195 126 int64 end = 0;
196 GLuint64 begin_stamp = 0; 127 gpu_timer_->GetStartEndTimestamps(&start, &end);
197 GLuint64 end_stamp = 0; 128 outputter_->TraceDevice(category_, name_, start, end);
198 129 }
199 // TODO(dsinclair): It's possible for the timer to wrap during the start/end.
200 // We need to detect if the end is less then the start and correct for the
201 // wrapping.
202 glGetQueryObjectui64v(queries_[0], GL_QUERY_RESULT, &begin_stamp);
203 glGetQueryObjectui64v(queries_[1], GL_QUERY_RESULT, &end_stamp);
204
205 start_time_ = (begin_stamp / base::Time::kNanosecondsPerMicrosecond) +
206 offset_;
207 end_time_ = (end_stamp / base::Time::kNanosecondsPerMicrosecond) + offset_;
208 outputter_->TraceDevice(category_, name_, start_time_, end_time_);
209 } 130 }
210 131
211 GPUTracer::GPUTracer(gles2::GLES2Decoder* decoder) 132 GPUTracer::GPUTracer(gles2::GLES2Decoder* decoder)
212 : gpu_trace_srv_category(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED( 133 : gpu_trace_srv_category(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
213 TRACE_DISABLED_BY_DEFAULT("gpu.service"))), 134 TRACE_DISABLED_BY_DEFAULT("gpu.service"))),
214 gpu_trace_dev_category(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED( 135 gpu_trace_dev_category(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
215 TRACE_DISABLED_BY_DEFAULT("gpu.device"))), 136 TRACE_DISABLED_BY_DEFAULT("gpu.device"))),
216 decoder_(decoder), 137 decoder_(decoder),
217 timer_offset_(0), 138 gpu_timing_(),
218 tracer_type_(kTracerTypeInvalid),
219 gpu_timing_synced_(false),
220 gpu_executing_(false), 139 gpu_executing_(false),
221 process_posted_(false) { 140 process_posted_(false) {
222 } 141 }
223 142
224 GPUTracer::~GPUTracer() { 143 GPUTracer::~GPUTracer() {
225 } 144 }
226 145
227 bool GPUTracer::BeginDecoding() { 146 bool GPUTracer::BeginDecoding() {
228 if (gpu_executing_) 147 if (gpu_executing_)
229 return false; 148 return false;
230 149
231 if (outputter_ == NULL) { 150 if (outputter_ == NULL) {
232 tracer_type_ = DetermineTracerType(); 151 gpu_timing_.Initialize(decoder_->GetGLContext());
233 const char* tracer_type_name = "Unknown"; 152 outputter_ = CreateOutputter(gpu_timing_.GetTimerTypeName());
234 switch (tracer_type_) {
235 case kTracerTypeDisjointTimer:
236 tracer_type_name = "GL_EXT_disjoint_timer_query";
237 break;
238 case kTracerTypeARBTimer:
239 tracer_type_name = "GL_ARB_timer_query";
240 break;
241
242 default:
243 break;
244 }
245
246 outputter_ = CreateOutputter(tracer_type_name);
247 } 153 }
248 154
249 if (cpu_time_ == NULL) {
250 cpu_time_ = CreateCPUTime();
251 }
252
253 CalculateTimerOffset();
254 gpu_executing_ = true; 155 gpu_executing_ = true;
255
256 if (IsTracing()) { 156 if (IsTracing()) {
257 // Reset disjoint bit for the disjoint timer.
258 if (tracer_type_ == kTracerTypeDisjointTimer) {
259 GLint disjoint_value = 0;
260 glGetIntegerv(GL_GPU_DISJOINT_EXT, &disjoint_value);
261 }
262
263 // Begin a Trace for all active markers 157 // Begin a Trace for all active markers
David Yen 2015/02/06 22:47:01 gpu_timing_ needs to reset the disjoint state here
Daniele Castagna 2015/02/10 04:49:33 Done.
264 for (int n = 0; n < NUM_TRACER_SOURCES; n++) { 158 for (int n = 0; n < NUM_TRACER_SOURCES; n++) {
265 for (size_t i = 0; i < markers_[n].size(); i++) { 159 for (size_t i = 0; i < markers_[n].size(); i++) {
266 TraceMarker& trace_marker = markers_[n][i]; 160 TraceMarker& trace_marker = markers_[n][i];
267 trace_marker.trace_ = CreateTrace(trace_marker.category_, 161 trace_marker.trace_ =
268 trace_marker.name_); 162 new GPUTrace(outputter_, &gpu_timing_, trace_marker.category_,
163 trace_marker.name_, *gpu_trace_dev_category != 0);
269 trace_marker.trace_->Start(*gpu_trace_srv_category != 0); 164 trace_marker.trace_->Start(*gpu_trace_srv_category != 0);
270 } 165 }
271 } 166 }
272 } 167 }
273 return true; 168 return true;
274 } 169 }
275 170
276 bool GPUTracer::EndDecoding() { 171 bool GPUTracer::EndDecoding() {
277 if (!gpu_executing_) 172 if (!gpu_executing_)
278 return false; 173 return false;
(...skipping 27 matching lines...) Expand all
306 if (!gpu_executing_) 201 if (!gpu_executing_)
307 return false; 202 return false;
308 203
309 DCHECK(source >= 0 && source < NUM_TRACER_SOURCES); 204 DCHECK(source >= 0 && source < NUM_TRACER_SOURCES);
310 205
311 // Push new marker from given 'source' 206 // Push new marker from given 'source'
312 markers_[source].push_back(TraceMarker(category, name)); 207 markers_[source].push_back(TraceMarker(category, name));
313 208
314 // Create trace 209 // Create trace
315 if (IsTracing()) { 210 if (IsTracing()) {
316 scoped_refptr<GPUTrace> trace = CreateTrace(category, name); 211 scoped_refptr<GPUTrace> trace =
212 new GPUTrace(outputter_, &gpu_timing_, category, name,
213 *gpu_trace_dev_category != '\0');
317 trace->Start(*gpu_trace_srv_category != 0); 214 trace->Start(*gpu_trace_srv_category != 0);
318 markers_[source].back().trace_ = trace; 215 markers_[source].back().trace_ = trace;
319 } 216 }
320 217
321 return true; 218 return true;
322 } 219 }
323 220
324 bool GPUTracer::End(GpuTracerSource source) { 221 bool GPUTracer::End(GpuTracerSource source) {
325 if (!gpu_executing_) 222 if (!gpu_executing_)
326 return false; 223 return false;
(...skipping 12 matching lines...) Expand all
339 } 236 }
340 } 237 }
341 238
342 markers_[source].pop_back(); 239 markers_[source].pop_back();
343 return true; 240 return true;
344 } 241 }
345 return false; 242 return false;
346 } 243 }
347 244
348 bool GPUTracer::IsTracing() { 245 bool GPUTracer::IsTracing() {
349 return (*gpu_trace_srv_category != 0) || (*gpu_trace_dev_category != 0); 246 return (*gpu_trace_srv_category != 0) || (*gpu_trace_dev_category != '\0');
David Yen 2015/02/06 22:47:01 I don't really mind which but these 2 should proba
Daniele Castagna 2015/02/10 04:49:33 Done.
350 } 247 }
351 248
352 const std::string& GPUTracer::CurrentCategory(GpuTracerSource source) const { 249 const std::string& GPUTracer::CurrentCategory(GpuTracerSource source) const {
353 if (source >= 0 && 250 if (source >= 0 &&
354 source < NUM_TRACER_SOURCES && 251 source < NUM_TRACER_SOURCES &&
355 !markers_[source].empty()) { 252 !markers_[source].empty()) {
356 return markers_[source].back().category_; 253 return markers_[source].back().category_;
357 } 254 }
358 return base::EmptyString(); 255 return base::EmptyString();
359 } 256 }
360 257
361 const std::string& GPUTracer::CurrentName(GpuTracerSource source) const { 258 const std::string& GPUTracer::CurrentName(GpuTracerSource source) const {
362 if (source >= 0 && 259 if (source >= 0 &&
363 source < NUM_TRACER_SOURCES && 260 source < NUM_TRACER_SOURCES &&
364 !markers_[source].empty()) { 261 !markers_[source].empty()) {
365 return markers_[source].back().name_; 262 return markers_[source].back().name_;
366 } 263 }
367 return base::EmptyString(); 264 return base::EmptyString();
368 } 265 }
369 266
370 scoped_refptr<GPUTrace> GPUTracer::CreateTrace(const std::string& category,
371 const std::string& name) {
372 GpuTracerType tracer_type = *gpu_trace_dev_category ? tracer_type_ :
373 kTracerTypeInvalid;
374
375 return new GPUTrace(outputter_, cpu_time_, category, name,
376 timer_offset_, tracer_type);
377 }
378
379 scoped_refptr<Outputter> GPUTracer::CreateOutputter(const std::string& name) { 267 scoped_refptr<Outputter> GPUTracer::CreateOutputter(const std::string& name) {
380 return TraceOutputter::Create(name); 268 return TraceOutputter::Create(name);
381 } 269 }
382 270
383 scoped_refptr<CPUTime> GPUTracer::CreateCPUTime() {
384 return new CPUTime();
385 }
386
387 GpuTracerType GPUTracer::DetermineTracerType() {
388 ContextGroup* context_group = decoder_->GetContextGroup();
389 const gpu::gles2::FeatureInfo* feature_info = context_group->feature_info();
390 const gfx::GLVersionInfo& version_info = feature_info->gl_version_info();
391
392 if (version_info.is_es3 &&
393 gfx::g_driver_gl.ext.b_GL_EXT_disjoint_timer_query) {
394 return kTracerTypeDisjointTimer;
395 } else if (gfx::g_driver_gl.ext.b_GL_ARB_timer_query) {
396 return kTracerTypeARBTimer;
397 }
398
399 return kTracerTypeInvalid;
400 }
401
402 void GPUTracer::PostTask() { 271 void GPUTracer::PostTask() {
403 base::MessageLoop::current()->PostDelayedTask( 272 base::MessageLoop::current()->PostDelayedTask(
404 FROM_HERE, 273 FROM_HERE,
405 base::Bind(&GPUTracer::Process, base::AsWeakPtr(this)), 274 base::Bind(&GPUTracer::Process, base::AsWeakPtr(this)),
406 base::TimeDelta::FromMilliseconds(kProcessInterval)); 275 base::TimeDelta::FromMilliseconds(kProcessInterval));
407 } 276 }
408 277
409 void GPUTracer::Process() { 278 void GPUTracer::Process() {
410 process_posted_ = false; 279 process_posted_ = false;
411 ProcessTraces(); 280 ProcessTraces();
412 IssueProcessTask(); 281 IssueProcessTask();
413 } 282 }
414 283
415 void GPUTracer::ProcessTraces() { 284 void GPUTracer::ProcessTraces() {
416 if (tracer_type_ == kTracerTypeInvalid) { 285 if (!gpu_timing_.IsAvailable()) {
417 traces_.clear(); 286 traces_.clear();
418 return; 287 return;
419 } 288 }
420 289
421 TRACE_EVENT0("gpu", "GPUTracer::ProcessTraces"); 290 TRACE_EVENT0("gpu", "GPUTracer::ProcessTraces");
422 291
423 // Make owning decoder's GL context current 292 // Make owning decoder's GL context current
424 if (!decoder_->MakeCurrent()) { 293 if (!decoder_->MakeCurrent()) {
425 // Skip subsequent GL calls if MakeCurrent fails 294 // Skip subsequent GL calls if MakeCurrent fails
426 traces_.clear(); 295 traces_.clear();
427 return; 296 return;
428 } 297 }
429 298
430 // Check if disjoint operation has occurred, discard ongoing traces if so. 299 // Check if timers are still valid (e.g: a disjoint operation
431 if (tracer_type_ == kTracerTypeDisjointTimer) { 300 // might have occurred.)
432 GLint disjoint_value = 0; 301 if (gpu_timing_.CheckAndResetTimerErrors())
433 glGetIntegerv(GL_GPU_DISJOINT_EXT, &disjoint_value);
434 if (disjoint_value)
435 traces_.clear(); 302 traces_.clear();
David Yen 2015/02/06 22:47:01 indentation needs to be corrected now.
Daniele Castagna 2015/02/10 04:49:33 I'm using git-clang-format, isn't that enough?
vmiura 2015/02/10 07:43:13 There should be a 2 space indentation. Did you ru
Daniele Castagna 2015/02/10 17:28:27 Is it possible that according to the diff that lin
436 }
437 303
438 while (!traces_.empty() && traces_.front()->IsAvailable()) { 304 while (!traces_.empty() && traces_.front()->IsAvailable()) {
439 traces_.front()->Process(); 305 traces_.front()->Process();
440 traces_.pop_front(); 306 traces_.pop_front();
441 } 307 }
442 308
443 // Clear pending traces if there were are any errors 309 // Clear pending traces if there were are any errors
444 GLenum err = glGetError(); 310 GLenum err = glGetError();
445 if (err != GL_NO_ERROR) 311 if (err != GL_NO_ERROR)
446 traces_.clear(); 312 traces_.clear();
447 } 313 }
448 314
449 void GPUTracer::CalculateTimerOffset() { 315 void GPUTracer::CalculateTimerOffset() {
450 if (tracer_type_ != kTracerTypeInvalid) { 316 if (gpu_timing_.IsAvailable()) {
451 if (*gpu_trace_dev_category == '\0') { 317 if (*gpu_trace_dev_category == '\0') {
452 // If GPU device category is off, invalidate timing sync. 318 // If GPU device category is off, invalidate timing sync.
453 gpu_timing_synced_ = false; 319 gpu_timing_.InvalidateTimerOffset();
454 } else if (!gpu_timing_synced_ && tracer_type_ == kTracerTypeARBTimer) { 320 } else {
455 TRACE_EVENT0("gpu", "GPUTracer::CalculateTimerOffset"); 321 TRACE_EVENT0("gpu", "GPUTracer::CalculateTimerOffset");
456 322 gpu_timing_.CalculateTimerOffset();
David Yen 2015/02/06 22:47:01 Since gpu_timing now internally keeps track of whe
Daniele Castagna 2015/02/10 04:49:33 Done.
457 // ARB Timer is written for OpenGL 3.2 which contains glGetInteger64v().
458 GLint64 gl_now = 0;
459 glGetInteger64v(GL_TIMESTAMP, &gl_now);
460 timer_offset_ = cpu_time_->GetCurrentTime() -
461 gl_now / base::Time::kNanosecondsPerMicrosecond;
462 gpu_timing_synced_ = true;
463 } 323 }
464 } 324 }
465 } 325 }
466 326
467 void GPUTracer::IssueProcessTask() { 327 void GPUTracer::IssueProcessTask() {
468 if (traces_.empty() || process_posted_) 328 if (traces_.empty() || process_posted_)
469 return; 329 return;
470 330
471 process_posted_ = true; 331 process_posted_ = true;
472 PostTask(); 332 PostTask();
473 } 333 }
474 334
475 } // namespace gles2 335 } // namespace gles2
476 } // namespace gpu 336 } // namespace gpu
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698