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

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: Update the autogen'd files. Created 7 years, 10 months 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
« no previous file with comments | « gpu/command_buffer/service/gpu_tracer.h ('k') | gpu/command_buffer_service.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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* g_outputter_thread = 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 (!g_outputter_thread) {
32 g_outputter_thread = new Outputter(name);
33 g_outputter_thread->Start();
34 g_outputter_thread->Stop();
35 }
36 return g_outputter_thread;
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 g_outputter_thread = 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();
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 IssueProcessTask();
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 // TODO(dsinclair): It's possible for the timer to wrap during the start/end.
221 // We need to detect if the end is less then the start and correct for the
222 // wrapping.
223 glGetQueryObjecti64v(queries_[0], GL_QUERY_RESULT, &timestamp);
224 start_time_ = (timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_;
225
226 glGetQueryObjecti64v(queries_[1], GL_QUERY_RESULT, &timestamp);
227 end_time_ = (timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_;
228
229 glDeleteQueries(2, queries_);
230
231 TRACE_EVENT_COPY_BEGIN_WITH_ID_TID_AND_TIMESTAMP0("gpu", name().c_str(),
232 this, outputter_->Id(), start_time_);
233 TRACE_EVENT_COPY_END_WITH_ID_TID_AND_TIMESTAMP0("gpu", name().c_str(),
234 this, outputter_->Id(), end_time_);
235 }
236
237 bool GPUTracerImpl::Begin(const std::string& name) {
238 // Make sure we are not nesting trace commands.
239 if (current_trace_)
240 return false;
241
242 current_trace_ = CreateTrace(name);
243 current_trace_->Start();
244 return true;
245 }
246
247 bool GPUTracerImpl::End() {
248 if (!current_trace_)
249 return false;
250
251 current_trace_->End();
252 if (current_trace_->IsProcessable())
253 traces_.push_back(current_trace_);
254 current_trace_ = NULL;
255
256 IssueProcessTask();
257 return true;
258 }
259
260 void GPUTracerImpl::Process() {
261 process_posted_ = false;
262
263 while (!traces_.empty() && traces_.front()->IsAvailable()) {
264 traces_.front()->Process();
265 traces_.pop_front();
266 }
267
268 IssueProcessTask();
269 }
270
271 const std::string& GPUTracerImpl::CurrentName() const {
272 if (!current_trace_)
273 return EmptyString();
274 return current_trace_->name();
275 }
276
277 scoped_refptr<Trace> GPUTracerImpl::CreateTrace(const std::string& name) {
278 return new NoopTrace(name);
279 }
280
281 void GPUTracerImpl::IssueProcessTask() {
282 if (traces_.empty() || process_posted_)
283 return;
284
285 process_posted_ = true;
286 MessageLoop::current()->PostDelayedTask(FROM_HERE,
287 base::Bind(&GPUTracerImpl::Process, base::AsWeakPtr(this)),
288 base::TimeDelta::FromMilliseconds(kProcessInterval));
289 }
290
291 GPUTracerARBTimerQuery::GPUTracerARBTimerQuery()
292 : GPUTracerImpl(),
293 timer_offset_(0),
294 last_offset_check_(0) {
295 CalculateTimerOffset();
296 outputter_ = Outputter::Create("GL_ARB_timer_query");
297 }
298
299 GPUTracerARBTimerQuery::~GPUTracerARBTimerQuery() {
300 }
301
302 scoped_refptr<Trace> GPUTracerARBTimerQuery::CreateTrace(
303 const std::string& name) {
304 if (*gpu_category_enabled_)
305 return new GLARBTimerTrace(outputter_, name, timer_offset_);
306 return GPUTracerImpl::CreateTrace(name);
307 }
308
309 void GPUTracerARBTimerQuery::Process() {
310 GPUTracerImpl::Process();
311
312 if (*gpu_category_enabled_ &&
313 (last_offset_check_ + base::Time::kMicrosecondsPerSecond) <
314 base::TimeTicks::NowFromSystemTraceTime().ToInternalValue())
315 CalculateTimerOffset();
316 }
317
318 void GPUTracerARBTimerQuery::CalculateTimerOffset() {
319 TRACE_EVENT0("gpu", "CalculateTimerOffset");
320 // TODO(dsinclair): Change to glGetInteger64v.
321 GLuint64 gl_now = 0;
322 GLuint query;
323 glGenQueries(1, &query);
324
325 glQueryCounter(query, GL_TIMESTAMP);
326 glGetQueryObjectui64v(query, GL_QUERY_RESULT, &gl_now);
327 base::TimeTicks system_now = base::TimeTicks::NowFromSystemTraceTime();
328
329 gl_now /= base::Time::kNanosecondsPerMicrosecond;
330 timer_offset_ = system_now.ToInternalValue() - gl_now;
331 glDeleteQueries(1, &query);
332
333 last_offset_check_ = system_now.ToInternalValue();
334 }
335
336 } // namespace
337
338 scoped_ptr<GPUTracer> GPUTracer::Create() {
339 if (gfx::g_driver_gl.ext.b_GL_ARB_timer_query)
340 return scoped_ptr<GPUTracer>(new GPUTracerARBTimerQuery());
341 return scoped_ptr<GPUTracer>(new GPUTracerImpl());
342 }
343
344 } // namespace gles2
345 } // namespace gpu
OLDNEW
« no previous file with comments | « gpu/command_buffer/service/gpu_tracer.h ('k') | gpu/command_buffer_service.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698