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

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 #include <stack>
jonathan.backer 2012/12/03 14:23:14 necessary?
dsinclair 2012/12/03 16:47:42 Done.
9
10 #include "base/bind.h"
11 #include "base/debug/trace_event.h"
12 #include "base/threading/non_thread_safe.h"
jonathan.backer 2012/12/03 14:23:14 necessary?
dsinclair 2012/12/03 16:47:42 Done.
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 static const unsigned int kGPUTraceMaxQueueSize = 1024;
22
23 class Outputter
24 : public base::Thread,
25 public base::RefCounted<Outputter> {
26 public:
27 static scoped_refptr<Outputter> Create(const std::string& name) {
28 if (!g_outputter_thread) {
29 g_outputter_thread = new Outputter(name);
30 g_outputter_thread->Start();
31 }
32 return g_outputter_thread;
33 }
34
35 private:
36 explicit Outputter(const std::string& name) : base::Thread(name.c_str()) {}
37
38 virtual ~Outputter() {
39 g_outputter_thread->Stop();
40 g_outputter_thread = NULL;
41 }
42
43 static Outputter* g_outputter_thread;
44
45 friend class base::RefCounted<Outputter>;
46
47 DISALLOW_COPY_AND_ASSIGN(Outputter);
48 };
49
50 Outputter* Outputter::g_outputter_thread = NULL;
51
52 class Trace : public base::RefCountedThreadSafe<Trace> {
53 public:
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 const char* name() {
63 return name_.c_str();
64 }
65
jonathan.backer 2012/12/03 14:23:14 nit: extra new-line
dsinclair 2012/12/03 16:47:42 Done.
66
67 protected:
jonathan.backer 2012/12/03 14:23:14 private? I don't see why you'd want to subclass th
dsinclair 2012/12/03 16:47:42 Done.
68 explicit Trace(const std::string& name) : name_(name) {}
69 virtual ~Trace() {};
jonathan.backer 2012/12/03 14:23:14 semi-colon?
dsinclair 2012/12/03 16:47:42 Done.
70
71 private:
72 friend class base::RefCountedThreadSafe<Trace>;
73
74 std::string name_;
75
76 DISALLOW_COPY_AND_ASSIGN(Trace);
77 };
78
79 class GLARBTimerTrace : public Trace {
80 public:
81 GLARBTimerTrace(scoped_refptr<Outputter> output, const std::string& name,
82 int64 offset);
83
84 // Implementation of Tracer
85 virtual void Start() OVERRIDE;
86 virtual void End() OVERRIDE;
87 virtual bool IsAvailable() OVERRIDE;
88 virtual void Process() OVERRIDE;
89
90 private:
91 ~GLARBTimerTrace() OVERRIDE;
92
93 void Output();
94
95 scoped_refptr<Outputter> output_;
jonathan.backer 2012/12/03 14:23:14 nit: s/output_/outputter_? I think that instances
dsinclair 2012/12/03 16:47:42 Done.
96
97 int64 offset_;
98 int64 start_time_;
99 int64 end_time_;
100
101 unsigned int start_timer_;
102 unsigned int end_timer_;
103
104 DISALLOW_COPY_AND_ASSIGN(GLARBTimerTrace);
105 };
106
107 class NoopTrace : public Trace {
108 public:
109 explicit NoopTrace(const std::string& name) : Trace(name) {}
110
111 // Implementation of Tracer
112 virtual void Start() OVERRIDE {}
113 virtual void End() OVERRIDE {}
114 virtual bool IsAvailable() OVERRIDE { return true; }
115 virtual void Process() OVERRIDE {}
116
117 private:
118 ~NoopTrace() {}
119
120 DISALLOW_COPY_AND_ASSIGN(NoopTrace);
121 };
122
123 class GPUTracerImpl : public GPUTracer {
124 public:
125 GPUTracerImpl()
126 : gpu_category_enabled_(TRACE_EVENT_API_GET_CATEGORY_ENABLED("gpu")) {
127 }
128 virtual ~GPUTracerImpl() {}
129
130 // Implementation of gpu::gles2::GPUTracer
131 virtual bool Begin(const std::string& name) OVERRIDE;
132 virtual bool End() OVERRIDE;
133 virtual void Process() OVERRIDE;
134 virtual const char* CurrentName() OVERRIDE;
135
136 protected:
137 // Create a new trace.
138 virtual scoped_refptr<Trace> CreateTrace(const std::string& name);
139
140 scoped_refptr<Outputter> output_;
141
142 const unsigned char* gpu_category_enabled_;
143
144 private:
145 scoped_refptr<Trace> current_trace_;
146 std::deque<scoped_refptr<Trace> > traces_;
147
148 DISALLOW_COPY_AND_ASSIGN(GPUTracerImpl);
149 };
150
151 class GPUTracerARBTimerQuery : public GPUTracerImpl {
152 public:
153 GPUTracerARBTimerQuery();
154 virtual ~GPUTracerARBTimerQuery();
155
156 // Implementation of GPUTracerImpl.
157 virtual scoped_refptr<Trace> CreateTrace(const std::string& name) OVERRIDE;
jonathan.backer 2012/12/03 14:23:14 why did this become public? seems like it should b
dsinclair 2012/12/03 16:47:42 Done.
158
159 private:
160 int64 timer_offset_;
161
162 DISALLOW_COPY_AND_ASSIGN(GPUTracerARBTimerQuery);
163 };
164
165 GLARBTimerTrace::GLARBTimerTrace(scoped_refptr<Outputter> output,
166 const std::string& name, int64 offset)
167 : Trace(name),
168 output_(output),
169 offset_(offset),
170 start_time_(0),
171 end_time_(0),
172 start_timer_(0),
173 end_timer_(0) {
174 GLuint queries[2];
175 glGenQueries(2, queries);
176
177 start_timer_ = queries[0];
178 end_timer_ = queries[1];
179 }
180
181 GLARBTimerTrace::~GLARBTimerTrace() {
182 }
183
184 void GLARBTimerTrace::Start() {
185 glQueryCounter(start_timer_, GL_TIMESTAMP);
186 }
187
188 void GLARBTimerTrace::End() {
189 glQueryCounter(end_timer_, GL_TIMESTAMP);
190 }
191
192 bool GLARBTimerTrace::IsAvailable() {
193 GLint done = 0;
194 glGetQueryObjectiv(end_timer_, GL_QUERY_RESULT_AVAILABLE, &done);
195 return !!done;
196 }
197
198 void GLARBTimerTrace::Process() {
199 DCHECK(IsAvailable());
200
201 GLint64 timestamp;
202
203 glGetQueryObjecti64v(start_timer_, GL_QUERY_RESULT, &timestamp);
204 start_time_ = (timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_;
205
206 glGetQueryObjecti64v(end_timer_, GL_QUERY_RESULT, &timestamp);
207 end_time_ = (timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_;
208
209 GLuint queries[] = {start_timer_, end_timer_};
jonathan.backer 2012/12/03 14:23:14 nit: maybe just store the timer ids in an array to
dsinclair 2012/12/03 16:47:42 Done.
210 glDeleteQueries(2, queries);
211
212 output_->message_loop()->PostTask(FROM_HERE,
213 base::Bind(&GLARBTimerTrace::Output, this));
214 }
215
216 void GLARBTimerTrace::Output() {
217 // TODO(dsinclair): Output TRACE_EVENT
218 }
219
220 bool GPUTracerImpl::Begin(const std::string& name) {
221 // Make sure we are not nesting trace commands.
222 if (current_trace_.get() != NULL)
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() == NULL)
232 return false;
233
234 current_trace_->End();
235 traces_.push_back(current_trace_);
236 current_trace_ = NULL;
237
238 if (traces_.size() > kGPUTraceMaxQueueSize)
239 Process();
240
241 return true;
242 }
243
244 void GPUTracerImpl::Process() {
245 while (!traces_.empty() && traces_.front()->IsAvailable()) {
246 traces_.front()->Process();
247 traces_.pop_front();
248 }
249 }
250
251 const char* GPUTracerImpl::CurrentName() {
252 if (current_trace_ == NULL)
253 return NULL;
254 return current_trace_->name();
255 }
256
257 scoped_refptr<Trace> GPUTracerImpl::CreateTrace(const std::string& name) {
258 return new NoopTrace(name);
259 }
260
261 GPUTracerARBTimerQuery::GPUTracerARBTimerQuery() : GPUTracerImpl() {
262 // TODO(dsinclair): This offset can drift, we should move to another thread
263 // in order to re-calculate the drift every second-ish.
264 // TODO(dsinclair): Change to glGetInteger64v.
265 GLuint64 gl_now = 0;
266 GLuint query;
267 glGenQueries(1, &query);
268
269 glQueryCounter(query, GL_TIMESTAMP);
270 glGetQueryObjectui64v(query, GL_QUERY_RESULT, &gl_now);
271 glDeleteQueries(1, &query);
jonathan.backer 2012/12/03 14:23:14 seems like we should get |system_now| as close as
dsinclair 2012/12/03 16:47:42 Done.
272
273 gl_now /= base::Time::kNanosecondsPerMicrosecond;
274 base::TimeTicks system_now = base::TimeTicks::NowFromSystemTraceTime();
275 timer_offset_ = system_now.ToInternalValue() - gl_now;
276
277 output_ = Outputter::Create("GL_ARB_timer_query");
278 }
279
280 GPUTracerARBTimerQuery::~GPUTracerARBTimerQuery() {
281 }
282
283 scoped_refptr<Trace> GPUTracerARBTimerQuery::CreateTrace(
284 const std::string& name) {
285 if (*gpu_category_enabled_)
286 return new GLARBTimerTrace(output_, name, timer_offset_);
287 return GPUTracerImpl::CreateTrace(name);
288 }
289
290 } // namespace
291
292 scoped_ptr<GPUTracer> GPUTracer::Create() {
293 if (gfx::g_driver_gl.ext.b_GL_ARB_timer_query)
294 return scoped_ptr<GPUTracer>(new GPUTracerARBTimerQuery());
295 return scoped_ptr<GPUTracer>(new GPUTracerImpl());
296 }
297
298 } // namespace gles2
299 } // namespace gpu
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698