Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(195)

Side by Side Diff: gpu/command_buffer/service/gpu_tracer.cc

Issue 11416117: Hookup the GPUTrace events. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Skip processing of no-op traces. Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "gpu/command_buffer/service/gpu_tracer.h"
6
7 #include <deque>
8
9 #include "base/bind.h"
10 #include "base/debug/trace_event.h"
11 #include "base/memory/weak_ptr.h"
12 #include "base/threading/thread.h"
13 #include "base/time.h"
14 #include "ui/gl/gl_bindings.h"
15
16 namespace gpu {
17 namespace gles2 {
18 namespace {
19
20 class Outputter;
21
22 static const unsigned int kProcessInterval = 16;
23 static Outputter* kOutputterThread = NULL;
24
25 class Outputter
26 : public base::Thread,
jonathan.backer 2012/12/07 15:38:11 nit: just an idea. maybe you want private inherita
dsinclair 2012/12/10 16:59:03 Done.
27 public base::RefCountedThreadSafe<Outputter> {
jonathan.backer 2012/12/07 15:38:11 nit: these don't need to be threadsafe anymore.
dsinclair 2012/12/10 16:59:03 Done.
28 public:
29 static scoped_refptr<Outputter> Create(const std::string& name) {
30 if (!kOutputterThread) {
31 kOutputterThread = new Outputter(name);
32 kOutputterThread->Start();
33 kOutputterThread->Stop();
34 }
35 return kOutputterThread;
36 }
37
38 private:
39 friend class base::RefCountedThreadSafe<Outputter>;
40
41 explicit Outputter(const std::string& name) : base::Thread(name.c_str()) {}
42
43 virtual ~Outputter() {
44 kOutputterThread = NULL;
45 }
46
47 DISALLOW_COPY_AND_ASSIGN(Outputter);
48 };
49
50 class Trace : public base::RefCountedThreadSafe<Trace> {
jonathan.backer 2012/12/07 15:38:11 nit: no need to be threadsafe.
dsinclair 2012/12/10 16:59:03 Done.
51 public:
52 explicit Trace(const std::string& name) : name_(name) {}
53
54 virtual void Start() = 0;
55 virtual void End() = 0;
56
57 // True if the the results of this query are available.
58 virtual bool IsAvailable() = 0;
59
60 virtual bool IsProcessable() { return true; }
61 virtual void Process() = 0;
62
63 virtual std::string name() {
jonathan.backer 2012/12/07 15:38:11 nit: return |const std::string&|?
dsinclair 2012/12/10 16:59:03 Done.
64 return name_;
65 }
66
67 protected:
68 virtual ~Trace() {}
69
70 private:
71 friend class base::RefCountedThreadSafe<Trace>;
72
73 std::string name_;
74
75 DISALLOW_COPY_AND_ASSIGN(Trace);
76 };
77
78 class GLARBTimerTrace : public Trace {
79 public:
80 GLARBTimerTrace(scoped_refptr<Outputter> output, const std::string& name,
81 int64 offset);
82
83 // Implementation of Tracer
84 virtual void Start() OVERRIDE;
85 virtual void End() OVERRIDE;
86 virtual bool IsAvailable() OVERRIDE;
87 virtual void Process() OVERRIDE;
88
89 private:
90 ~GLARBTimerTrace() OVERRIDE;
91
92 void Output();
93
94 scoped_refptr<Outputter> outputter_;
95
96 int64 offset_;
97 int64 start_time_;
98 int64 end_time_;
99
100 GLuint queries_[2];
101
102 DISALLOW_COPY_AND_ASSIGN(GLARBTimerTrace);
103 };
104
105 class NoopTrace : public Trace {
106 public:
107 explicit NoopTrace(const std::string& name) : Trace(name) {}
108
109 // Implementation of Tracer
110 virtual void Start() OVERRIDE {}
111 virtual void End() OVERRIDE {}
112 virtual bool IsAvailable() OVERRIDE { return true; }
113 virtual bool IsProcessable() OVERRIDE { return false; }
114 virtual void Process() OVERRIDE {}
115
116 private:
117 ~NoopTrace() {}
118
119 DISALLOW_COPY_AND_ASSIGN(NoopTrace);
120 };
121
122 class GPUTracerImpl
123 : public GPUTracer,
124 public base::SupportsWeakPtr<GPUTracerImpl> {
125 public:
126 GPUTracerImpl()
127 : gpu_category_enabled_(TRACE_EVENT_API_GET_CATEGORY_ENABLED("gpu")) {
128 }
129 virtual ~GPUTracerImpl() {}
130
131 // Implementation of gpu::gles2::GPUTracer
132 virtual bool Begin(const std::string& name) OVERRIDE;
133 virtual bool End() OVERRIDE;
134 virtual void Process() OVERRIDE;
135 virtual std::string CurrentName() const OVERRIDE;
136
137 protected:
138 // Create a new trace.
139 virtual scoped_refptr<Trace> CreateTrace(const std::string& name);
140
141 const unsigned char* gpu_category_enabled_;
142
143 private:
144 scoped_refptr<Trace> current_trace_;
145 std::deque<scoped_refptr<Trace> > traces_;
146
147 DISALLOW_COPY_AND_ASSIGN(GPUTracerImpl);
148 };
149
150 class GPUTracerARBTimerQuery : public GPUTracerImpl {
151 public:
152 GPUTracerARBTimerQuery();
153 virtual ~GPUTracerARBTimerQuery();
154
155 // Implementation of gpu::gles2::GPUTracer
156 virtual bool End() OVERRIDE;
157 virtual void Process() OVERRIDE;
158
159 private:
160 // Implementation of GPUTracerImpl.
161 virtual scoped_refptr<Trace> CreateTrace(const std::string& name) OVERRIDE;
162
163 void CalculateTimerOffset();
164
165 scoped_refptr<Outputter> outputter_;
166
167 int64 timer_offset_;
168 int64 last_offset_check_;
169 bool process_posted_;
170
171 DISALLOW_COPY_AND_ASSIGN(GPUTracerARBTimerQuery);
172 };
173
174 GLARBTimerTrace::GLARBTimerTrace(scoped_refptr<Outputter> output,
175 const std::string& name, int64 offset)
176 : Trace(name),
177 outputter_(output),
178 offset_(offset),
179 start_time_(0),
180 end_time_(0) {
181 glGenQueries(2, queries_);
182 }
183
184 GLARBTimerTrace::~GLARBTimerTrace() {
185 }
186
187 void GLARBTimerTrace::Start() {
188 glQueryCounter(queries_[0], GL_TIMESTAMP);
189 }
190
191 void GLARBTimerTrace::End() {
192 glQueryCounter(queries_[1], GL_TIMESTAMP);
193 }
194
195 bool GLARBTimerTrace::IsAvailable() {
196 GLint done = 0;
197 glGetQueryObjectiv(queries_[1], GL_QUERY_RESULT_AVAILABLE, &done);
jonathan.backer 2012/12/07 15:38:11 Just occurred to me, is there a problem if this is
dsinclair 2012/12/10 16:59:03 Done.
198 return !!done;
199 }
200
201 void GLARBTimerTrace::Process() {
202 DCHECK(IsAvailable());
203
204 GLint64 timestamp;
205
206 glGetQueryObjecti64v(queries_[0], GL_QUERY_RESULT, &timestamp);
207 start_time_ = (timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_;
208
209 glGetQueryObjecti64v(queries_[1], GL_QUERY_RESULT, &timestamp);
210 end_time_ = (timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_;
211
212 glDeleteQueries(2, queries_);
213
214 TRACE_EVENT_COPY_BEGIN_EXPLICIT0("gpu", name().c_str(),
215 outputter_->thread_id(), this, start_time_);
216 TRACE_EVENT_COPY_END_EXPLICIT0("gpu", name().c_str(), outputter_->thread_id(),
217 this, end_time_);
218 }
219
220 bool GPUTracerImpl::Begin(const std::string& name) {
221 // Make sure we are not nesting trace commands.
222 if (current_trace_.get())
jonathan.backer 2012/12/07 15:38:11 nit: do you need the get()?
dsinclair 2012/12/10 16:59:03 I believe so, current_trace_ exists, it just may n
dsinclair 2012/12/14 16:06:23 Done.
223 return false;
224
225 current_trace_ = CreateTrace(name);
226 current_trace_->Start();
227 return true;
228 }
229
230 bool GPUTracerImpl::End() {
231 if (!current_trace_.get())
jonathan.backer 2012/12/07 15:38:11 nit: need the get()?
dsinclair 2012/12/10 16:59:03 As above.
dsinclair 2012/12/14 16:06:23 Done.
232 return false;
233
234 current_trace_->End();
235 if (current_trace_->IsProcessable())
236 traces_.push_back(current_trace_);
237 current_trace_ = NULL;
238
239 return true;
240 }
241
242 void GPUTracerImpl::Process() {
243 while (!traces_.empty() && traces_.front()->IsAvailable()) {
244 traces_.front()->Process();
245 traces_.pop_front();
246 }
247 }
248
249 std::string GPUTracerImpl::CurrentName() const {
250 if (!current_trace_)
251 return std::string("");
252 return current_trace_->name();
253 }
254
255 scoped_refptr<Trace> GPUTracerImpl::CreateTrace(const std::string& name) {
256 return new NoopTrace(name);
257 }
258
259 GPUTracerARBTimerQuery::GPUTracerARBTimerQuery()
260 : GPUTracerImpl(),
261 timer_offset_(0),
262 last_offset_check_(0),
263 process_posted_(false) {
264 CalculateTimerOffset();
265 outputter_ = Outputter::Create("GL_ARB_timer_query");
266 }
267
268 GPUTracerARBTimerQuery::~GPUTracerARBTimerQuery() {
269 }
270
271 scoped_refptr<Trace> GPUTracerARBTimerQuery::CreateTrace(
272 const std::string& name) {
273 if (*gpu_category_enabled_)
274 return new GLARBTimerTrace(outputter_, name, timer_offset_);
275 return GPUTracerImpl::CreateTrace(name);
276 }
277
278 bool GPUTracerARBTimerQuery::End() {
279 bool ret = GPUTracerImpl::End();
280
281 if (!process_posted_) {
jonathan.backer 2012/12/07 15:38:11 seems like you want to move this to GPUTracerImpl
dsinclair 2012/12/10 16:59:03 Done.
282 process_posted_ = true;
283 MessageLoop::current()->PostDelayedTask(FROM_HERE,
284 base::Bind(&GPUTracerARBTimerQuery::Process, base::AsWeakPtr(this)),
285 base::TimeDelta::FromMilliseconds(kProcessInterval));
286 }
287
288 return ret;
289 }
290
291 void GPUTracerARBTimerQuery::Process() {
292 process_posted_ = false;
293 GPUTracerImpl::Process();
294
295 if (*gpu_category_enabled_ &&
296 (last_offset_check_ + base::Time::kMicrosecondsPerSecond) <
jonathan.backer 2012/12/07 15:38:11 doing this every microsecond?
dsinclair 2012/12/10 16:59:03 Every second.
297 base::TimeTicks::NowFromSystemTraceTime().ToInternalValue())
298 CalculateTimerOffset();
299 }
300
301 void GPUTracerARBTimerQuery::CalculateTimerOffset() {
302 TRACE_EVENT0("gpu", "CalculateTimerOffset");
303 // TODO(dsinclair): Change to glGetInteger64v.
304 GLuint64 gl_now = 0;
305 GLuint query;
306 glGenQueries(1, &query);
307
308 glQueryCounter(query, GL_TIMESTAMP);
309 glGetQueryObjectui64v(query, GL_QUERY_RESULT, &gl_now);
310 base::TimeTicks system_now = base::TimeTicks::NowFromSystemTraceTime();
311
312 gl_now /= base::Time::kNanosecondsPerMicrosecond;
313 timer_offset_ = system_now.ToInternalValue() - gl_now;
314 glDeleteQueries(1, &query);
315
316 last_offset_check_ = system_now.ToInternalValue();
317 }
318
319 } // namespace
320
321 scoped_ptr<GPUTracer> GPUTracer::Create() {
322 if (gfx::g_driver_gl.ext.b_GL_ARB_timer_query)
323 return scoped_ptr<GPUTracer>(new GPUTracerARBTimerQuery());
324 return scoped_ptr<GPUTracer>(new GPUTracerImpl());
325 }
326
327 } // namespace gles2
328 } // namespace gpu
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698