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

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: Fixup TraceEnd test 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 : private base::Thread,
27 public base::RefCounted<Outputter> {
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::RefCounted<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::RefCounted<Trace> {
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 const std::string& name() {
64 return name_;
65 }
66
67 protected:
68 virtual ~Trace() {}
69
70 private:
71 friend class base::RefCounted<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,
jonathan.backer 2012/12/10 21:31:02 s/output/outputter
dsinclair 2012/12/14 16:06:23 Done.
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 bool end_requested_;
100
101 GLuint queries_[2];
102
103 DISALLOW_COPY_AND_ASSIGN(GLARBTimerTrace);
104 };
105
106 class NoopTrace : public Trace {
107 public:
108 explicit NoopTrace(const std::string& name) : Trace(name) {}
109
110 // Implementation of Tracer
111 virtual void Start() OVERRIDE {}
112 virtual void End() OVERRIDE {}
113 virtual bool IsAvailable() OVERRIDE { return true; }
114 virtual bool IsProcessable() OVERRIDE { return false; }
115 virtual void Process() OVERRIDE {}
116
117 private:
118 ~NoopTrace() {}
119
120 DISALLOW_COPY_AND_ASSIGN(NoopTrace);
121 };
122
123 class GPUTracerImpl
124 : public GPUTracer,
125 public base::SupportsWeakPtr<GPUTracerImpl> {
126 public:
127 GPUTracerImpl()
128 : gpu_category_enabled_(TRACE_EVENT_API_GET_CATEGORY_ENABLED("gpu")),
129 process_posted_(false) {
130 }
131 virtual ~GPUTracerImpl() {}
132
133 // Implementation of gpu::gles2::GPUTracer
134 virtual bool Begin(const std::string& name) OVERRIDE;
135 virtual bool End() OVERRIDE;
136 virtual void Process() OVERRIDE;
137 virtual std::string CurrentName() const OVERRIDE;
138
139 protected:
140 // Create a new trace.
141 virtual scoped_refptr<Trace> CreateTrace(const std::string& name);
142
143 const unsigned char* gpu_category_enabled_;
144
145 private:
146 scoped_refptr<Trace> current_trace_;
147 std::deque<scoped_refptr<Trace> > traces_;
148
149 bool process_posted_;
150
151 DISALLOW_COPY_AND_ASSIGN(GPUTracerImpl);
152 };
153
154 class GPUTracerARBTimerQuery : public GPUTracerImpl {
155 public:
156 GPUTracerARBTimerQuery();
157 virtual ~GPUTracerARBTimerQuery();
158
159 // Implementation of gpu::gles2::GPUTracer
160 virtual void Process() OVERRIDE;
161
162 private:
163 // Implementation of GPUTracerImpl.
164 virtual scoped_refptr<Trace> CreateTrace(const std::string& name) OVERRIDE;
165
166 void CalculateTimerOffset();
167
168 scoped_refptr<Outputter> outputter_;
169
170 int64 timer_offset_;
171 int64 last_offset_check_;
172
173 DISALLOW_COPY_AND_ASSIGN(GPUTracerARBTimerQuery);
174 };
175
176 GLARBTimerTrace::GLARBTimerTrace(scoped_refptr<Outputter> output,
177 const std::string& name, int64 offset)
178 : Trace(name),
179 outputter_(output),
180 offset_(offset),
181 start_time_(0),
182 end_time_(0),
183 end_requested_(false) {
184 glGenQueries(2, queries_);
185 }
186
187 GLARBTimerTrace::~GLARBTimerTrace() {
188 }
189
190 void GLARBTimerTrace::Start() {
191 glQueryCounter(queries_[0], GL_TIMESTAMP);
192 }
193
194 void GLARBTimerTrace::End() {
195 glQueryCounter(queries_[1], GL_TIMESTAMP);
196 end_requested_ = true;
197 }
198
199 bool GLARBTimerTrace::IsAvailable() {
200 if (!end_requested_)
201 return false;
202
203 GLint done = 0;
204 glGetQueryObjectiv(queries_[1], GL_QUERY_RESULT_AVAILABLE, &done);
205 return !!done;
206 }
207
208 void GLARBTimerTrace::Process() {
209 DCHECK(IsAvailable());
210
211 GLint64 timestamp;
212
213 glGetQueryObjecti64v(queries_[0], GL_QUERY_RESULT, &timestamp);
214 start_time_ = (timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_;
215
216 glGetQueryObjecti64v(queries_[1], GL_QUERY_RESULT, &timestamp);
217 end_time_ = (timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_;
218
219 glDeleteQueries(2, queries_);
220
221 /* TRACE_EVENT_COPY_BEGIN_EXPLICIT0("gpu", name().c_str(),
222 outputter_->thread_id(), this, start_time_);
jonathan.backer 2012/12/10 21:31:02 I'm not sure that the private inheritance did what
dsinclair 2012/12/14 16:06:23 Doh, the problem with have stuff you're going to r
223 TRACE_EVENT_COPY_END_EXPLICIT0("gpu", name().c_str(), outputter_->thread_id(),
224 this, end_time_);
225 */}
226
227 bool GPUTracerImpl::Begin(const std::string& name) {
228 // Make sure we are not nesting trace commands.
229 if (current_trace_)
230 return false;
231
232 current_trace_ = CreateTrace(name);
233 current_trace_->Start();
234 return true;
235 }
236
237 bool GPUTracerImpl::End() {
238 if (!current_trace_)
239 return false;
240
241 current_trace_->End();
242 if (current_trace_->IsProcessable())
243 traces_.push_back(current_trace_);
244 current_trace_ = NULL;
245
246 if (!process_posted_) {
jonathan.backer 2012/12/10 21:31:02 Maybe check that you have traces to process (in th
dsinclair 2012/12/14 16:06:23 Done.
247 process_posted_ = true;
248 MessageLoop::current()->PostDelayedTask(FROM_HERE,
249 base::Bind(&GPUTracerImpl::Process, base::AsWeakPtr(this)),
250 base::TimeDelta::FromMilliseconds(kProcessInterval));
251 }
252
253 return true;
254 }
255
256 void GPUTracerImpl::Process() {
257 process_posted_ = false;
258
259 while (!traces_.empty() && traces_.front()->IsAvailable()) {
260 traces_.front()->Process();
261 traces_.pop_front();
262 }
jonathan.backer 2012/12/10 21:31:02 Repost another delayed Process if the queue isn't
dsinclair 2012/12/14 16:06:23 Done.
263 }
264
265 std::string GPUTracerImpl::CurrentName() const {
266 if (!current_trace_)
267 return std::string("");
268 return current_trace_->name();
269 }
270
271 scoped_refptr<Trace> GPUTracerImpl::CreateTrace(const std::string& name) {
272 return new NoopTrace(name);
273 }
274
275 GPUTracerARBTimerQuery::GPUTracerARBTimerQuery()
276 : GPUTracerImpl(),
277 timer_offset_(0),
278 last_offset_check_(0) {
279 CalculateTimerOffset();
280 outputter_ = Outputter::Create("GL_ARB_timer_query");
281 }
282
283 GPUTracerARBTimerQuery::~GPUTracerARBTimerQuery() {
284 }
285
286 scoped_refptr<Trace> GPUTracerARBTimerQuery::CreateTrace(
287 const std::string& name) {
288 if (*gpu_category_enabled_)
289 return new GLARBTimerTrace(outputter_, name, timer_offset_);
290 return GPUTracerImpl::CreateTrace(name);
291 }
292
293 void GPUTracerARBTimerQuery::Process() {
294 GPUTracerImpl::Process();
295
296 if (*gpu_category_enabled_ &&
297 (last_offset_check_ + base::Time::kMicrosecondsPerSecond) <
298 base::TimeTicks::NowFromSystemTraceTime().ToInternalValue())
299 CalculateTimerOffset();
300 }
301
302 void GPUTracerARBTimerQuery::CalculateTimerOffset() {
303 TRACE_EVENT0("gpu", "CalculateTimerOffset");
304 // TODO(dsinclair): Change to glGetInteger64v.
305 GLuint64 gl_now = 0;
306 GLuint query;
307 glGenQueries(1, &query);
308
309 glQueryCounter(query, GL_TIMESTAMP);
310 glGetQueryObjectui64v(query, GL_QUERY_RESULT, &gl_now);
311 base::TimeTicks system_now = base::TimeTicks::NowFromSystemTraceTime();
312
313 gl_now /= base::Time::kNanosecondsPerMicrosecond;
314 timer_offset_ = system_now.ToInternalValue() - gl_now;
315 glDeleteQueries(1, &query);
316
317 last_offset_check_ = system_now.ToInternalValue();
318 }
319
320 } // namespace
321
322 scoped_ptr<GPUTracer> GPUTracer::Create() {
323 if (gfx::g_driver_gl.ext.b_GL_ARB_timer_query)
324 return scoped_ptr<GPUTracer>(new GPUTracerARBTimerQuery());
325 return scoped_ptr<GPUTracer>(new GPUTracerImpl());
326 }
327
328 } // namespace gles2
329 } // namespace gpu
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698