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

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: Re-calculate drift. 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/threading/thread.h"
12 #include "base/time.h"
13 #include "ui/gl/gl_bindings.h"
14
15 namespace gpu {
16 namespace gles2 {
17 namespace {
18
19 static const unsigned int kGPUTraceMaxQueueSize = 1024;
20
21 class Outputter
22 : public base::Thread,
23 public base::RefCountedThreadSafe<Outputter> {
24 public:
25 static scoped_refptr<Outputter> Create(const std::string& name) {
26 if (!g_outputter_thread) {
27 g_outputter_thread = new Outputter(name);
28 g_outputter_thread->Start();
29 }
30 return g_outputter_thread;
31 }
32
33 private:
34 explicit Outputter(const std::string& name) : base::Thread(name.c_str()) {}
35
36 virtual ~Outputter() {
37 g_outputter_thread->Stop();
38 g_outputter_thread = NULL;
39 }
40
41 static Outputter* g_outputter_thread;
42
43 friend class base::RefCountedThreadSafe<Outputter>;
44
45 DISALLOW_COPY_AND_ASSIGN(Outputter);
46 };
47
48 Outputter* Outputter::g_outputter_thread = NULL;
49
50 class Trace : public base::RefCountedThreadSafe<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 void Process() = 0;
61
62 virtual std::string name() {
63 return name_;
64 }
65
66 protected:
67 virtual ~Trace() {}
68
69 private:
70 friend class base::RefCountedThreadSafe<Trace>;
71
72 std::string name_;
73
74 DISALLOW_COPY_AND_ASSIGN(Trace);
75 };
76
77 class GLARBTimerTrace : public Trace {
78 public:
79 GLARBTimerTrace(scoped_refptr<Outputter> output, const std::string& name,
80 int64 offset);
81
82 // Implementation of Tracer
83 virtual void Start() OVERRIDE;
84 virtual void End() OVERRIDE;
85 virtual bool IsAvailable() OVERRIDE;
86 virtual void Process() OVERRIDE;
87
88 private:
89 ~GLARBTimerTrace() OVERRIDE;
90
91 void Output();
92
93 scoped_refptr<Outputter> outputter_;
94
95 int64 offset_;
96 int64 start_time_;
97 int64 end_time_;
98
99 GLuint queries_[2];
100
101 DISALLOW_COPY_AND_ASSIGN(GLARBTimerTrace);
102 };
103
104 class NoopTrace : public Trace {
105 public:
106 explicit NoopTrace(const std::string& name) : Trace(name) {}
107
108 // Implementation of Tracer
109 virtual void Start() OVERRIDE {}
110 virtual void End() OVERRIDE {}
111 virtual bool IsAvailable() OVERRIDE { return true; }
112 virtual void Process() OVERRIDE {}
113
114 private:
115 ~NoopTrace() {}
116
117 DISALLOW_COPY_AND_ASSIGN(NoopTrace);
118 };
119
120 class GPUTracerImpl : public GPUTracer {
121 public:
122 GPUTracerImpl()
123 : gpu_category_enabled_(TRACE_EVENT_API_GET_CATEGORY_ENABLED("gpu")) {
124 }
125 virtual ~GPUTracerImpl() {}
126
127 // Implementation of gpu::gles2::GPUTracer
128 virtual bool Begin(const std::string& name) OVERRIDE;
129 virtual bool End() OVERRIDE;
130 virtual void Process() OVERRIDE;
131 virtual std::string CurrentName() const OVERRIDE;
132
133 protected:
134 // Create a new trace.
135 virtual scoped_refptr<Trace> CreateTrace(const std::string& name);
136
137 scoped_refptr<Outputter> outputter_;
jonathan.backer 2012/12/03 18:29:32 Does this need an |outputter_|?
dsinclair 2012/12/03 21:40:04 Done.
138
139 const unsigned char* gpu_category_enabled_;
140
141 private:
142 scoped_refptr<Trace> current_trace_;
143 std::deque<scoped_refptr<Trace> > traces_;
144
145 DISALLOW_COPY_AND_ASSIGN(GPUTracerImpl);
146 };
147
148 class GPUTracerARBTimerQuery : public GPUTracerImpl {
149 public:
150 GPUTracerARBTimerQuery();
151 virtual ~GPUTracerARBTimerQuery();
152
153 // Implementation of gpu::gles2::GPUTracer
154 virtual void Process() OVERRIDE;
155
156 private:
157 // Implementation of GPUTracerImpl.
158 virtual scoped_refptr<Trace> CreateTrace(const std::string& name) OVERRIDE;
159
160 void CalculateTimerOffset();
161
162 int64 timer_offset_;
163 int64 last_offset_check_;
164
165 DISALLOW_COPY_AND_ASSIGN(GPUTracerARBTimerQuery);
166 };
167
168 GLARBTimerTrace::GLARBTimerTrace(scoped_refptr<Outputter> output,
169 const std::string& name, int64 offset)
170 : Trace(name),
171 outputter_(output),
172 offset_(offset),
173 start_time_(0),
174 end_time_(0) {
175 glGenQueries(2, queries_);
176 }
177
178 GLARBTimerTrace::~GLARBTimerTrace() {
179 }
180
181 void GLARBTimerTrace::Start() {
182 glQueryCounter(queries_[0], GL_TIMESTAMP);
183 }
184
185 void GLARBTimerTrace::End() {
186 glQueryCounter(queries_[1], GL_TIMESTAMP);
187 }
188
189 bool GLARBTimerTrace::IsAvailable() {
190 GLint done = 0;
191 glGetQueryObjectiv(queries_[1], GL_QUERY_RESULT_AVAILABLE, &done);
192 return !!done;
193 }
194
195 void GLARBTimerTrace::Process() {
196 DCHECK(IsAvailable());
197
198 GLint64 timestamp;
199
200 glGetQueryObjecti64v(queries_[0], GL_QUERY_RESULT, &timestamp);
201 start_time_ = (timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_;
202
203 glGetQueryObjecti64v(queries_[1], GL_QUERY_RESULT, &timestamp);
204 end_time_ = (timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_;
205
206 glDeleteQueries(2, queries_);
207
208 outputter_->message_loop()->PostTask(FROM_HERE,
209 base::Bind(&GLARBTimerTrace::Output, this));
210 }
211
212 void GLARBTimerTrace::Output() {
213 // TODO(dsinclair): Output TRACE_EVENT
214 }
215
216 bool GPUTracerImpl::Begin(const std::string& name) {
217 // Make sure we are not nesting trace commands.
218 if (current_trace_.get() != NULL)
219 return false;
220
221 current_trace_ = CreateTrace(name);
222 current_trace_->Start();
223 return true;
224 }
225
226 bool GPUTracerImpl::End() {
227 if (current_trace_.get() == NULL)
228 return false;
229
230 current_trace_->End();
231 traces_.push_back(current_trace_);
232 current_trace_ = NULL;
233
234 if (traces_.size() > kGPUTraceMaxQueueSize)
235 Process();
236
237 return true;
238 }
239
240 void GPUTracerImpl::Process() {
241 while (!traces_.empty() && traces_.front()->IsAvailable()) {
242 traces_.front()->Process();
243 traces_.pop_front();
244 }
245 }
246
247 std::string GPUTracerImpl::CurrentName() const {
248 if (current_trace_ == NULL)
249 return NULL;
250 return current_trace_->name();
251 }
252
253 scoped_refptr<Trace> GPUTracerImpl::CreateTrace(const std::string& name) {
254 return new NoopTrace(name);
255 }
256
257 GPUTracerARBTimerQuery::GPUTracerARBTimerQuery() : GPUTracerImpl() {
258 CalculateTimerOffset();
259 outputter_ = Outputter::Create("GL_ARB_timer_query");
260 }
261
262 GPUTracerARBTimerQuery::~GPUTracerARBTimerQuery() {
263 }
264
265 scoped_refptr<Trace> GPUTracerARBTimerQuery::CreateTrace(
266 const std::string& name) {
267 if (*gpu_category_enabled_) {
268 return new GLARBTimerTrace(outputter_, name, timer_offset_);
269 }
270 return GPUTracerImpl::CreateTrace(name);
271 }
272
273 void GPUTracerARBTimerQuery::Process() {
274 if (*gpu_category_enabled_ &&
275 (last_offset_check_ + base::Time::kMicrosecondsPerSecond) <
jonathan.backer 2012/12/03 18:29:32 How did you come up with this value? Is every 10s
dsinclair 2012/12/03 21:40:04 It was what I saw a couple of other examples using
276 base::TimeTicks::NowFromSystemTraceTime().ToInternalValue())
277 CalculateTimerOffset();
278
279 GPUTracerImpl::Process();
280 }
281
282 void GPUTracerARBTimerQuery::CalculateTimerOffset() {
283 TRACE_EVENT_BEGIN0("gpu", "CalculateTimerOffset");
jonathan.backer 2012/12/03 18:29:32 Just a regular TRACE_EVENT0?
dsinclair 2012/12/03 21:40:04 Done.
284 // TODO(dsinclair): Change to glGetInteger64v.
285 GLuint64 gl_now = 0;
286 GLuint query;
287 glGenQueries(1, &query);
288
289 glQueryCounter(query, GL_TIMESTAMP);
290 glGetQueryObjectui64v(query, GL_QUERY_RESULT, &gl_now);
291 base::TimeTicks system_now = base::TimeTicks::NowFromSystemTraceTime();
292
293 gl_now /= base::Time::kNanosecondsPerMicrosecond;
294 timer_offset_ = system_now.ToInternalValue() - gl_now;
295 glDeleteQueries(1, &query);
296
297 last_offset_check_ = system_now.ToInternalValue();
298 TRACE_EVENT_END0("gpu", "CalculateTimerOffset");
299 }
300
301 } // namespace
302
303 scoped_ptr<GPUTracer> GPUTracer::Create() {
304 if (gfx::g_driver_gl.ext.b_GL_ARB_timer_query)
305 return scoped_ptr<GPUTracer>(new GPUTracerARBTimerQuery());
306 return scoped_ptr<GPUTracer>(new GPUTracerImpl());
307 }
308
309 } // namespace gles2
310 } // namespace gpu
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698