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

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

Issue 794673007: Added unit tests for the GPU Tracer. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Reverted gpu_service_test Created 5 years, 11 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"
11 #include "base/strings/string_util.h" 11 #include "base/strings/string_util.h"
12 #include "base/time/time.h" 12 #include "base/time/time.h"
13 #include "gpu/command_buffer/common/gles2_cmd_utils.h" 13 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
14 14
15 namespace gpu { 15 namespace gpu {
16 namespace gles2 { 16 namespace gles2 {
17 17
18 static const unsigned int kProcessInterval = 16; 18 static const unsigned int kProcessInterval = 16;
19 static TraceOutputter* g_outputter_thread = NULL; 19 static TraceOutputter* g_outputter_thread = NULL;
20 20
21 CPUTime::CPUTime() {
22 }
23
24 int64 CPUTime::GetCurrentTime() {
25 return base::TimeTicks::NowFromSystemTraceTime().ToInternalValue();
26 }
27
28 CPUTime::~CPUTime() {
29 }
30
21 TraceMarker::TraceMarker(const std::string& category, const std::string& name) 31 TraceMarker::TraceMarker(const std::string& category, const std::string& name)
22 : category_(category), 32 : category_(category),
23 name_(name), 33 name_(name),
24 trace_(NULL) { 34 trace_(NULL) {
25 } 35 }
26 36
27 TraceMarker::~TraceMarker() { 37 TraceMarker::~TraceMarker() {
28 } 38 }
29 39
30 scoped_refptr<TraceOutputter> TraceOutputter::Create(const std::string& name) { 40 scoped_refptr<TraceOutputter> TraceOutputter::Create(const std::string& name) {
31 if (!g_outputter_thread) { 41 if (!g_outputter_thread) {
32 g_outputter_thread = new TraceOutputter(name); 42 g_outputter_thread = new TraceOutputter(name);
33 } 43 }
34 return g_outputter_thread; 44 return g_outputter_thread;
35 } 45 }
36 46
37 TraceOutputter::TraceOutputter(const std::string& name) 47 TraceOutputter::TraceOutputter(const std::string& name)
38 : named_thread_(name.c_str()), local_trace_id_(0) { 48 : named_thread_(name.c_str()), local_trace_id_(0) {
39 named_thread_.Start(); 49 named_thread_.Start();
40 named_thread_.Stop(); 50 named_thread_.Stop();
41 } 51 }
42 52
43 TraceOutputter::~TraceOutputter() { g_outputter_thread = NULL; } 53 TraceOutputter::~TraceOutputter() { g_outputter_thread = NULL; }
44 54
45 void TraceOutputter::Trace(const std::string& category, 55 void TraceOutputter::TraceDevice(const std::string& category,
46 const std::string& name, 56 const std::string& name,
47 int64 start_time, 57 int64 start_time,
48 int64 end_time) { 58 int64 end_time) {
49 TRACE_EVENT_COPY_BEGIN_WITH_ID_TID_AND_TIMESTAMP0(category.c_str(), 59 TRACE_EVENT_COPY_BEGIN_WITH_ID_TID_AND_TIMESTAMP0(category.c_str(),
50 name.c_str(), 60 name.c_str(),
51 local_trace_id_, 61 local_trace_id_,
52 named_thread_.thread_id(), 62 named_thread_.thread_id(),
53 start_time); 63 start_time);
54 TRACE_EVENT_COPY_END_WITH_ID_TID_AND_TIMESTAMP0(category.c_str(), 64 TRACE_EVENT_COPY_END_WITH_ID_TID_AND_TIMESTAMP0(category.c_str(),
55 name.c_str(), 65 name.c_str(),
56 local_trace_id_, 66 local_trace_id_,
57 named_thread_.thread_id(), 67 named_thread_.thread_id(),
58 end_time); 68 end_time);
59 ++local_trace_id_; 69 ++local_trace_id_;
60 } 70 }
61 71
72 void TraceOutputter::TraceServiceBegin(const std::string& category,
73 const std::string& name,
74 void* id) {
75 TRACE_EVENT_COPY_ASYNC_BEGIN0(category.c_str(), name.c_str(), id);
vmiura 2015/01/07 00:40:56 Using dynamic category strings isn't working right
David Yen 2015/01/07 18:11:47 Yes, that change is still in the other CL where gl
76 }
77
78 void TraceOutputter::TraceServiceEnd(const std::string& category,
79 const std::string& name,
80 void* id) {
81 TRACE_EVENT_COPY_ASYNC_END0(category.c_str(), name.c_str(), id);
82 }
83
62 GPUTrace::GPUTrace(scoped_refptr<Outputter> outputter, 84 GPUTrace::GPUTrace(scoped_refptr<Outputter> outputter,
85 scoped_refptr<CPUTime> cpu_time,
63 const std::string& category, 86 const std::string& category,
64 const std::string& name, 87 const std::string& name,
65 int64 offset, 88 int64 offset,
66 GpuTracerType tracer_type) 89 GpuTracerType tracer_type)
67 : category_(category), 90 : category_(category),
68 name_(name), 91 name_(name),
69 outputter_(outputter), 92 outputter_(outputter),
93 cpu_time_(cpu_time),
70 offset_(offset), 94 offset_(offset),
71 start_time_(0), 95 start_time_(0),
72 end_time_(0), 96 end_time_(0),
73 tracer_type_(tracer_type), 97 tracer_type_(tracer_type),
74 end_requested_(false) { 98 end_requested_(false) {
75 memset(queries_, 0, sizeof(queries_)); 99 memset(queries_, 0, sizeof(queries_));
76 switch (tracer_type_) { 100 switch (tracer_type_) {
77 case kTracerTypeARBTimer: 101 case kTracerTypeARBTimer:
78 case kTracerTypeDisjointTimer: 102 case kTracerTypeDisjointTimer:
79 glGenQueriesARB(2, queries_); 103 glGenQueriesARB(2, queries_);
(...skipping 11 matching lines...) Expand all
91 115
92 case kTracerTypeARBTimer: 116 case kTracerTypeARBTimer:
93 case kTracerTypeDisjointTimer: 117 case kTracerTypeDisjointTimer:
94 glDeleteQueriesARB(2, queries_); 118 glDeleteQueriesARB(2, queries_);
95 break; 119 break;
96 } 120 }
97 } 121 }
98 122
99 void GPUTrace::Start(bool trace_service) { 123 void GPUTrace::Start(bool trace_service) {
100 if (trace_service) { 124 if (trace_service) {
101 TRACE_EVENT_COPY_ASYNC_BEGIN0(category().c_str(), name().c_str(), this); 125 outputter_->TraceServiceBegin(category_, name_, this);
102 } 126 }
103 127
104 switch (tracer_type_) { 128 switch (tracer_type_) {
105 case kTracerTypeInvalid: 129 case kTracerTypeInvalid:
106 break; 130 break;
107 131
108 case kTracerTypeDisjointTimer: 132 case kTracerTypeDisjointTimer:
109 // For the disjoint timer, GPU idle time does not seem to increment the 133 // For the disjoint timer, GPU idle time does not seem to increment the
110 // internal counter. We must calculate the offset before any query. The 134 // internal counter. We must calculate the offset before any query. The
111 // good news is any device that supports disjoint timer will also support 135 // good news is any device that supports disjoint timer will also support
112 // glGetInteger64v, so we can query it directly unlike the ARBTimer case. 136 // glGetInteger64v, so we can query it directly unlike the ARBTimer case.
113 // The "offset_" variable will always be 0 during normal use cases, only 137 // The "offset_" variable will always be 0 during normal use cases, only
114 // under the unit tests will it be set to specific test values. 138 // under the unit tests will it be set to specific test values.
115 if (offset_ == 0) { 139 if (offset_ == 0) {
116 GLint64 gl_now = 0; 140 GLint64 gl_now = 0;
117 glGetInteger64v(GL_TIMESTAMP, &gl_now); 141 glGetInteger64v(GL_TIMESTAMP, &gl_now);
118 offset_ = base::TimeTicks::NowFromSystemTraceTime().ToInternalValue() - 142 offset_ = cpu_time_->GetCurrentTime() -
119 gl_now / base::Time::kNanosecondsPerMicrosecond; 143 gl_now / base::Time::kNanosecondsPerMicrosecond;
120 } 144 }
121 // Intentionally fall through to kTracerTypeARBTimer case.xs 145 // Intentionally fall through to kTracerTypeARBTimer case.xs
122 case kTracerTypeARBTimer: 146 case kTracerTypeARBTimer:
123 // GL_TIMESTAMP and GL_TIMESTAMP_EXT both have the same value. 147 // GL_TIMESTAMP and GL_TIMESTAMP_EXT both have the same value.
124 glQueryCounter(queries_[0], GL_TIMESTAMP); 148 glQueryCounter(queries_[0], GL_TIMESTAMP);
125 break; 149 break;
126 } 150 }
127 } 151 }
128 152
129 void GPUTrace::End(bool tracing_service) { 153 void GPUTrace::End(bool tracing_service) {
130 end_requested_ = true; 154 end_requested_ = true;
131 switch (tracer_type_) { 155 switch (tracer_type_) {
132 case kTracerTypeInvalid: 156 case kTracerTypeInvalid:
133 break; 157 break;
134 158
135 case kTracerTypeARBTimer: 159 case kTracerTypeARBTimer:
136 case kTracerTypeDisjointTimer: 160 case kTracerTypeDisjointTimer:
137 // GL_TIMESTAMP and GL_TIMESTAMP_EXT both have the same value. 161 // GL_TIMESTAMP and GL_TIMESTAMP_EXT both have the same value.
138 glQueryCounter(queries_[1], GL_TIMESTAMP); 162 glQueryCounter(queries_[1], GL_TIMESTAMP);
139 break; 163 break;
140 } 164 }
141 165
142 if (tracing_service) { 166 if (tracing_service) {
143 TRACE_EVENT_COPY_ASYNC_END0(category().c_str(), name().c_str(), this); 167 outputter_->TraceServiceEnd(category_, name_, this);
144 } 168 }
145 } 169 }
146 170
147 bool GPUTrace::IsAvailable() { 171 bool GPUTrace::IsAvailable() {
148 if (tracer_type_ != kTracerTypeInvalid) { 172 if (tracer_type_ != kTracerTypeInvalid) {
149 if (!end_requested_) 173 if (!end_requested_)
150 return false; 174 return false;
151 175
152 GLint done = 0; 176 GLint done = 0;
153 glGetQueryObjectiv(queries_[1], GL_QUERY_RESULT_AVAILABLE, &done); 177 glGetQueryObjectiv(queries_[1], GL_QUERY_RESULT_AVAILABLE, &done);
(...skipping 14 matching lines...) Expand all
168 192
169 // TODO(dsinclair): It's possible for the timer to wrap during the start/end. 193 // TODO(dsinclair): It's possible for the timer to wrap during the start/end.
170 // We need to detect if the end is less then the start and correct for the 194 // We need to detect if the end is less then the start and correct for the
171 // wrapping. 195 // wrapping.
172 glGetQueryObjectui64v(queries_[0], GL_QUERY_RESULT, &begin_stamp); 196 glGetQueryObjectui64v(queries_[0], GL_QUERY_RESULT, &begin_stamp);
173 glGetQueryObjectui64v(queries_[1], GL_QUERY_RESULT, &end_stamp); 197 glGetQueryObjectui64v(queries_[1], GL_QUERY_RESULT, &end_stamp);
174 198
175 start_time_ = (begin_stamp / base::Time::kNanosecondsPerMicrosecond) + 199 start_time_ = (begin_stamp / base::Time::kNanosecondsPerMicrosecond) +
176 offset_; 200 offset_;
177 end_time_ = (end_stamp / base::Time::kNanosecondsPerMicrosecond) + offset_; 201 end_time_ = (end_stamp / base::Time::kNanosecondsPerMicrosecond) + offset_;
178 outputter_->Trace(category(), name(), start_time_, end_time_); 202 outputter_->TraceDevice(category(), name(), start_time_, end_time_);
179 } 203 }
180 204
181 GPUTracer::GPUTracer(gles2::GLES2Decoder* decoder) 205 GPUTracer::GPUTracer(gles2::GLES2Decoder* decoder)
182 : gpu_trace_srv_category(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED( 206 : gpu_trace_srv_category(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
183 TRACE_DISABLED_BY_DEFAULT("gpu.service"))), 207 TRACE_DISABLED_BY_DEFAULT("gpu.service"))),
184 gpu_trace_dev_category(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED( 208 gpu_trace_dev_category(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
185 TRACE_DISABLED_BY_DEFAULT("gpu.device"))), 209 TRACE_DISABLED_BY_DEFAULT("gpu.device"))),
186 decoder_(decoder), 210 decoder_(decoder),
187 timer_offset_(0), 211 timer_offset_(0),
188 last_tracer_source_(kTraceGroupInvalid), 212 last_tracer_source_(kTraceGroupInvalid),
189 tracer_type_(kTracerTypeInvalid), 213 tracer_type_(kTracerTypeInvalid),
190 gpu_timing_synced_(false), 214 gpu_timing_synced_(false),
191 gpu_executing_(false), 215 gpu_executing_(false),
192 process_posted_(false) { 216 process_posted_(false) {
193 if (gfx::g_driver_gl.ext.b_GL_EXT_disjoint_timer_query) {
194 tracer_type_ = kTracerTypeDisjointTimer;
195 outputter_ = TraceOutputter::Create("GL_EXT_disjoint_timer_query");
196 } else if (gfx::g_driver_gl.ext.b_GL_ARB_timer_query) {
197 tracer_type_ = kTracerTypeARBTimer;
198 outputter_ = TraceOutputter::Create("GL_ARB_timer_query");
199 }
200 } 217 }
201 218
202 GPUTracer::~GPUTracer() { 219 GPUTracer::~GPUTracer() {
203 } 220 }
204 221
205 bool GPUTracer::BeginDecoding() { 222 bool GPUTracer::BeginDecoding() {
206 if (gpu_executing_) 223 if (gpu_executing_)
207 return false; 224 return false;
208 225
226 if (outputter_ == NULL) {
227 tracer_type_ = DetermineTracerType();
228 const char* tracer_type_name = "Unknown";
229 switch (tracer_type_) {
230 case kTracerTypeDisjointTimer:
231 tracer_type_name = "GL_EXT_disjoint_timer_query";
232 break;
233 case kTracerTypeARBTimer:
234 tracer_type_name = "GL_ARB_timer_query";
235 break;
236
237 default:
238 break;
239 }
240
241 outputter_ = CreateOutputter(tracer_type_name);
242 }
243
244 if (cpu_time_ == NULL) {
245 cpu_time_ = CreateCPUTime();
246 }
247
209 CalculateTimerOffset(); 248 CalculateTimerOffset();
210 gpu_executing_ = true; 249 gpu_executing_ = true;
211 250
212 if (IsTracing()) { 251 if (IsTracing()) {
213 // Reset disjoint bit for the disjoint timer. 252 // Reset disjoint bit for the disjoint timer.
214 if (tracer_type_ == kTracerTypeDisjointTimer) { 253 if (tracer_type_ == kTracerTypeDisjointTimer) {
215 GLint disjoint_value = 0; 254 GLint disjoint_value = 0;
216 glGetIntegerv(GL_GPU_DISJOINT_EXT, &disjoint_value); 255 glGetIntegerv(GL_GPU_DISJOINT_EXT, &disjoint_value);
217 } 256 }
218 257
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
320 return markers_[last_tracer_source_].back().name_; 359 return markers_[last_tracer_source_].back().name_;
321 } 360 }
322 return base::EmptyString(); 361 return base::EmptyString();
323 } 362 }
324 363
325 scoped_refptr<GPUTrace> GPUTracer::CreateTrace(const std::string& category, 364 scoped_refptr<GPUTrace> GPUTracer::CreateTrace(const std::string& category,
326 const std::string& name) { 365 const std::string& name) {
327 GpuTracerType tracer_type = *gpu_trace_dev_category ? tracer_type_ : 366 GpuTracerType tracer_type = *gpu_trace_dev_category ? tracer_type_ :
328 kTracerTypeInvalid; 367 kTracerTypeInvalid;
329 368
330 return new GPUTrace(outputter_, category, name, timer_offset_, tracer_type); 369 return new GPUTrace(outputter_, cpu_time_, category, name,
370 timer_offset_, tracer_type);
371 }
372
373 scoped_refptr<Outputter> GPUTracer::CreateOutputter(const std::string& name) {
374 return TraceOutputter::Create(name);
375 }
376
377 scoped_refptr<CPUTime> GPUTracer::CreateCPUTime() {
378 return new CPUTime();
379 }
380
381 GpuTracerType GPUTracer::DetermineTracerType() {
382 if (gfx::g_driver_gl.ext.b_GL_EXT_disjoint_timer_query) {
383 return kTracerTypeDisjointTimer;
384 } else if (gfx::g_driver_gl.ext.b_GL_ARB_timer_query) {
385 return kTracerTypeARBTimer;
386 }
387
388 return kTracerTypeInvalid;
389 }
390
391 void GPUTracer::PostTask() {
392 base::MessageLoop::current()->PostDelayedTask(
393 FROM_HERE,
394 base::Bind(&GPUTracer::Process, base::AsWeakPtr(this)),
395 base::TimeDelta::FromMilliseconds(kProcessInterval));
331 } 396 }
332 397
333 void GPUTracer::Process() { 398 void GPUTracer::Process() {
334 process_posted_ = false; 399 process_posted_ = false;
335 ProcessTraces(); 400 ProcessTraces();
336 IssueProcessTask(); 401 IssueProcessTask();
337 } 402 }
338 403
339 void GPUTracer::ProcessTraces() { 404 void GPUTracer::ProcessTraces() {
340 if (tracer_type_ == kTracerTypeInvalid) { 405 if (tracer_type_ == kTracerTypeInvalid) {
341 traces_.clear(); 406 traces_.clear();
342 return; 407 return;
343 } 408 }
344 409
345 TRACE_EVENT0("gpu", "GPUTracer::ProcessTraces"); 410 TRACE_EVENT0("gpu", "GPUTracer::ProcessTraces");
346 411
347 // Make owning decoder's GL context current 412 // Make owning decoder's GL context current
348 if (!decoder_->MakeCurrent()) { 413 if (decoder_ && !decoder_->MakeCurrent()) {
vmiura 2015/01/07 00:40:56 Should the tests use a mock decoder instead?
David Yen 2015/01/07 18:11:48 Done.
349 // Skip subsequent GL calls if MakeCurrent fails 414 // Skip subsequent GL calls if MakeCurrent fails
350 traces_.clear(); 415 traces_.clear();
351 return; 416 return;
352 } 417 }
353 418
354 // Check if disjoint operation has occurred, discard ongoing traces if so. 419 // Check if disjoint operation has occurred, discard ongoing traces if so.
355 if (tracer_type_ == kTracerTypeDisjointTimer) { 420 if (tracer_type_ == kTracerTypeDisjointTimer) {
356 GLint disjoint_value = 0; 421 GLint disjoint_value = 0;
357 glGetIntegerv(GL_GPU_DISJOINT_EXT, &disjoint_value); 422 glGetIntegerv(GL_GPU_DISJOINT_EXT, &disjoint_value);
358 if (disjoint_value) 423 if (disjoint_value)
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
394 459
395 glGenQueriesARB(1, &query); 460 glGenQueriesARB(1, &query);
396 461
397 glFinish(); 462 glFinish();
398 glQueryCounter(query, GL_TIMESTAMP); 463 glQueryCounter(query, GL_TIMESTAMP);
399 glFinish(); 464 glFinish();
400 465
401 glGetQueryObjectui64v(query, GL_QUERY_RESULT, &gl_now); 466 glGetQueryObjectui64v(query, GL_QUERY_RESULT, &gl_now);
402 glDeleteQueriesARB(1, &query); 467 glDeleteQueriesARB(1, &query);
403 468
404 base::TimeTicks system_now = base::TimeTicks::NowFromSystemTraceTime();
405
406 gl_now /= base::Time::kNanosecondsPerMicrosecond; 469 gl_now /= base::Time::kNanosecondsPerMicrosecond;
407 timer_offset_ = system_now.ToInternalValue() - gl_now; 470 timer_offset_ = cpu_time_->GetCurrentTime() - gl_now;
408 gpu_timing_synced_ = true; 471 gpu_timing_synced_ = true;
409 } 472 }
410 } 473 }
411 474
412 void GPUTracer::IssueProcessTask() { 475 void GPUTracer::IssueProcessTask() {
413 if (traces_.empty() || process_posted_) 476 if (traces_.empty() || process_posted_)
414 return; 477 return;
415 478
416 process_posted_ = true; 479 process_posted_ = true;
417 base::MessageLoop::current()->PostDelayedTask( 480 PostTask();
418 FROM_HERE,
419 base::Bind(&GPUTracer::Process, base::AsWeakPtr(this)),
420 base::TimeDelta::FromMilliseconds(kProcessInterval));
421 } 481 }
422 482
423 } // namespace gles2 483 } // namespace gles2
424 } // namespace gpu 484 } // 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