| 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/memory/weak_ptr.h" | |
| 12 #include "base/strings/string_util.h" | 11 #include "base/strings/string_util.h" |
| 13 #include "base/threading/thread.h" | |
| 14 #include "base/time/time.h" | 12 #include "base/time/time.h" |
| 15 #include "ui/gl/gl_bindings.h" | |
| 16 | 13 |
| 17 namespace gpu { | 14 namespace gpu { |
| 18 namespace gles2 { | 15 namespace gles2 { |
| 19 namespace { | |
| 20 | |
| 21 class Outputter; | |
| 22 | 16 |
| 23 static const unsigned int kProcessInterval = 16; | 17 static const unsigned int kProcessInterval = 16; |
| 24 static Outputter* g_outputter_thread = NULL; | 18 static TraceOutputter* g_outputter_thread = NULL; |
| 25 | 19 |
| 26 class Outputter | 20 scoped_refptr<TraceOutputter> TraceOutputter::Create(const std::string& name) { |
| 27 : private base::Thread, | 21 if (!g_outputter_thread) { |
| 28 public base::RefCounted<Outputter> { | 22 g_outputter_thread = new TraceOutputter(name); |
| 29 public: | |
| 30 static scoped_refptr<Outputter> Create(const std::string& name) { | |
| 31 if (!g_outputter_thread) { | |
| 32 g_outputter_thread = new Outputter(name); | |
| 33 g_outputter_thread->Start(); | |
| 34 g_outputter_thread->Stop(); | |
| 35 } | |
| 36 return g_outputter_thread; | |
| 37 } | 23 } |
| 24 return g_outputter_thread; |
| 25 } |
| 38 | 26 |
| 39 uint64 Id() { return thread_id(); } | 27 TraceOutputter::TraceOutputter(const std::string& name) |
| 28 : named_thread_(name.c_str()), local_trace_id_(0) { |
| 29 named_thread_.Start(); |
| 30 named_thread_.Stop(); |
| 31 } |
| 40 | 32 |
| 41 private: | 33 TraceOutputter::~TraceOutputter() { g_outputter_thread = NULL; } |
| 42 friend class base::RefCounted<Outputter>; | |
| 43 | 34 |
| 44 explicit Outputter(const std::string& name) : base::Thread(name.c_str()) {} | 35 void TraceOutputter::Trace(const std::string& name, |
| 45 | 36 int64 start_time, |
| 46 virtual ~Outputter() { | 37 int64 end_time) { |
| 47 g_outputter_thread = NULL; | 38 TRACE_EVENT_COPY_BEGIN_WITH_ID_TID_AND_TIMESTAMP0("gpu", |
| 48 } | 39 name.c_str(), |
| 49 | 40 local_trace_id_, |
| 50 DISALLOW_COPY_AND_ASSIGN(Outputter); | 41 named_thread_.thread_id(), |
| 51 }; | 42 start_time); |
| 52 | 43 TRACE_EVENT_COPY_END_WITH_ID_TID_AND_TIMESTAMP0("gpu", |
| 53 class Trace : public base::RefCounted<Trace> { | 44 name.c_str(), |
| 54 public: | 45 local_trace_id_, |
| 55 explicit Trace(const std::string& name) : name_(name) {} | 46 named_thread_.thread_id(), |
| 56 | 47 end_time); |
| 57 virtual void Start() = 0; | 48 ++local_trace_id_; |
| 58 virtual void End() = 0; | 49 } |
| 59 | |
| 60 // True if the the results of this query are available. | |
| 61 virtual bool IsAvailable() = 0; | |
| 62 | |
| 63 virtual bool IsProcessable() { return true; } | |
| 64 virtual void Process() = 0; | |
| 65 | |
| 66 virtual const std::string& name() { | |
| 67 return name_; | |
| 68 } | |
| 69 | |
| 70 protected: | |
| 71 virtual ~Trace() {} | |
| 72 | |
| 73 private: | |
| 74 friend class base::RefCounted<Trace>; | |
| 75 | |
| 76 std::string name_; | |
| 77 | |
| 78 DISALLOW_COPY_AND_ASSIGN(Trace); | |
| 79 }; | |
| 80 | |
| 81 class GLARBTimerTrace : public Trace { | |
| 82 public: | |
| 83 GLARBTimerTrace(scoped_refptr<Outputter> outputter, const std::string& name, | |
| 84 int64 offset); | |
| 85 | |
| 86 // Implementation of Tracer | |
| 87 virtual void Start() OVERRIDE; | |
| 88 virtual void End() OVERRIDE; | |
| 89 virtual bool IsAvailable() OVERRIDE; | |
| 90 virtual void Process() OVERRIDE; | |
| 91 | |
| 92 private: | |
| 93 virtual ~GLARBTimerTrace(); | |
| 94 | |
| 95 void Output(); | |
| 96 | |
| 97 scoped_refptr<Outputter> outputter_; | |
| 98 | |
| 99 int64 offset_; | |
| 100 int64 start_time_; | |
| 101 int64 end_time_; | |
| 102 bool end_requested_; | |
| 103 | |
| 104 GLuint queries_[2]; | |
| 105 | |
| 106 DISALLOW_COPY_AND_ASSIGN(GLARBTimerTrace); | |
| 107 }; | |
| 108 | 50 |
| 109 class NoopTrace : public Trace { | 51 class NoopTrace : public Trace { |
| 110 public: | 52 public: |
| 111 explicit NoopTrace(const std::string& name) : Trace(name) {} | 53 explicit NoopTrace(const std::string& name) : Trace(name) {} |
| 112 | 54 |
| 113 // Implementation of Tracer | 55 // Implementation of Tracer |
| 114 virtual void Start() OVERRIDE {} | 56 virtual void Start() OVERRIDE {} |
| 115 virtual void End() OVERRIDE {} | 57 virtual void End() OVERRIDE {} |
| 116 virtual bool IsAvailable() OVERRIDE { return true; } | 58 virtual bool IsAvailable() OVERRIDE { return true; } |
| 117 virtual bool IsProcessable() OVERRIDE { return false; } | 59 virtual bool IsProcessable() OVERRIDE { return false; } |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 174 void CalculateTimerOffset(); | 116 void CalculateTimerOffset(); |
| 175 | 117 |
| 176 scoped_refptr<Outputter> outputter_; | 118 scoped_refptr<Outputter> outputter_; |
| 177 | 119 |
| 178 int64 timer_offset_; | 120 int64 timer_offset_; |
| 179 int64 last_offset_check_; | 121 int64 last_offset_check_; |
| 180 | 122 |
| 181 DISALLOW_COPY_AND_ASSIGN(GPUTracerARBTimerQuery); | 123 DISALLOW_COPY_AND_ASSIGN(GPUTracerARBTimerQuery); |
| 182 }; | 124 }; |
| 183 | 125 |
| 126 bool Trace::IsProcessable() { return true; } |
| 127 |
| 128 const std::string& Trace::name() { return name_; } |
| 129 |
| 184 GLARBTimerTrace::GLARBTimerTrace(scoped_refptr<Outputter> outputter, | 130 GLARBTimerTrace::GLARBTimerTrace(scoped_refptr<Outputter> outputter, |
| 185 const std::string& name, int64 offset) | 131 const std::string& name, |
| 132 int64 offset) |
| 186 : Trace(name), | 133 : Trace(name), |
| 187 outputter_(outputter), | 134 outputter_(outputter), |
| 188 offset_(offset), | 135 offset_(offset), |
| 189 start_time_(0), | 136 start_time_(0), |
| 190 end_time_(0), | 137 end_time_(0), |
| 191 end_requested_(false) { | 138 end_requested_(false) { |
| 192 glGenQueries(2, queries_); | 139 glGenQueries(2, queries_); |
| 193 } | 140 } |
| 194 | 141 |
| 195 GLARBTimerTrace::~GLARBTimerTrace() { | 142 GLARBTimerTrace::~GLARBTimerTrace() { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 209 return false; | 156 return false; |
| 210 | 157 |
| 211 GLint done = 0; | 158 GLint done = 0; |
| 212 glGetQueryObjectiv(queries_[1], GL_QUERY_RESULT_AVAILABLE, &done); | 159 glGetQueryObjectiv(queries_[1], GL_QUERY_RESULT_AVAILABLE, &done); |
| 213 return !!done; | 160 return !!done; |
| 214 } | 161 } |
| 215 | 162 |
| 216 void GLARBTimerTrace::Process() { | 163 void GLARBTimerTrace::Process() { |
| 217 DCHECK(IsAvailable()); | 164 DCHECK(IsAvailable()); |
| 218 | 165 |
| 219 GLint64 timestamp; | 166 GLuint64 timestamp; |
| 220 | 167 |
| 221 // TODO(dsinclair): It's possible for the timer to wrap during the start/end. | 168 // TODO(dsinclair): It's possible for the timer to wrap during the start/end. |
| 222 // We need to detect if the end is less then the start and correct for the | 169 // We need to detect if the end is less then the start and correct for the |
| 223 // wrapping. | 170 // wrapping. |
| 224 glGetQueryObjecti64v(queries_[0], GL_QUERY_RESULT, ×tamp); | 171 glGetQueryObjectui64v(queries_[0], GL_QUERY_RESULT, ×tamp); |
| 225 start_time_ = (timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_; | 172 start_time_ = (timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_; |
| 226 | 173 |
| 227 glGetQueryObjecti64v(queries_[1], GL_QUERY_RESULT, ×tamp); | 174 glGetQueryObjectui64v(queries_[1], GL_QUERY_RESULT, ×tamp); |
| 228 end_time_ = (timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_; | 175 end_time_ = (timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_; |
| 229 | 176 |
| 230 glDeleteQueries(2, queries_); | 177 glDeleteQueries(2, queries_); |
| 231 | 178 outputter_->Trace(name(), start_time_, end_time_); |
| 232 TRACE_EVENT_COPY_BEGIN_WITH_ID_TID_AND_TIMESTAMP0("gpu", name().c_str(), | |
| 233 this, outputter_->Id(), start_time_); | |
| 234 TRACE_EVENT_COPY_END_WITH_ID_TID_AND_TIMESTAMP0("gpu", name().c_str(), | |
| 235 this, outputter_->Id(), end_time_); | |
| 236 } | 179 } |
| 237 | 180 |
| 238 bool GPUTracerImpl::Begin(const std::string& name) { | 181 bool GPUTracerImpl::Begin(const std::string& name) { |
| 239 // Make sure we are not nesting trace commands. | 182 // Make sure we are not nesting trace commands. |
| 240 if (current_trace_.get()) | 183 if (current_trace_.get()) |
| 241 return false; | 184 return false; |
| 242 | 185 |
| 243 current_trace_ = CreateTrace(name); | 186 current_trace_ = CreateTrace(name); |
| 244 current_trace_->Start(); | 187 current_trace_->Start(); |
| 245 return true; | 188 return true; |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 288 FROM_HERE, | 231 FROM_HERE, |
| 289 base::Bind(&GPUTracerImpl::Process, base::AsWeakPtr(this)), | 232 base::Bind(&GPUTracerImpl::Process, base::AsWeakPtr(this)), |
| 290 base::TimeDelta::FromMilliseconds(kProcessInterval)); | 233 base::TimeDelta::FromMilliseconds(kProcessInterval)); |
| 291 } | 234 } |
| 292 | 235 |
| 293 GPUTracerARBTimerQuery::GPUTracerARBTimerQuery() | 236 GPUTracerARBTimerQuery::GPUTracerARBTimerQuery() |
| 294 : GPUTracerImpl(), | 237 : GPUTracerImpl(), |
| 295 timer_offset_(0), | 238 timer_offset_(0), |
| 296 last_offset_check_(0) { | 239 last_offset_check_(0) { |
| 297 CalculateTimerOffset(); | 240 CalculateTimerOffset(); |
| 298 outputter_ = Outputter::Create("GL_ARB_timer_query"); | 241 outputter_ = TraceOutputter::Create("GL_ARB_timer_query"); |
| 299 } | 242 } |
| 300 | 243 |
| 301 GPUTracerARBTimerQuery::~GPUTracerARBTimerQuery() { | 244 GPUTracerARBTimerQuery::~GPUTracerARBTimerQuery() { |
| 302 } | 245 } |
| 303 | 246 |
| 304 scoped_refptr<Trace> GPUTracerARBTimerQuery::CreateTrace( | 247 scoped_refptr<Trace> GPUTracerARBTimerQuery::CreateTrace( |
| 305 const std::string& name) { | 248 const std::string& name) { |
| 306 if (*gpu_category_enabled_) | 249 if (*gpu_category_enabled_) |
| 307 return new GLARBTimerTrace(outputter_, name, timer_offset_); | 250 return new GLARBTimerTrace(outputter_, name, timer_offset_); |
| 308 return GPUTracerImpl::CreateTrace(name); | 251 return GPUTracerImpl::CreateTrace(name); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 328 glGetQueryObjectui64v(query, GL_QUERY_RESULT, &gl_now); | 271 glGetQueryObjectui64v(query, GL_QUERY_RESULT, &gl_now); |
| 329 base::TimeTicks system_now = base::TimeTicks::NowFromSystemTraceTime(); | 272 base::TimeTicks system_now = base::TimeTicks::NowFromSystemTraceTime(); |
| 330 | 273 |
| 331 gl_now /= base::Time::kNanosecondsPerMicrosecond; | 274 gl_now /= base::Time::kNanosecondsPerMicrosecond; |
| 332 timer_offset_ = system_now.ToInternalValue() - gl_now; | 275 timer_offset_ = system_now.ToInternalValue() - gl_now; |
| 333 glDeleteQueries(1, &query); | 276 glDeleteQueries(1, &query); |
| 334 | 277 |
| 335 last_offset_check_ = system_now.ToInternalValue(); | 278 last_offset_check_ = system_now.ToInternalValue(); |
| 336 } | 279 } |
| 337 | 280 |
| 338 } // namespace | |
| 339 | |
| 340 scoped_ptr<GPUTracer> GPUTracer::Create() { | 281 scoped_ptr<GPUTracer> GPUTracer::Create() { |
| 341 if (gfx::g_driver_gl.ext.b_GL_ARB_timer_query) | 282 if (gfx::g_driver_gl.ext.b_GL_ARB_timer_query) { |
| 342 return scoped_ptr<GPUTracer>(new GPUTracerARBTimerQuery()); | 283 return scoped_ptr<GPUTracer>(new GPUTracerARBTimerQuery()); |
| 284 } |
| 343 return scoped_ptr<GPUTracer>(new GPUTracerImpl()); | 285 return scoped_ptr<GPUTracer>(new GPUTracerImpl()); |
| 344 } | 286 } |
| 345 | 287 |
| 346 } // namespace gles2 | 288 } // namespace gles2 |
| 347 } // namespace gpu | 289 } // namespace gpu |
| OLD | NEW |