OLD | NEW |
---|---|
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 TraceMarker::TraceMarker(const std::string& name) | 21 TraceMarker::TraceMarker(const std::string& category, const std::string& name) |
22 : name_(name), | 22 : category_(category), |
23 name_(name), | |
23 trace_(NULL) { | 24 trace_(NULL) { |
24 } | 25 } |
25 | 26 |
26 TraceMarker::~TraceMarker() { | 27 TraceMarker::~TraceMarker() { |
27 } | 28 } |
28 | 29 |
29 scoped_refptr<TraceOutputter> TraceOutputter::Create(const std::string& name) { | 30 scoped_refptr<TraceOutputter> TraceOutputter::Create(const std::string& name) { |
30 if (!g_outputter_thread) { | 31 if (!g_outputter_thread) { |
31 g_outputter_thread = new TraceOutputter(name); | 32 g_outputter_thread = new TraceOutputter(name); |
32 } | 33 } |
33 return g_outputter_thread; | 34 return g_outputter_thread; |
34 } | 35 } |
35 | 36 |
36 TraceOutputter::TraceOutputter(const std::string& name) | 37 TraceOutputter::TraceOutputter(const std::string& name) |
37 : named_thread_(name.c_str()), local_trace_id_(0) { | 38 : named_thread_(name.c_str()), local_trace_id_(0) { |
38 named_thread_.Start(); | 39 named_thread_.Start(); |
39 named_thread_.Stop(); | 40 named_thread_.Stop(); |
40 } | 41 } |
41 | 42 |
42 TraceOutputter::~TraceOutputter() { g_outputter_thread = NULL; } | 43 TraceOutputter::~TraceOutputter() { g_outputter_thread = NULL; } |
43 | 44 |
44 void TraceOutputter::Trace(const std::string& name, | 45 void TraceOutputter::Trace(const std::string& category, |
46 const std::string& name, | |
45 int64 start_time, | 47 int64 start_time, |
46 int64 end_time) { | 48 int64 end_time) { |
47 TRACE_EVENT_COPY_BEGIN_WITH_ID_TID_AND_TIMESTAMP0( | 49 TRACE_EVENT_COPY_BEGIN_WITH_ID_TID_AND_TIMESTAMP0(category.c_str(), |
48 TRACE_DISABLED_BY_DEFAULT("gpu.device"), | 50 name.c_str(), |
49 name.c_str(), | 51 local_trace_id_, |
50 local_trace_id_, | 52 named_thread_.thread_id(), |
51 named_thread_.thread_id(), | 53 start_time); |
52 start_time); | 54 TRACE_EVENT_COPY_END_WITH_ID_TID_AND_TIMESTAMP0(category.c_str(), |
53 TRACE_EVENT_COPY_END_WITH_ID_TID_AND_TIMESTAMP0( | 55 name.c_str(), |
54 TRACE_DISABLED_BY_DEFAULT("gpu.device"), | 56 local_trace_id_, |
55 name.c_str(), | 57 named_thread_.thread_id(), |
56 local_trace_id_, | 58 end_time); |
57 named_thread_.thread_id(), | |
58 end_time); | |
59 ++local_trace_id_; | 59 ++local_trace_id_; |
60 } | 60 } |
61 | 61 |
62 GPUTrace::GPUTrace(scoped_refptr<Outputter> outputter, | 62 GPUTrace::GPUTrace(scoped_refptr<Outputter> outputter, |
63 const std::string& category, | |
63 const std::string& name, | 64 const std::string& name, |
64 int64 offset, | 65 int64 offset, |
65 GpuTracerType tracer_type) | 66 GpuTracerType tracer_type) |
66 : name_(name), | 67 : category_(category), |
68 name_(name), | |
67 outputter_(outputter), | 69 outputter_(outputter), |
68 offset_(offset), | 70 offset_(offset), |
69 start_time_(0), | 71 start_time_(0), |
70 end_time_(0), | 72 end_time_(0), |
71 tracer_type_(tracer_type), | 73 tracer_type_(tracer_type), |
72 end_requested_(false) { | 74 end_requested_(false) { |
73 memset(queries_, 0, sizeof(queries_)); | 75 memset(queries_, 0, sizeof(queries_)); |
74 switch (tracer_type_) { | 76 switch (tracer_type_) { |
75 case kTracerTypeARBTimer: | 77 case kTracerTypeARBTimer: |
76 case kTracerTypeDisjointTimer: | 78 case kTracerTypeDisjointTimer: |
(...skipping 11 matching lines...) Expand all Loading... | |
88 break; | 90 break; |
89 | 91 |
90 case kTracerTypeARBTimer: | 92 case kTracerTypeARBTimer: |
91 case kTracerTypeDisjointTimer: | 93 case kTracerTypeDisjointTimer: |
92 glDeleteQueriesARB(2, queries_); | 94 glDeleteQueriesARB(2, queries_); |
93 break; | 95 break; |
94 } | 96 } |
95 } | 97 } |
96 | 98 |
97 void GPUTrace::Start() { | 99 void GPUTrace::Start() { |
98 TRACE_EVENT_COPY_ASYNC_BEGIN0( | 100 TRACE_EVENT_COPY_ASYNC_BEGIN0(category().c_str(), name().c_str(), this); |
vmiura
2014/12/08 23:23:06
Shoud we check the gpu.service category is enabled
David Yen
2014/12/08 23:45:38
I believe Start() is only called from the GPUTrace
vmiura
2014/12/08 23:53:00
True, but IsTracing() returns true both (*gpu_trac
David Yen
2014/12/09 00:10:41
Good point, done.
| |
99 TRACE_DISABLED_BY_DEFAULT("gpu.service"), name().c_str(), this); | |
100 | 101 |
101 switch (tracer_type_) { | 102 switch (tracer_type_) { |
102 case kTracerTypeInvalid: | 103 case kTracerTypeInvalid: |
103 break; | 104 break; |
104 | 105 |
105 case kTracerTypeDisjointTimer: | 106 case kTracerTypeDisjointTimer: |
106 // For the disjoint timer, GPU idle time does not seem to increment the | 107 // For the disjoint timer, GPU idle time does not seem to increment the |
107 // internal counter. We must calculate the offset before any query. The | 108 // internal counter. We must calculate the offset before any query. The |
108 // good news is any device that supports disjoint timer will also support | 109 // good news is any device that supports disjoint timer will also support |
109 // glGetInteger64v, so we can query it directly unlike the ARBTimer case. | 110 // glGetInteger64v, so we can query it directly unlike the ARBTimer case. |
(...skipping 19 matching lines...) Expand all Loading... | |
129 case kTracerTypeInvalid: | 130 case kTracerTypeInvalid: |
130 break; | 131 break; |
131 | 132 |
132 case kTracerTypeARBTimer: | 133 case kTracerTypeARBTimer: |
133 case kTracerTypeDisjointTimer: | 134 case kTracerTypeDisjointTimer: |
134 // GL_TIMESTAMP and GL_TIMESTAMP_EXT both have the same value. | 135 // GL_TIMESTAMP and GL_TIMESTAMP_EXT both have the same value. |
135 glQueryCounter(queries_[1], GL_TIMESTAMP); | 136 glQueryCounter(queries_[1], GL_TIMESTAMP); |
136 break; | 137 break; |
137 } | 138 } |
138 | 139 |
139 TRACE_EVENT_COPY_ASYNC_END0( | 140 TRACE_EVENT_COPY_ASYNC_END0(category().c_str(), name().c_str(), this); |
vmiura
2014/12/08 23:23:06
And here.
if (*gpu_trace_srv_category) {
...
}
David Yen
2014/12/08 23:45:38
Same reason as above.
David Yen
2014/12/09 00:10:41
Done.
| |
140 TRACE_DISABLED_BY_DEFAULT("gpu.service"), name().c_str(), this); | |
141 } | 141 } |
142 | 142 |
143 bool GPUTrace::IsAvailable() { | 143 bool GPUTrace::IsAvailable() { |
144 if (tracer_type_ != kTracerTypeInvalid) { | 144 if (tracer_type_ != kTracerTypeInvalid) { |
145 if (!end_requested_) | 145 if (!end_requested_) |
146 return false; | 146 return false; |
147 | 147 |
148 GLint done = 0; | 148 GLint done = 0; |
149 glGetQueryObjectiv(queries_[1], GL_QUERY_RESULT_AVAILABLE, &done); | 149 glGetQueryObjectiv(queries_[1], GL_QUERY_RESULT_AVAILABLE, &done); |
150 return !!done; | 150 return !!done; |
(...skipping 13 matching lines...) Expand all Loading... | |
164 | 164 |
165 // TODO(dsinclair): It's possible for the timer to wrap during the start/end. | 165 // TODO(dsinclair): It's possible for the timer to wrap during the start/end. |
166 // We need to detect if the end is less then the start and correct for the | 166 // We need to detect if the end is less then the start and correct for the |
167 // wrapping. | 167 // wrapping. |
168 glGetQueryObjectui64v(queries_[0], GL_QUERY_RESULT, &begin_stamp); | 168 glGetQueryObjectui64v(queries_[0], GL_QUERY_RESULT, &begin_stamp); |
169 glGetQueryObjectui64v(queries_[1], GL_QUERY_RESULT, &end_stamp); | 169 glGetQueryObjectui64v(queries_[1], GL_QUERY_RESULT, &end_stamp); |
170 | 170 |
171 start_time_ = (begin_stamp / base::Time::kNanosecondsPerMicrosecond) + | 171 start_time_ = (begin_stamp / base::Time::kNanosecondsPerMicrosecond) + |
172 offset_; | 172 offset_; |
173 end_time_ = (end_stamp / base::Time::kNanosecondsPerMicrosecond) + offset_; | 173 end_time_ = (end_stamp / base::Time::kNanosecondsPerMicrosecond) + offset_; |
174 outputter_->Trace(name(), start_time_, end_time_); | 174 outputter_->Trace(category(), name(), start_time_, end_time_); |
175 } | 175 } |
176 | 176 |
177 GPUTracer::GPUTracer(gles2::GLES2Decoder* decoder) | 177 GPUTracer::GPUTracer(gles2::GLES2Decoder* decoder) |
178 : gpu_trace_srv_category(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED( | 178 : gpu_trace_srv_category(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED( |
179 TRACE_DISABLED_BY_DEFAULT("gpu.service"))), | 179 TRACE_DISABLED_BY_DEFAULT("gpu.service"))), |
180 gpu_trace_dev_category(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED( | 180 gpu_trace_dev_category(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED( |
181 TRACE_DISABLED_BY_DEFAULT("gpu.device"))), | 181 TRACE_DISABLED_BY_DEFAULT("gpu.device"))), |
182 decoder_(decoder), | 182 decoder_(decoder), |
183 timer_offset_(0), | 183 timer_offset_(0), |
184 last_tracer_source_(kTraceGroupInvalid), | 184 last_tracer_source_(kTraceGroupInvalid), |
(...skipping 23 matching lines...) Expand all Loading... | |
208 if (IsTracing()) { | 208 if (IsTracing()) { |
209 // Reset disjoint bit for the disjoint timer. | 209 // Reset disjoint bit for the disjoint timer. |
210 if (tracer_type_ == kTracerTypeDisjointTimer) { | 210 if (tracer_type_ == kTracerTypeDisjointTimer) { |
211 GLint disjoint_value = 0; | 211 GLint disjoint_value = 0; |
212 glGetIntegerv(GL_GPU_DISJOINT_EXT, &disjoint_value); | 212 glGetIntegerv(GL_GPU_DISJOINT_EXT, &disjoint_value); |
213 } | 213 } |
214 | 214 |
215 // Begin a Trace for all active markers | 215 // Begin a Trace for all active markers |
216 for (int n = 0; n < NUM_TRACER_SOURCES; n++) { | 216 for (int n = 0; n < NUM_TRACER_SOURCES; n++) { |
217 for (size_t i = 0; i < markers_[n].size(); i++) { | 217 for (size_t i = 0; i < markers_[n].size(); i++) { |
218 markers_[n][i].trace_ = CreateTrace(markers_[n][i].name_); | 218 TraceMarker& trace_marker = markers_[n][i]; |
219 markers_[n][i].trace_->Start(); | 219 trace_marker.trace_ = CreateTrace(trace_marker.category_, |
220 trace_marker.name_); | |
221 trace_marker.trace_->Start(); | |
220 } | 222 } |
221 } | 223 } |
222 } | 224 } |
223 return true; | 225 return true; |
224 } | 226 } |
225 | 227 |
226 bool GPUTracer::EndDecoding() { | 228 bool GPUTracer::EndDecoding() { |
227 if (!gpu_executing_) | 229 if (!gpu_executing_) |
228 return false; | 230 return false; |
229 | 231 |
(...skipping 12 matching lines...) Expand all Loading... | |
242 IssueProcessTask(); | 244 IssueProcessTask(); |
243 } | 245 } |
244 | 246 |
245 gpu_executing_ = false; | 247 gpu_executing_ = false; |
246 | 248 |
247 // NOTE(vmiura): glFlush() here can help give better trace results, | 249 // NOTE(vmiura): glFlush() here can help give better trace results, |
248 // but it distorts the normal device behavior. | 250 // but it distorts the normal device behavior. |
249 return true; | 251 return true; |
250 } | 252 } |
251 | 253 |
252 bool GPUTracer::Begin(const std::string& name, GpuTracerSource source) { | 254 bool GPUTracer::Begin(const std::string& category, const std::string& name, |
255 GpuTracerSource source) { | |
253 if (!gpu_executing_) | 256 if (!gpu_executing_) |
254 return false; | 257 return false; |
255 | 258 |
256 DCHECK(source >= 0 && source < NUM_TRACER_SOURCES); | 259 DCHECK(source >= 0 && source < NUM_TRACER_SOURCES); |
257 | 260 |
258 // Push new marker from given 'source' | 261 // Push new marker from given 'source' |
259 last_tracer_source_ = source; | 262 last_tracer_source_ = source; |
260 markers_[source].push_back(TraceMarker(name)); | 263 markers_[source].push_back(TraceMarker(category, name)); |
261 | 264 |
262 // Create trace | 265 // Create trace |
263 if (IsTracing()) { | 266 if (IsTracing()) { |
264 scoped_refptr<GPUTrace> trace = CreateTrace(name); | 267 scoped_refptr<GPUTrace> trace = CreateTrace(category, name); |
265 trace->Start(); | 268 trace->Start(); |
266 markers_[source].back().trace_ = trace; | 269 markers_[source].back().trace_ = trace; |
267 } | 270 } |
268 | 271 |
269 return true; | 272 return true; |
270 } | 273 } |
271 | 274 |
272 bool GPUTracer::End(GpuTracerSource source) { | 275 bool GPUTracer::End(GpuTracerSource source) { |
273 if (!gpu_executing_) | 276 if (!gpu_executing_) |
274 return false; | 277 return false; |
(...skipping 15 matching lines...) Expand all Loading... | |
290 markers_[source].pop_back(); | 293 markers_[source].pop_back(); |
291 return true; | 294 return true; |
292 } | 295 } |
293 return false; | 296 return false; |
294 } | 297 } |
295 | 298 |
296 bool GPUTracer::IsTracing() { | 299 bool GPUTracer::IsTracing() { |
297 return (*gpu_trace_srv_category != 0) || (*gpu_trace_dev_category != 0); | 300 return (*gpu_trace_srv_category != 0) || (*gpu_trace_dev_category != 0); |
298 } | 301 } |
299 | 302 |
303 const std::string& GPUTracer::CurrentCategory() const { | |
304 if (last_tracer_source_ >= 0 && | |
305 last_tracer_source_ < NUM_TRACER_SOURCES && | |
306 !markers_[last_tracer_source_].empty()) { | |
307 return markers_[last_tracer_source_].back().category_; | |
308 } | |
309 return base::EmptyString(); | |
310 } | |
311 | |
300 const std::string& GPUTracer::CurrentName() const { | 312 const std::string& GPUTracer::CurrentName() const { |
301 if (last_tracer_source_ >= 0 && | 313 if (last_tracer_source_ >= 0 && |
302 last_tracer_source_ < NUM_TRACER_SOURCES && | 314 last_tracer_source_ < NUM_TRACER_SOURCES && |
303 !markers_[last_tracer_source_].empty()) { | 315 !markers_[last_tracer_source_].empty()) { |
304 return markers_[last_tracer_source_].back().name_; | 316 return markers_[last_tracer_source_].back().name_; |
305 } | 317 } |
306 return base::EmptyString(); | 318 return base::EmptyString(); |
307 } | 319 } |
308 | 320 |
309 scoped_refptr<GPUTrace> GPUTracer::CreateTrace(const std::string& name) { | 321 scoped_refptr<GPUTrace> GPUTracer::CreateTrace(const std::string& category, |
322 const std::string& name) { | |
310 GpuTracerType tracer_type = *gpu_trace_dev_category ? tracer_type_ : | 323 GpuTracerType tracer_type = *gpu_trace_dev_category ? tracer_type_ : |
311 kTracerTypeInvalid; | 324 kTracerTypeInvalid; |
312 | 325 |
313 return new GPUTrace(outputter_, name, timer_offset_, tracer_type); | 326 return new GPUTrace(outputter_, category, name, timer_offset_, tracer_type); |
314 } | 327 } |
315 | 328 |
316 void GPUTracer::Process() { | 329 void GPUTracer::Process() { |
317 process_posted_ = false; | 330 process_posted_ = false; |
318 ProcessTraces(); | 331 ProcessTraces(); |
319 IssueProcessTask(); | 332 IssueProcessTask(); |
320 } | 333 } |
321 | 334 |
322 void GPUTracer::ProcessTraces() { | 335 void GPUTracer::ProcessTraces() { |
323 if (tracer_type_ == kTracerTypeInvalid) { | 336 if (tracer_type_ == kTracerTypeInvalid) { |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
398 | 411 |
399 process_posted_ = true; | 412 process_posted_ = true; |
400 base::MessageLoop::current()->PostDelayedTask( | 413 base::MessageLoop::current()->PostDelayedTask( |
401 FROM_HERE, | 414 FROM_HERE, |
402 base::Bind(&GPUTracer::Process, base::AsWeakPtr(this)), | 415 base::Bind(&GPUTracer::Process, base::AsWeakPtr(this)), |
403 base::TimeDelta::FromMilliseconds(kProcessInterval)); | 416 base::TimeDelta::FromMilliseconds(kProcessInterval)); |
404 } | 417 } |
405 | 418 |
406 } // namespace gles2 | 419 } // namespace gles2 |
407 } // namespace gpu | 420 } // namespace gpu |
OLD | NEW |