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

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: 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/string_util.h"
13 #include "base/threading/thread.h"
14 #include "base/time.h"
15 #include "ui/gl/gl_bindings.h"
16
17 namespace gpu {
18 namespace gles2 {
19 namespace {
20
21 class Outputter;
22
23 static const unsigned int kProcessInterval = 16;
24 static Outputter* kOutputterThread = NULL;
25
26 class Outputter
27 : private base::Thread,
28 public base::RefCounted<Outputter> {
29 public:
30 static scoped_refptr<Outputter> Create(const std::string& name) {
31 if (!kOutputterThread) {
32 kOutputterThread = new Outputter(name);
33 kOutputterThread->Start();
34 kOutputterThread->Stop();
35 }
36 return kOutputterThread;
37 }
38
39 uint64 Id() { return thread_id(); }
40
41 private:
42 friend class base::RefCounted<Outputter>;
43
44 explicit Outputter(const std::string& name) : base::Thread(name.c_str()) {}
45
46 virtual ~Outputter() {
47 kOutputterThread = 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 ~GLARBTimerTrace() OVERRIDE;
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
109 class NoopTrace : public Trace {
110 public:
111 explicit NoopTrace(const std::string& name) : Trace(name) {}
112
113 // Implementation of Tracer
114 virtual void Start() OVERRIDE {}
115 virtual void End() OVERRIDE {}
116 virtual bool IsAvailable() OVERRIDE { return true; }
117 virtual bool IsProcessable() OVERRIDE { return false; }
118 virtual void Process() OVERRIDE {}
119
120 private:
121 ~NoopTrace() {}
122
123 DISALLOW_COPY_AND_ASSIGN(NoopTrace);
124 };
125
126 class GPUTracerImpl
127 : public GPUTracer,
128 public base::SupportsWeakPtr<GPUTracerImpl> {
129 public:
130 GPUTracerImpl()
131 : gpu_category_enabled_(TRACE_EVENT_API_GET_CATEGORY_ENABLED("gpu")),
132 process_posted_(false) {
133 }
134 virtual ~GPUTracerImpl() {}
135
136 // Implementation of gpu::gles2::GPUTracer
137 virtual bool Begin(const std::string& name) OVERRIDE;
138 virtual bool End() OVERRIDE;
139 virtual const std::string& CurrentName() const OVERRIDE;
140
141 // Process any completed traces.
142 virtual void Process();
143
144 protected:
145 // Create a new trace.
146 virtual scoped_refptr<Trace> CreateTrace(const std::string& name);
147
148 const unsigned char* gpu_category_enabled_;
149
150 private:
151 void issue_process_task();
jonathan.backer 2012/12/14 20:48:29 I think the style guidelines are IssueProcessTask(
dsinclair 2012/12/14 21:26:04 Done.
152
153 scoped_refptr<Trace> current_trace_;
154 std::deque<scoped_refptr<Trace> > traces_;
155
156 bool process_posted_;
157
158 DISALLOW_COPY_AND_ASSIGN(GPUTracerImpl);
159 };
160
161 class GPUTracerARBTimerQuery : public GPUTracerImpl {
162 public:
163 GPUTracerARBTimerQuery();
164 virtual ~GPUTracerARBTimerQuery();
165
166 // Implementation of GPUTracerImpl
167 virtual void Process() OVERRIDE;
168
169 private:
170 // Implementation of GPUTracerImpl.
171 virtual scoped_refptr<Trace> CreateTrace(const std::string& name) OVERRIDE;
172
173 void CalculateTimerOffset();
174
175 scoped_refptr<Outputter> outputter_;
176
177 int64 timer_offset_;
178 int64 last_offset_check_;
179
180 DISALLOW_COPY_AND_ASSIGN(GPUTracerARBTimerQuery);
181 };
182
183 GLARBTimerTrace::GLARBTimerTrace(scoped_refptr<Outputter> outputter,
184 const std::string& name, int64 offset)
185 : Trace(name),
186 outputter_(outputter),
187 offset_(offset),
188 start_time_(0),
189 end_time_(0),
190 end_requested_(false) {
191 glGenQueries(2, queries_);
192 }
193
194 GLARBTimerTrace::~GLARBTimerTrace() {
195 }
196
197 void GLARBTimerTrace::Start() {
198 glQueryCounter(queries_[0], GL_TIMESTAMP);
199 }
200
201 void GLARBTimerTrace::End() {
202 glQueryCounter(queries_[1], GL_TIMESTAMP);
203 end_requested_ = true;
204 }
205
206 bool GLARBTimerTrace::IsAvailable() {
207 if (!end_requested_)
208 return false;
209
210 GLint done = 0;
211 glGetQueryObjectiv(queries_[1], GL_QUERY_RESULT_AVAILABLE, &done);
212 return !!done;
213 }
214
215 void GLARBTimerTrace::Process() {
216 DCHECK(IsAvailable());
217
218 GLint64 timestamp;
219
220 glGetQueryObjecti64v(queries_[0], GL_QUERY_RESULT, &timestamp);
221 start_time_ = (timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_;
222
223 glGetQueryObjecti64v(queries_[1], GL_QUERY_RESULT, &timestamp);
224 end_time_ = (timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_;
225
226 glDeleteQueries(2, queries_);
227
228 TRACE_EVENT_COPY_BEGIN_WITH_ID_TID_AND_TIMESTAMP0("gpu", name().c_str(),
229 this, outputter_->Id(), start_time_);
230 TRACE_EVENT_COPY_END_WITH_ID_TID_AND_TIMESTAMP0("gpu", name().c_str(),
231 this, outputter_->Id(), end_time_);
232 }
233
234 bool GPUTracerImpl::Begin(const std::string& name) {
235 // Make sure we are not nesting trace commands.
236 if (current_trace_)
237 return false;
238
239 current_trace_ = CreateTrace(name);
240 current_trace_->Start();
241 return true;
242 }
243
244 bool GPUTracerImpl::End() {
245 if (!current_trace_)
246 return false;
247
248 current_trace_->End();
249 if (current_trace_->IsProcessable())
250 traces_.push_back(current_trace_);
251 current_trace_ = NULL;
252
253 issue_process_task();
254 return true;
255 }
256
257 void GPUTracerImpl::Process() {
258 process_posted_ = false;
259
260 while (!traces_.empty() && traces_.front()->IsAvailable()) {
261 traces_.front()->Process();
262 traces_.pop_front();
263 }
264
265 issue_process_task();
266 }
267
268 const std::string& GPUTracerImpl::CurrentName() const {
269 if (!current_trace_)
270 return EmptyString();
271 return current_trace_->name();
272 }
273
274 scoped_refptr<Trace> GPUTracerImpl::CreateTrace(const std::string& name) {
275 return new NoopTrace(name);
276 }
277
278 void GPUTracerImpl::issue_process_task() {
279 if (traces_.empty() || process_posted_)
280 return;
281
282 process_posted_ = true;
283 MessageLoop::current()->PostDelayedTask(FROM_HERE,
284 base::Bind(&GPUTracerImpl::Process, base::AsWeakPtr(this)),
285 base::TimeDelta::FromMilliseconds(kProcessInterval));
286 }
287
288 GPUTracerARBTimerQuery::GPUTracerARBTimerQuery()
289 : GPUTracerImpl(),
290 timer_offset_(0),
291 last_offset_check_(0) {
292 CalculateTimerOffset();
293 outputter_ = Outputter::Create("GL_ARB_timer_query");
294 }
295
296 GPUTracerARBTimerQuery::~GPUTracerARBTimerQuery() {
297 }
298
299 scoped_refptr<Trace> GPUTracerARBTimerQuery::CreateTrace(
300 const std::string& name) {
301 if (*gpu_category_enabled_)
302 return new GLARBTimerTrace(outputter_, name, timer_offset_);
303 return GPUTracerImpl::CreateTrace(name);
304 }
305
306 void GPUTracerARBTimerQuery::Process() {
307 GPUTracerImpl::Process();
308
309 if (*gpu_category_enabled_ &&
310 (last_offset_check_ + base::Time::kMicrosecondsPerSecond) <
311 base::TimeTicks::NowFromSystemTraceTime().ToInternalValue())
312 CalculateTimerOffset();
313 }
314
315 void GPUTracerARBTimerQuery::CalculateTimerOffset() {
316 TRACE_EVENT0("gpu", "CalculateTimerOffset");
317 // TODO(dsinclair): Change to glGetInteger64v.
318 GLuint64 gl_now = 0;
319 GLuint query;
320 glGenQueries(1, &query);
321
322 glQueryCounter(query, GL_TIMESTAMP);
323 glGetQueryObjectui64v(query, GL_QUERY_RESULT, &gl_now);
324 base::TimeTicks system_now = base::TimeTicks::NowFromSystemTraceTime();
325
326 gl_now /= base::Time::kNanosecondsPerMicrosecond;
327 timer_offset_ = system_now.ToInternalValue() - gl_now;
328 glDeleteQueries(1, &query);
329
330 last_offset_check_ = system_now.ToInternalValue();
331 }
332
333 } // namespace
334
335 scoped_ptr<GPUTracer> GPUTracer::Create() {
336 if (gfx::g_driver_gl.ext.b_GL_ARB_timer_query)
337 return scoped_ptr<GPUTracer>(new GPUTracerARBTimerQuery());
338 return scoped_ptr<GPUTracer>(new GPUTracerImpl());
339 }
340
341 } // namespace gles2
342 } // namespace gpu
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698