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

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
« 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 #include <stack>
9
10 #include "base/bind.h"
11 #include "base/debug/trace_event.h"
12 #include "base/threading/non_thread_safe.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 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 protected:
jonathan.backer 2012/11/30 20:25:45 private?
dsinclair 2012/11/30 21:51:41 Done.
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 private:
46 friend class base::RefCounted<Outputter>;
47
48 DISALLOW_COPY_AND_ASSIGN(Outputter);
49 };
50 Outputter* Outputter::g_outputter_thread = NULL;
jonathan.backer 2012/11/30 20:25:45 nit: newline?
dsinclair 2012/11/30 21:51:41 Done.
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(scoped_refptr<Outputter> output) = 0;
jonathan.backer 2012/11/30 20:25:45 I'd just pass this in the constructor and hold a r
dsinclair 2012/11/30 21:51:41 Done.
61
62 protected:
63 explicit Trace(const std::string& name) : name_(name) {}
64 virtual ~Trace() {};
65
66 const char* name() {
67 return name_.c_str();
jonathan.backer 2012/11/30 20:25:45 Do we need this for the no-op?
dsinclair 2012/11/30 21:51:41 Yes, we'll need to use this to get the name for th
68 }
69
70 private:
71 friend class base::RefCountedThreadSafe<Trace>;
72
73 std::string name_;
74
75 DISALLOW_COPY_AND_ASSIGN(Trace);
76 };
77
78 class GLARBTimerTrace : public Trace {
79 public:
80 explicit GLARBTimerTrace(const std::string& name, int64 offset);
jonathan.backer 2012/11/30 20:25:45 no longer need explicit
dsinclair 2012/11/30 21:51:41 Done.
81
jonathan.backer 2012/11/30 20:25:45 // Implementation of gpu::Tracer.
dsinclair 2012/11/30 21:51:41 Done.
82 void Start() OVERRIDE;
jonathan.backer 2012/11/30 20:25:45 still virtual.
dsinclair 2012/11/30 21:51:41 Done.
83 void End() OVERRIDE;
84 bool IsAvailable() OVERRIDE;
85 void Process(scoped_refptr<Outputter> output) OVERRIDE;
86
87 private:
88 ~GLARBTimerTrace() OVERRIDE;
89
90 void Output();
91
92 int64 offset_;
93 int64 start_time_;
94 int64 end_time_;
95
96 unsigned int start_timer_;
97 unsigned int end_timer_;
98
99 DISALLOW_COPY_AND_ASSIGN(GLARBTimerTrace);
100 };
101
102 class NoopTrace : public Trace {
103 public:
104 NoopTrace(const std::string& name) : Trace(name) {}
jonathan.backer 2012/11/30 20:25:45 explicit
dsinclair 2012/11/30 21:51:41 Done.
105
106 void Start() {}
jonathan.backer 2012/11/30 20:25:45 see above
dsinclair 2012/11/30 21:51:41 Done.
107 void End() {}
108
109 bool IsAvailable() { return true; }
110 void Process(scoped_refptr<Outputter> output) {}
111
112 private:
113 ~NoopTrace() {}
114
115 DISALLOW_COPY_AND_ASSIGN(NoopTrace);
116 };
117
118 class GPUTracerImpl : public GPUTracer {
jonathan.backer 2012/11/30 20:25:45 I know that you want to future proof, but are we g
dsinclair 2012/11/30 21:51:41 I think so, there is nothing ARB_timer_query speci
119 public:
120 GPUTracerImpl()
121 : gpu_category_enabled_(TRACE_EVENT_API_GET_CATEGORY_ENABLED("gpu")) {
122 }
123 virtual ~GPUTracerImpl() {}
124
125 // Begin a trace.
jonathan.backer 2012/11/30 20:25:45 // Implementation of gpu::GPUTracer.
dsinclair 2012/11/30 21:51:41 Done.
126 virtual bool Begin(const std::string& name) OVERRIDE;
127
128 // End the last started trace.
129 virtual bool End() OVERRIDE;
130
131 // Process any completed traces.
132 virtual void Process() OVERRIDE;
133
134 protected:
135 // Create a new trace.
136 virtual scoped_refptr<Trace> CreateTrace(const std::string& name);
137
138 scoped_refptr<Outputter> output_;
139
140 const unsigned char* gpu_category_enabled_;
141
142 private:
143 scoped_refptr<Trace> current_trace_;
144 std::deque<scoped_refptr<Trace> > traces_;
145
146 DISALLOW_COPY_AND_ASSIGN(GPUTracerImpl);
147 };
148
149 class GPUTracerARBTimerQuery : public GPUTracerImpl {
150 public:
151 GPUTracerARBTimerQuery();
152 ~GPUTracerARBTimerQuery();
153
154 scoped_refptr<Trace> CreateTrace(const std::string& name);
155
156 private:
157 int64 timer_offset_;
158
159 DISALLOW_COPY_AND_ASSIGN(GPUTracerARBTimerQuery);
160 };
161
162 GPUTracerARBTimerQuery::GPUTracerARBTimerQuery() : GPUTracerImpl() {
jonathan.backer 2012/11/30 20:25:45 I think that we list all the class declarations an
dsinclair 2012/11/30 21:51:41 Done.
163 // TODO(dsinclair): This offset can drift, we should move to another thread
164 // in order to re-calculate the drift every second-ish.
165 // TODO(dsinclair): Change to glGetInteger64v.
166 GLuint64 gl_now = 0;
167 GLuint query;
168 glGenQueries(1, &query);
169
170 glQueryCounter(query, GL_TIMESTAMP);
171 glGetQueryObjectui64v(query, GL_QUERY_RESULT, &gl_now);
172 glDeleteQueries(1, &query);
173
174 gl_now /= base::Time::kNanosecondsPerMicrosecond;
175 base::TimeTicks system_now = base::TimeTicks::NowFromSystemTraceTime();
176 timer_offset_ = system_now.ToInternalValue() - gl_now;
177
178 output_ = Outputter::Create("GL_ARB_timer_query");
179 }
180
181 GPUTracerARBTimerQuery::~GPUTracerARBTimerQuery() {
182 }
183
184 scoped_refptr<Trace> GPUTracerARBTimerQuery::CreateTrace(
185 const std::string& name) {
186 if (*gpu_category_enabled_)
187 return new GLARBTimerTrace(name, timer_offset_);
188 return GPUTracerImpl::CreateTrace(name);
189 }
190
191 GLARBTimerTrace::GLARBTimerTrace(const std::string& name, int64 offset)
192 : Trace(name),
193 offset_(offset),
194 start_time_(0),
195 end_time_(0),
196 start_timer_(0),
197 end_timer_(0) {
198 GLuint queries[2];
199 glGenQueries(2, queries);
200
201 start_timer_ = queries[0];
202 end_timer_ = queries[1];
203 }
204
205 GLARBTimerTrace::~GLARBTimerTrace() {
206 }
207
208 void GLARBTimerTrace::Start() {
209 glQueryCounter(start_timer_, GL_TIMESTAMP);
210 }
211
212 void GLARBTimerTrace::End() {
213 glQueryCounter(end_timer_, GL_TIMESTAMP);
214 }
215
216 bool GLARBTimerTrace::IsAvailable() {
217 GLint done = 0;
218 glGetQueryObjectiv(end_timer_, GL_QUERY_RESULT_AVAILABLE, &done);
219 return !!done;
220 }
221
222 void GLARBTimerTrace::Process(scoped_refptr<Outputter> output) {
jonathan.backer 2012/11/30 20:25:45 DCHECK(IsAvailable())?
dsinclair 2012/11/30 21:51:41 Done.
223 GLint64 timestamp;
224
225 glGetQueryObjecti64v(start_timer_, GL_QUERY_RESULT, &timestamp);
226 start_time_ = (timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_;
227
228 glGetQueryObjecti64v(end_timer_, GL_QUERY_RESULT, &timestamp);
229 end_time_ = (timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_;
230
231 GLuint queries[] = {start_timer_, end_timer_};
232 glDeleteQueries(2, queries);
233
234 output->message_loop()->PostTask(FROM_HERE,
235 base::Bind(&GLARBTimerTrace::Output, this));
236 }
237
238 void GLARBTimerTrace::Output() {
239 // TODO(dsinclair): Output TRACE_EVENT
240 }
241
242 bool GPUTracerImpl::Begin(const std::string& name) {
243 // Make sure we are not nesting trace commands.
244 if (current_trace_.get() != NULL)
245 return false;
246
247 current_trace_ = CreateTrace(name);
248 current_trace_->Start();
249 return true;
250 }
251
252 bool GPUTracerImpl::End() {
253 if (current_trace_.get() == NULL) {
254 return false;
255 }
jonathan.backer 2012/11/30 20:25:45 nit: braces
dsinclair 2012/11/30 21:51:41 Done.
256
257 current_trace_->End();
258 traces_.push_back(current_trace_);
259 current_trace_ = NULL;
260
261 if (traces_.size() > kGPUTraceMaxQueueSize)
262 Process();
263
264 return true;
265 }
266
267 void GPUTracerImpl::Process() {
268 while (!traces_.empty() && traces_.front()->IsAvailable()) {
269 traces_.front()->Process(output_);
270 traces_.pop_front();
271 }
272 }
273
274 scoped_refptr<Trace> GPUTracerImpl::CreateTrace(const std::string& name) {
275 return new NoopTrace(name);
276 }
277
278 } // namespace
279
280 scoped_ptr<GPUTracer> GPUTracer::Create() {
281 if (gfx::g_driver_gl.ext.b_GL_ARB_timer_query)
282 return scoped_ptr<GPUTracer>(new GPUTracerARBTimerQuery());
283 return scoped_ptr<GPUTracer>(NULL);
284 }
285
286 } // namespace gles2
287 } // 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