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: | 23 g_outputter_thread->Start(); |
30 static scoped_refptr<Outputter> Create(const std::string& name) { | 24 g_outputter_thread->Stop(); |
piman
2014/01/07 22:47:49
Are we really creating a thread just to get a uniq
vmiura
2014/01/07 23:26:47
Yep :/. This thread use is not part of my change
| |
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 } | 25 } |
26 return g_outputter_thread; | |
27 } | |
38 | 28 |
39 uint64 Id() { return thread_id(); } | 29 TraceOutputter::TraceOutputter(const std::string& name) |
30 : base::Thread(name.c_str()), | |
31 local_trace_id_(0) { | |
32 } | |
40 | 33 |
41 private: | 34 TraceOutputter::~TraceOutputter() { |
42 friend class base::RefCounted<Outputter>; | 35 g_outputter_thread = NULL; |
36 } | |
43 | 37 |
44 explicit Outputter(const std::string& name) : base::Thread(name.c_str()) {} | 38 void TraceOutputter::Trace(const std::string& name, |
39 int64 start_time, | |
piman
2014/01/07 22:47:49
nit: indentation ('int64' needs to be right under
vmiura
2014/01/07 23:26:47
Done.
| |
40 int64 end_time) { | |
41 TRACE_EVENT_COPY_BEGIN_WITH_ID_TID_AND_TIMESTAMP0("gpu", name.c_str(), | |
42 local_trace_id_, thread_id(), start_time); | |
piman
2014/01/07 22:47:49
nit: indentation for the line continuation (either
vmiura
2014/01/07 23:26:47
Done.
| |
43 TRACE_EVENT_COPY_END_WITH_ID_TID_AND_TIMESTAMP0("gpu", name.c_str(), | |
44 local_trace_id_, thread_id(), end_time); | |
piman
2014/01/07 22:47:49
nit: indentation
vmiura
2014/01/07 23:26:47
Done.
| |
45 ++local_trace_id_; | |
46 } | |
45 | 47 |
46 virtual ~Outputter() { | |
47 g_outputter_thread = NULL; | |
48 } | |
49 | |
50 DISALLOW_COPY_AND_ASSIGN(Outputter); | |
51 }; | |
52 | |
53 class Trace : public base::RefCounted<Trace> { | |
54 public: | |
55 explicit Trace(const std::string& name) : name_(name) {} | |
56 | |
57 virtual void Start() = 0; | |
58 virtual void End() = 0; | |
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 | 48 |
109 class NoopTrace : public Trace { | 49 class NoopTrace : public Trace { |
110 public: | 50 public: |
111 explicit NoopTrace(const std::string& name) : Trace(name) {} | 51 explicit NoopTrace(const std::string& name) : Trace(name) {} |
112 | 52 |
113 // Implementation of Tracer | 53 // Implementation of Tracer |
114 virtual void Start() OVERRIDE {} | 54 virtual void Start() OVERRIDE {} |
115 virtual void End() OVERRIDE {} | 55 virtual void End() OVERRIDE {} |
116 virtual bool IsAvailable() OVERRIDE { return true; } | 56 virtual bool IsAvailable() OVERRIDE { return true; } |
117 virtual bool IsProcessable() OVERRIDE { return false; } | 57 virtual bool IsProcessable() OVERRIDE { return false; } |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
174 void CalculateTimerOffset(); | 114 void CalculateTimerOffset(); |
175 | 115 |
176 scoped_refptr<Outputter> outputter_; | 116 scoped_refptr<Outputter> outputter_; |
177 | 117 |
178 int64 timer_offset_; | 118 int64 timer_offset_; |
179 int64 last_offset_check_; | 119 int64 last_offset_check_; |
180 | 120 |
181 DISALLOW_COPY_AND_ASSIGN(GPUTracerARBTimerQuery); | 121 DISALLOW_COPY_AND_ASSIGN(GPUTracerARBTimerQuery); |
182 }; | 122 }; |
183 | 123 |
184 GLARBTimerTrace::GLARBTimerTrace(scoped_refptr<Outputter> outputter, | 124 bool Trace::IsProcessable() { |
185 const std::string& name, int64 offset) | 125 return true; |
126 } | |
127 | |
128 const std::string& Trace::name() { | |
129 return name_; | |
130 } | |
131 | |
132 GLARBTimerTrace::GLARBTimerTrace( | |
133 scoped_refptr<Outputter> outputter, | |
134 const std::string& name, int64 offset) | |
186 : Trace(name), | 135 : Trace(name), |
187 outputter_(outputter), | 136 outputter_(outputter), |
188 offset_(offset), | 137 offset_(offset), |
189 start_time_(0), | 138 start_time_(0), |
190 end_time_(0), | 139 end_time_(0), |
191 end_requested_(false) { | 140 end_requested_(false) { |
192 glGenQueries(2, queries_); | 141 glGenQueries(2, queries_); |
193 } | 142 } |
194 | 143 |
195 GLARBTimerTrace::~GLARBTimerTrace() { | 144 GLARBTimerTrace::~GLARBTimerTrace() { |
(...skipping 13 matching lines...) Expand all Loading... | |
209 return false; | 158 return false; |
210 | 159 |
211 GLint done = 0; | 160 GLint done = 0; |
212 glGetQueryObjectiv(queries_[1], GL_QUERY_RESULT_AVAILABLE, &done); | 161 glGetQueryObjectiv(queries_[1], GL_QUERY_RESULT_AVAILABLE, &done); |
213 return !!done; | 162 return !!done; |
214 } | 163 } |
215 | 164 |
216 void GLARBTimerTrace::Process() { | 165 void GLARBTimerTrace::Process() { |
217 DCHECK(IsAvailable()); | 166 DCHECK(IsAvailable()); |
218 | 167 |
219 GLint64 timestamp; | 168 GLuint64 timestamp; |
220 | 169 |
221 // TODO(dsinclair): It's possible for the timer to wrap during the start/end. | 170 // 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 | 171 // We need to detect if the end is less then the start and correct for the |
223 // wrapping. | 172 // wrapping. |
224 glGetQueryObjecti64v(queries_[0], GL_QUERY_RESULT, ×tamp); | 173 glGetQueryObjectui64v(queries_[0], GL_QUERY_RESULT, ×tamp); |
225 start_time_ = (timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_; | 174 start_time_ = (timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_; |
226 | 175 |
227 glGetQueryObjecti64v(queries_[1], GL_QUERY_RESULT, ×tamp); | 176 glGetQueryObjectui64v(queries_[1], GL_QUERY_RESULT, ×tamp); |
228 end_time_ = (timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_; | 177 end_time_ = (timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_; |
229 | 178 |
230 glDeleteQueries(2, queries_); | 179 glDeleteQueries(2, queries_); |
231 | 180 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 } | 181 } |
237 | 182 |
238 bool GPUTracerImpl::Begin(const std::string& name) { | 183 bool GPUTracerImpl::Begin(const std::string& name) { |
239 // Make sure we are not nesting trace commands. | 184 // Make sure we are not nesting trace commands. |
240 if (current_trace_.get()) | 185 if (current_trace_.get()) |
241 return false; | 186 return false; |
242 | 187 |
243 current_trace_ = CreateTrace(name); | 188 current_trace_ = CreateTrace(name); |
244 current_trace_->Start(); | 189 current_trace_->Start(); |
245 return true; | 190 return true; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
288 FROM_HERE, | 233 FROM_HERE, |
289 base::Bind(&GPUTracerImpl::Process, base::AsWeakPtr(this)), | 234 base::Bind(&GPUTracerImpl::Process, base::AsWeakPtr(this)), |
290 base::TimeDelta::FromMilliseconds(kProcessInterval)); | 235 base::TimeDelta::FromMilliseconds(kProcessInterval)); |
291 } | 236 } |
292 | 237 |
293 GPUTracerARBTimerQuery::GPUTracerARBTimerQuery() | 238 GPUTracerARBTimerQuery::GPUTracerARBTimerQuery() |
294 : GPUTracerImpl(), | 239 : GPUTracerImpl(), |
295 timer_offset_(0), | 240 timer_offset_(0), |
296 last_offset_check_(0) { | 241 last_offset_check_(0) { |
297 CalculateTimerOffset(); | 242 CalculateTimerOffset(); |
298 outputter_ = Outputter::Create("GL_ARB_timer_query"); | 243 outputter_ = TraceOutputter::Create("GL_ARB_timer_query"); |
299 } | 244 } |
300 | 245 |
301 GPUTracerARBTimerQuery::~GPUTracerARBTimerQuery() { | 246 GPUTracerARBTimerQuery::~GPUTracerARBTimerQuery() { |
302 } | 247 } |
303 | 248 |
304 scoped_refptr<Trace> GPUTracerARBTimerQuery::CreateTrace( | 249 scoped_refptr<Trace> GPUTracerARBTimerQuery::CreateTrace( |
305 const std::string& name) { | 250 const std::string& name) { |
306 if (*gpu_category_enabled_) | 251 if (*gpu_category_enabled_) |
307 return new GLARBTimerTrace(outputter_, name, timer_offset_); | 252 return new GLARBTimerTrace(outputter_, name, timer_offset_); |
308 return GPUTracerImpl::CreateTrace(name); | 253 return GPUTracerImpl::CreateTrace(name); |
(...skipping 19 matching lines...) Expand all Loading... | |
328 glGetQueryObjectui64v(query, GL_QUERY_RESULT, &gl_now); | 273 glGetQueryObjectui64v(query, GL_QUERY_RESULT, &gl_now); |
329 base::TimeTicks system_now = base::TimeTicks::NowFromSystemTraceTime(); | 274 base::TimeTicks system_now = base::TimeTicks::NowFromSystemTraceTime(); |
330 | 275 |
331 gl_now /= base::Time::kNanosecondsPerMicrosecond; | 276 gl_now /= base::Time::kNanosecondsPerMicrosecond; |
332 timer_offset_ = system_now.ToInternalValue() - gl_now; | 277 timer_offset_ = system_now.ToInternalValue() - gl_now; |
333 glDeleteQueries(1, &query); | 278 glDeleteQueries(1, &query); |
334 | 279 |
335 last_offset_check_ = system_now.ToInternalValue(); | 280 last_offset_check_ = system_now.ToInternalValue(); |
336 } | 281 } |
337 | 282 |
338 } // namespace | |
339 | |
340 scoped_ptr<GPUTracer> GPUTracer::Create() { | 283 scoped_ptr<GPUTracer> GPUTracer::Create() { |
341 if (gfx::g_driver_gl.ext.b_GL_ARB_timer_query) | 284 if (gfx::g_driver_gl.ext.b_GL_ARB_timer_query) { |
342 return scoped_ptr<GPUTracer>(new GPUTracerARBTimerQuery()); | 285 return scoped_ptr<GPUTracer>(new GPUTracerARBTimerQuery()); |
286 } | |
343 return scoped_ptr<GPUTracer>(new GPUTracerImpl()); | 287 return scoped_ptr<GPUTracer>(new GPUTracerImpl()); |
344 } | 288 } |
345 | 289 |
346 } // namespace gles2 | 290 } // namespace gles2 |
347 } // namespace gpu | 291 } // namespace gpu |
OLD | NEW |