Chromium Code Reviews| 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 |