| 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" |
| (...skipping 28 matching lines...) Expand all Loading... |
| 39 named_thread_.Start(); | 39 named_thread_.Start(); |
| 40 named_thread_.Stop(); | 40 named_thread_.Stop(); |
| 41 } | 41 } |
| 42 | 42 |
| 43 TraceOutputter::~TraceOutputter() { g_outputter_thread = NULL; } | 43 TraceOutputter::~TraceOutputter() { g_outputter_thread = NULL; } |
| 44 | 44 |
| 45 void TraceOutputter::Trace(const std::string& category, | 45 void TraceOutputter::Trace(const std::string& category, |
| 46 const std::string& name, | 46 const std::string& name, |
| 47 int64 start_time, | 47 int64 start_time, |
| 48 int64 end_time) { | 48 int64 end_time) { |
| 49 TRACE_EVENT_COPY_BEGIN_WITH_ID_TID_AND_TIMESTAMP0(category.c_str(), | 49 TRACE_EVENT_COPY_BEGIN_WITH_ID_TID_AND_TIMESTAMP1( |
| 50 name.c_str(), | 50 TRACE_DISABLED_BY_DEFAULT("gpu.device"), |
| 51 local_trace_id_, | 51 name.c_str(), |
| 52 named_thread_.thread_id(), | 52 local_trace_id_, |
| 53 start_time); | 53 named_thread_.thread_id(), |
| 54 TRACE_EVENT_COPY_END_WITH_ID_TID_AND_TIMESTAMP0(category.c_str(), | 54 start_time, |
| 55 name.c_str(), | 55 "gl_category", |
| 56 local_trace_id_, | 56 category.c_str()); |
| 57 named_thread_.thread_id(), | 57 TRACE_EVENT_COPY_END_WITH_ID_TID_AND_TIMESTAMP1( |
| 58 end_time); | 58 TRACE_DISABLED_BY_DEFAULT("gpu.device"), |
| 59 name.c_str(), |
| 60 local_trace_id_, |
| 61 named_thread_.thread_id(), |
| 62 end_time, |
| 63 "gl_category", |
| 64 category.c_str()); |
| 59 ++local_trace_id_; | 65 ++local_trace_id_; |
| 60 } | 66 } |
| 61 | 67 |
| 62 GPUTrace::GPUTrace(scoped_refptr<Outputter> outputter, | 68 GPUTrace::GPUTrace(scoped_refptr<Outputter> outputter, |
| 63 const std::string& category, | 69 const std::string& category, |
| 64 const std::string& name, | 70 const std::string& name, |
| 65 int64 offset, | 71 int64 offset, |
| 66 GpuTracerType tracer_type) | 72 GpuTracerType tracer_type) |
| 67 : category_(category), | 73 : category_(category), |
| 68 name_(name), | 74 name_(name), |
| (...skipping 22 matching lines...) Expand all Loading... |
| 91 | 97 |
| 92 case kTracerTypeARBTimer: | 98 case kTracerTypeARBTimer: |
| 93 case kTracerTypeDisjointTimer: | 99 case kTracerTypeDisjointTimer: |
| 94 glDeleteQueriesARB(2, queries_); | 100 glDeleteQueriesARB(2, queries_); |
| 95 break; | 101 break; |
| 96 } | 102 } |
| 97 } | 103 } |
| 98 | 104 |
| 99 void GPUTrace::Start(bool trace_service) { | 105 void GPUTrace::Start(bool trace_service) { |
| 100 if (trace_service) { | 106 if (trace_service) { |
| 101 TRACE_EVENT_COPY_ASYNC_BEGIN0(category().c_str(), name().c_str(), this); | 107 TRACE_EVENT_COPY_ASYNC_BEGIN1(TRACE_DISABLED_BY_DEFAULT("gpu.service"), |
| 108 name_.c_str(), this, |
| 109 "gl_category", category_.c_str()); |
| 102 } | 110 } |
| 103 | 111 |
| 104 switch (tracer_type_) { | 112 switch (tracer_type_) { |
| 105 case kTracerTypeInvalid: | 113 case kTracerTypeInvalid: |
| 106 break; | 114 break; |
| 107 | 115 |
| 108 case kTracerTypeDisjointTimer: | 116 case kTracerTypeDisjointTimer: |
| 109 // For the disjoint timer, GPU idle time does not seem to increment the | 117 // 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 | 118 // internal counter. We must calculate the offset before any query. The |
| 111 // good news is any device that supports disjoint timer will also support | 119 // good news is any device that supports disjoint timer will also support |
| (...skipping 21 matching lines...) Expand all Loading... |
| 133 break; | 141 break; |
| 134 | 142 |
| 135 case kTracerTypeARBTimer: | 143 case kTracerTypeARBTimer: |
| 136 case kTracerTypeDisjointTimer: | 144 case kTracerTypeDisjointTimer: |
| 137 // GL_TIMESTAMP and GL_TIMESTAMP_EXT both have the same value. | 145 // GL_TIMESTAMP and GL_TIMESTAMP_EXT both have the same value. |
| 138 glQueryCounter(queries_[1], GL_TIMESTAMP); | 146 glQueryCounter(queries_[1], GL_TIMESTAMP); |
| 139 break; | 147 break; |
| 140 } | 148 } |
| 141 | 149 |
| 142 if (tracing_service) { | 150 if (tracing_service) { |
| 143 TRACE_EVENT_COPY_ASYNC_END0(category().c_str(), name().c_str(), this); | 151 TRACE_EVENT_COPY_ASYNC_END1(TRACE_DISABLED_BY_DEFAULT("gpu.service"), |
| 152 name_.c_str(), this, |
| 153 "gl_category", category_.c_str()); |
| 144 } | 154 } |
| 145 } | 155 } |
| 146 | 156 |
| 147 bool GPUTrace::IsAvailable() { | 157 bool GPUTrace::IsAvailable() { |
| 148 if (tracer_type_ != kTracerTypeInvalid) { | 158 if (tracer_type_ != kTracerTypeInvalid) { |
| 149 if (!end_requested_) | 159 if (!end_requested_) |
| 150 return false; | 160 return false; |
| 151 | 161 |
| 152 GLint done = 0; | 162 GLint done = 0; |
| 153 glGetQueryObjectiv(queries_[1], GL_QUERY_RESULT_AVAILABLE, &done); | 163 glGetQueryObjectiv(queries_[1], GL_QUERY_RESULT_AVAILABLE, &done); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 168 | 178 |
| 169 // TODO(dsinclair): It's possible for the timer to wrap during the start/end. | 179 // 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 | 180 // We need to detect if the end is less then the start and correct for the |
| 171 // wrapping. | 181 // wrapping. |
| 172 glGetQueryObjectui64v(queries_[0], GL_QUERY_RESULT, &begin_stamp); | 182 glGetQueryObjectui64v(queries_[0], GL_QUERY_RESULT, &begin_stamp); |
| 173 glGetQueryObjectui64v(queries_[1], GL_QUERY_RESULT, &end_stamp); | 183 glGetQueryObjectui64v(queries_[1], GL_QUERY_RESULT, &end_stamp); |
| 174 | 184 |
| 175 start_time_ = (begin_stamp / base::Time::kNanosecondsPerMicrosecond) + | 185 start_time_ = (begin_stamp / base::Time::kNanosecondsPerMicrosecond) + |
| 176 offset_; | 186 offset_; |
| 177 end_time_ = (end_stamp / base::Time::kNanosecondsPerMicrosecond) + offset_; | 187 end_time_ = (end_stamp / base::Time::kNanosecondsPerMicrosecond) + offset_; |
| 178 outputter_->Trace(category(), name(), start_time_, end_time_); | 188 outputter_->Trace(category_, name_, start_time_, end_time_); |
| 179 } | 189 } |
| 180 | 190 |
| 181 GPUTracer::GPUTracer(gles2::GLES2Decoder* decoder) | 191 GPUTracer::GPUTracer(gles2::GLES2Decoder* decoder) |
| 182 : gpu_trace_srv_category(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED( | 192 : gpu_trace_srv_category(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED( |
| 183 TRACE_DISABLED_BY_DEFAULT("gpu.service"))), | 193 TRACE_DISABLED_BY_DEFAULT("gpu.service"))), |
| 184 gpu_trace_dev_category(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED( | 194 gpu_trace_dev_category(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED( |
| 185 TRACE_DISABLED_BY_DEFAULT("gpu.device"))), | 195 TRACE_DISABLED_BY_DEFAULT("gpu.device"))), |
| 186 decoder_(decoder), | 196 decoder_(decoder), |
| 187 timer_offset_(0), | 197 timer_offset_(0), |
| 188 last_tracer_source_(kTraceGroupInvalid), | |
| 189 tracer_type_(kTracerTypeInvalid), | 198 tracer_type_(kTracerTypeInvalid), |
| 190 gpu_timing_synced_(false), | 199 gpu_timing_synced_(false), |
| 191 gpu_executing_(false), | 200 gpu_executing_(false), |
| 192 process_posted_(false) { | 201 process_posted_(false) { |
| 193 if (gfx::g_driver_gl.ext.b_GL_EXT_disjoint_timer_query) { | 202 if (gfx::g_driver_gl.ext.b_GL_EXT_disjoint_timer_query) { |
| 194 tracer_type_ = kTracerTypeDisjointTimer; | 203 tracer_type_ = kTracerTypeDisjointTimer; |
| 195 outputter_ = TraceOutputter::Create("GL_EXT_disjoint_timer_query"); | 204 outputter_ = TraceOutputter::Create("GL_EXT_disjoint_timer_query"); |
| 196 } else if (gfx::g_driver_gl.ext.b_GL_ARB_timer_query) { | 205 } else if (gfx::g_driver_gl.ext.b_GL_ARB_timer_query) { |
| 197 tracer_type_ = kTracerTypeARBTimer; | 206 tracer_type_ = kTracerTypeARBTimer; |
| 198 outputter_ = TraceOutputter::Create("GL_ARB_timer_query"); | 207 outputter_ = TraceOutputter::Create("GL_ARB_timer_query"); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 230 } | 239 } |
| 231 | 240 |
| 232 bool GPUTracer::EndDecoding() { | 241 bool GPUTracer::EndDecoding() { |
| 233 if (!gpu_executing_) | 242 if (!gpu_executing_) |
| 234 return false; | 243 return false; |
| 235 | 244 |
| 236 // End Trace for all active markers | 245 // End Trace for all active markers |
| 237 if (IsTracing()) { | 246 if (IsTracing()) { |
| 238 for (int n = 0; n < NUM_TRACER_SOURCES; n++) { | 247 for (int n = 0; n < NUM_TRACER_SOURCES; n++) { |
| 239 for (size_t i = 0; i < markers_[n].size(); i++) { | 248 for (size_t i = 0; i < markers_[n].size(); i++) { |
| 240 if (markers_[n][i].trace_.get()) { | 249 TraceMarker& marker = markers_[n][i]; |
| 241 markers_[n][i].trace_->End(*gpu_trace_srv_category != 0); | 250 if (marker.trace_.get()) { |
| 242 if (markers_[n][i].trace_->IsEnabled()) | 251 marker.trace_->End(*gpu_trace_srv_category != 0); |
| 243 traces_.push_back(markers_[n][i].trace_); | 252 if (marker.trace_->IsEnabled()) |
| 253 traces_.push_back(marker.trace_); |
| 254 |
| 244 markers_[n][i].trace_ = 0; | 255 markers_[n][i].trace_ = 0; |
| 245 } | 256 } |
| 246 } | 257 } |
| 247 } | 258 } |
| 248 IssueProcessTask(); | 259 IssueProcessTask(); |
| 249 } | 260 } |
| 250 | 261 |
| 251 gpu_executing_ = false; | 262 gpu_executing_ = false; |
| 252 | 263 |
| 253 // NOTE(vmiura): glFlush() here can help give better trace results, | 264 // NOTE(vmiura): glFlush() here can help give better trace results, |
| 254 // but it distorts the normal device behavior. | 265 // but it distorts the normal device behavior. |
| 255 return true; | 266 return true; |
| 256 } | 267 } |
| 257 | 268 |
| 258 bool GPUTracer::Begin(const std::string& category, const std::string& name, | 269 bool GPUTracer::Begin(const std::string& category, const std::string& name, |
| 259 GpuTracerSource source) { | 270 GpuTracerSource source) { |
| 260 if (!gpu_executing_) | 271 if (!gpu_executing_) |
| 261 return false; | 272 return false; |
| 262 | 273 |
| 263 DCHECK(source >= 0 && source < NUM_TRACER_SOURCES); | 274 DCHECK(source >= 0 && source < NUM_TRACER_SOURCES); |
| 264 | 275 |
| 265 // Push new marker from given 'source' | 276 // Push new marker from given 'source' |
| 266 last_tracer_source_ = source; | |
| 267 markers_[source].push_back(TraceMarker(category, name)); | 277 markers_[source].push_back(TraceMarker(category, name)); |
| 268 | 278 |
| 269 // Create trace | 279 // Create trace |
| 270 if (IsTracing()) { | 280 if (IsTracing()) { |
| 271 scoped_refptr<GPUTrace> trace = CreateTrace(category, name); | 281 scoped_refptr<GPUTrace> trace = CreateTrace(category, name); |
| 272 trace->Start(*gpu_trace_srv_category != 0); | 282 trace->Start(*gpu_trace_srv_category != 0); |
| 273 markers_[source].back().trace_ = trace; | 283 markers_[source].back().trace_ = trace; |
| 274 } | 284 } |
| 275 | 285 |
| 276 return true; | 286 return true; |
| 277 } | 287 } |
| 278 | 288 |
| 279 bool GPUTracer::End(GpuTracerSource source) { | 289 bool GPUTracer::End(GpuTracerSource source) { |
| 280 if (!gpu_executing_) | 290 if (!gpu_executing_) |
| 281 return false; | 291 return false; |
| 282 | 292 |
| 283 DCHECK(source >= 0 && source < NUM_TRACER_SOURCES); | 293 DCHECK(source >= 0 && source < NUM_TRACER_SOURCES); |
| 284 | 294 |
| 285 // Pop last marker with matching 'source' | 295 // Pop last marker with matching 'source' |
| 286 if (!markers_[source].empty()) { | 296 if (!markers_[source].empty()) { |
| 297 TraceMarker& marker = markers_[source].back(); |
| 287 if (IsTracing()) { | 298 if (IsTracing()) { |
| 288 scoped_refptr<GPUTrace> trace = markers_[source].back().trace_; | 299 scoped_refptr<GPUTrace> trace = marker.trace_; |
| 289 if (trace.get()) { | 300 if (trace.get()) { |
| 290 trace->End(*gpu_trace_srv_category != 0); | 301 trace->End(*gpu_trace_srv_category != 0); |
| 291 if (trace->IsEnabled()) | 302 if (trace->IsEnabled()) |
| 292 traces_.push_back(trace); | 303 traces_.push_back(trace); |
| 293 IssueProcessTask(); | 304 IssueProcessTask(); |
| 294 } | 305 } |
| 295 } | 306 } |
| 296 | 307 |
| 297 markers_[source].pop_back(); | 308 markers_[source].pop_back(); |
| 298 return true; | 309 return true; |
| 299 } | 310 } |
| 300 return false; | 311 return false; |
| 301 } | 312 } |
| 302 | 313 |
| 303 bool GPUTracer::IsTracing() { | 314 bool GPUTracer::IsTracing() { |
| 304 return (*gpu_trace_srv_category != 0) || (*gpu_trace_dev_category != 0); | 315 return (*gpu_trace_srv_category != 0) || (*gpu_trace_dev_category != 0); |
| 305 } | 316 } |
| 306 | 317 |
| 307 const std::string& GPUTracer::CurrentCategory() const { | 318 const std::string& GPUTracer::CurrentCategory(GpuTracerSource source) const { |
| 308 if (last_tracer_source_ >= 0 && | 319 if (source >= 0 && |
| 309 last_tracer_source_ < NUM_TRACER_SOURCES && | 320 source < NUM_TRACER_SOURCES && |
| 310 !markers_[last_tracer_source_].empty()) { | 321 !markers_[source].empty()) { |
| 311 return markers_[last_tracer_source_].back().category_; | 322 return markers_[source].back().category_; |
| 312 } | 323 } |
| 313 return base::EmptyString(); | 324 return base::EmptyString(); |
| 314 } | 325 } |
| 315 | 326 |
| 316 const std::string& GPUTracer::CurrentName() const { | 327 const std::string& GPUTracer::CurrentName(GpuTracerSource source) const { |
| 317 if (last_tracer_source_ >= 0 && | 328 if (source >= 0 && |
| 318 last_tracer_source_ < NUM_TRACER_SOURCES && | 329 source < NUM_TRACER_SOURCES && |
| 319 !markers_[last_tracer_source_].empty()) { | 330 !markers_[source].empty()) { |
| 320 return markers_[last_tracer_source_].back().name_; | 331 return markers_[last_tracer_source_].back().name_; |
| 321 } | 332 } |
| 322 return base::EmptyString(); | 333 return base::EmptyString(); |
| 323 } | 334 } |
| 324 | 335 |
| 325 scoped_refptr<GPUTrace> GPUTracer::CreateTrace(const std::string& category, | 336 scoped_refptr<GPUTrace> GPUTracer::CreateTrace(const std::string& category, |
| 326 const std::string& name) { | 337 const std::string& name) { |
| 327 GpuTracerType tracer_type = *gpu_trace_dev_category ? tracer_type_ : | 338 GpuTracerType tracer_type = *gpu_trace_dev_category ? tracer_type_ : |
| 328 kTracerTypeInvalid; | 339 kTracerTypeInvalid; |
| 329 | 340 |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 415 | 426 |
| 416 process_posted_ = true; | 427 process_posted_ = true; |
| 417 base::MessageLoop::current()->PostDelayedTask( | 428 base::MessageLoop::current()->PostDelayedTask( |
| 418 FROM_HERE, | 429 FROM_HERE, |
| 419 base::Bind(&GPUTracer::Process, base::AsWeakPtr(this)), | 430 base::Bind(&GPUTracer::Process, base::AsWeakPtr(this)), |
| 420 base::TimeDelta::FromMilliseconds(kProcessInterval)); | 431 base::TimeDelta::FromMilliseconds(kProcessInterval)); |
| 421 } | 432 } |
| 422 | 433 |
| 423 } // namespace gles2 | 434 } // namespace gles2 |
| 424 } // namespace gpu | 435 } // namespace gpu |
| OLD | NEW |