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

Side by Side Diff: gpu/command_buffer/service/gpu_tracer.cc

Issue 419073008: Simplified GPU Tracer by removing parent base class. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Re-enabled gpu.service to use gl queries Created 6 years, 4 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
« no previous file with comments | « gpu/command_buffer/service/gpu_tracer.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "gpu/command_buffer/service/gpu_tracer.h" 5 #include "gpu/command_buffer/service/gpu_tracer.h"
6 6
7 #include <deque> 7 #include <deque>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/debug/trace_event.h" 10 #include "base/debug/trace_event.h"
11 #include "base/strings/string_util.h" 11 #include "base/strings/string_util.h"
12 #include "base/time/time.h" 12 #include "base/time/time.h"
13 #include "gpu/command_buffer/common/gles2_cmd_utils.h" 13 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
14 14
15 namespace gpu { 15 namespace gpu {
16 namespace gles2 { 16 namespace gles2 {
17 17
18 static const unsigned int kProcessInterval = 16; 18 static const unsigned int kProcessInterval = 16;
19 static TraceOutputter* g_outputter_thread = NULL; 19 static TraceOutputter* g_outputter_thread = NULL;
20 20
21 TraceMarker::TraceMarker(const std::string& name)
22 : name_(name),
23 trace_(NULL) {
24 }
25
26 TraceMarker::~TraceMarker() {
27 }
28
21 scoped_refptr<TraceOutputter> TraceOutputter::Create(const std::string& name) { 29 scoped_refptr<TraceOutputter> TraceOutputter::Create(const std::string& name) {
22 if (!g_outputter_thread) { 30 if (!g_outputter_thread) {
23 g_outputter_thread = new TraceOutputter(name); 31 g_outputter_thread = new TraceOutputter(name);
24 } 32 }
25 return g_outputter_thread; 33 return g_outputter_thread;
26 } 34 }
27 35
28 TraceOutputter::TraceOutputter(const std::string& name) 36 TraceOutputter::TraceOutputter(const std::string& name)
29 : named_thread_(name.c_str()), local_trace_id_(0) { 37 : named_thread_(name.c_str()), local_trace_id_(0) {
30 named_thread_.Start(); 38 named_thread_.Start();
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
121 glGetQueryObjectui64v(queries_[0], GL_QUERY_RESULT, &timestamp); 129 glGetQueryObjectui64v(queries_[0], GL_QUERY_RESULT, &timestamp);
122 start_time_ = (timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_; 130 start_time_ = (timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_;
123 131
124 glGetQueryObjectui64v(queries_[1], GL_QUERY_RESULT, &timestamp); 132 glGetQueryObjectui64v(queries_[1], GL_QUERY_RESULT, &timestamp);
125 end_time_ = (timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_; 133 end_time_ = (timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_;
126 134
127 glDeleteQueries(2, queries_); 135 glDeleteQueries(2, queries_);
128 outputter_->Trace(name(), start_time_, end_time_); 136 outputter_->Trace(name(), start_time_, end_time_);
129 } 137 }
130 138
131 struct TraceMarker { 139 GPUTracer::GPUTracer(gles2::GLES2Decoder* decoder)
132 TraceMarker(const std::string& name, GpuTracerSource source) 140 : gpu_trace_srv_category(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
133 : name_(name), source_(source) {} 141 TRACE_DISABLED_BY_DEFAULT("gpu.service"))),
142 gpu_trace_dev_category(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
143 TRACE_DISABLED_BY_DEFAULT("gpu.device"))),
144 decoder_(decoder),
145 timer_offset_(0),
146 last_tracer_source_(kTraceGroupInvalid),
147 enabled_(false),
148 gpu_timing_synced_(false),
149 gpu_executing_(false),
150 process_posted_(false) {
151 if (gfx::g_driver_gl.ext.b_GL_ARB_timer_query) {
152 outputter_ = TraceOutputter::Create("GL_ARB_timer_query");
153 enabled_ = true;
154 }
155 }
134 156
135 std::string name_; 157 GPUTracer::~GPUTracer() {
136 GpuTracerSource source_; 158 }
137 scoped_refptr<GPUTrace> trace_;
138 };
139 159
140 class GPUTracerImpl 160 bool GPUTracer::BeginDecoding() {
141 : public GPUTracer, 161 if (enabled_) {
142 public base::SupportsWeakPtr<GPUTracerImpl> { 162 if (*gpu_trace_dev_category) {
143 public: 163 // Make sure timing is synced before tracing
144 GPUTracerImpl() 164 if (!gpu_timing_synced_) {
145 : gpu_trace_srv_category(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED( 165 CalculateTimerOffset();
146 TRACE_DISABLED_BY_DEFAULT("gpu.service"))), 166 gpu_timing_synced_ = true;
147 gpu_trace_dev_category(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED( 167 }
148 TRACE_DISABLED_BY_DEFAULT("gpu.device"))), 168 } else {
149 gpu_executing_(false), 169 // If GPU device category is off, invalidate timing sync
150 process_posted_(false) {} 170 gpu_timing_synced_ = false;
151 virtual ~GPUTracerImpl() {} 171 }
172 }
152 173
153 // Implementation of gpu::gles2::GPUTracer
154 virtual bool BeginDecoding() OVERRIDE;
155 virtual bool EndDecoding() OVERRIDE;
156 virtual bool Begin(const std::string& name, GpuTracerSource source) OVERRIDE;
157 virtual bool End(GpuTracerSource source) OVERRIDE;
158 virtual const std::string& CurrentName() const OVERRIDE;
159 virtual bool IsTracing() OVERRIDE {
160 return (*gpu_trace_srv_category != 0) || (*gpu_trace_dev_category != 0);
161 }
162 virtual void CalculateTimerOffset() {}
163
164 // Process any completed traces.
165 virtual void Process();
166 virtual void ProcessTraces();
167
168 protected:
169 // Create a new trace.
170 virtual scoped_refptr<GPUTrace> CreateTrace(const std::string& name);
171
172 const unsigned char* gpu_trace_srv_category;
173 const unsigned char* gpu_trace_dev_category;
174
175 protected:
176 void IssueProcessTask();
177
178 std::vector<TraceMarker> markers_;
179 std::deque<scoped_refptr<GPUTrace> > traces_;
180
181 bool gpu_executing_;
182 bool process_posted_;
183
184 DISALLOW_COPY_AND_ASSIGN(GPUTracerImpl);
185 };
186
187 class GPUTracerARBTimerQuery : public GPUTracerImpl {
188 public:
189 explicit GPUTracerARBTimerQuery(gles2::GLES2Decoder* decoder);
190 virtual ~GPUTracerARBTimerQuery();
191
192 // Implementation of GPUTracerImpl
193 virtual void ProcessTraces() OVERRIDE;
194
195 protected:
196 // Implementation of GPUTracerImpl.
197 virtual bool BeginDecoding() OVERRIDE;
198 virtual bool EndDecoding() OVERRIDE;
199 virtual scoped_refptr<GPUTrace> CreateTrace(const std::string& name) OVERRIDE;
200 virtual void CalculateTimerOffset() OVERRIDE;
201
202 scoped_refptr<Outputter> outputter_;
203
204 bool gpu_timing_synced_;
205 int64 timer_offset_;
206
207 gles2::GLES2Decoder* decoder_;
208
209 DISALLOW_COPY_AND_ASSIGN(GPUTracerARBTimerQuery);
210 };
211
212 bool GPUTracerImpl::BeginDecoding() {
213 if (gpu_executing_) 174 if (gpu_executing_)
214 return false; 175 return false;
215 176
216 gpu_executing_ = true; 177 gpu_executing_ = true;
217 178
218 if (IsTracing()) { 179 if (IsTracing()) {
219 // Begin a Trace for all active markers 180 // Begin a Trace for all active markers
220 for (size_t i = 0; i < markers_.size(); i++) { 181 for (int n = 0; n < NUM_TRACER_SOURCES; n++) {
221 markers_[i].trace_ = CreateTrace(markers_[i].name_); 182 for (size_t i = 0; i < markers_[n].size(); i++) {
222 markers_[i].trace_->Start(); 183 markers_[n][i].trace_ = CreateTrace(markers_[n][i].name_);
184 markers_[n][i].trace_->Start();
185 }
223 } 186 }
224 } 187 }
225 return true; 188 return true;
226 } 189 }
227 190
228 bool GPUTracerImpl::EndDecoding() { 191 bool GPUTracer::EndDecoding() {
229 if (!gpu_executing_) 192 if (!gpu_executing_)
230 return false; 193 return false;
231 194
232 // End Trace for all active markers 195 // End Trace for all active markers
233 if (IsTracing()) { 196 if (IsTracing()) {
234 for (size_t i = 0; i < markers_.size(); i++) { 197 for (int n = 0; n < NUM_TRACER_SOURCES; n++) {
235 if (markers_[i].trace_) { 198 for (size_t i = 0; i < markers_[n].size(); i++) {
236 markers_[i].trace_->End(); 199 if (markers_[n][i].trace_) {
237 if (markers_[i].trace_->IsEnabled()) 200 markers_[n][i].trace_->End();
238 traces_.push_back(markers_[i].trace_); 201 if (markers_[n][i].trace_->IsEnabled())
239 markers_[i].trace_ = 0; 202 traces_.push_back(markers_[n][i].trace_);
203 markers_[n][i].trace_ = 0;
204 }
240 } 205 }
241 } 206 }
242 IssueProcessTask(); 207 IssueProcessTask();
243 } 208 }
244 209
245 gpu_executing_ = false; 210 gpu_executing_ = false;
211
212 // NOTE(vmiura): glFlush() here can help give better trace results,
213 // but it distorts the normal device behavior.
246 return true; 214 return true;
247 } 215 }
248 216
249 bool GPUTracerImpl::Begin(const std::string& name, GpuTracerSource source) { 217 bool GPUTracer::Begin(const std::string& name, GpuTracerSource source) {
250 if (!gpu_executing_) 218 if (!gpu_executing_)
251 return false; 219 return false;
252 220
221 DCHECK(source >= 0 && source < NUM_TRACER_SOURCES);
222
253 // Push new marker from given 'source' 223 // Push new marker from given 'source'
254 markers_.push_back(TraceMarker(name, source)); 224 last_tracer_source_ = source;
225 markers_[source].push_back(TraceMarker(name));
255 226
256 // Create trace 227 // Create trace
257 if (IsTracing()) { 228 if (IsTracing()) {
258 scoped_refptr<GPUTrace> trace = CreateTrace(name); 229 scoped_refptr<GPUTrace> trace = CreateTrace(name);
259 trace->Start(); 230 trace->Start();
260 markers_.back().trace_ = trace; 231 markers_[source].back().trace_ = trace;
261 } 232 }
233
262 return true; 234 return true;
263 } 235 }
264 236
265 bool GPUTracerImpl::End(GpuTracerSource source) { 237 bool GPUTracer::End(GpuTracerSource source) {
266 if (!gpu_executing_) 238 if (!gpu_executing_)
267 return false; 239 return false;
268 240
241 DCHECK(source >= 0 && source < NUM_TRACER_SOURCES);
242
269 // Pop last marker with matching 'source' 243 // Pop last marker with matching 'source'
270 for (int i = markers_.size() - 1; i >= 0; i--) { 244 if (!markers_[source].empty()) {
271 if (markers_[i].source_ == source) { 245 if (IsTracing()) {
272 // End trace 246 scoped_refptr<GPUTrace> trace = markers_[source].back().trace_;
273 if (IsTracing()) { 247 if (trace) {
274 scoped_refptr<GPUTrace> trace = markers_[i].trace_; 248 trace->End();
275 if (trace) { 249 if (trace->IsEnabled())
276 trace->End(); 250 traces_.push_back(trace);
277 if (trace->IsEnabled()) 251 IssueProcessTask();
278 traces_.push_back(trace);
279 IssueProcessTask();
280 }
281 } 252 }
253 }
282 254
283 markers_.erase(markers_.begin() + i); 255 markers_[source].pop_back();
284 return true; 256 return true;
285 }
286 } 257 }
287 return false; 258 return false;
288 } 259 }
289 260
290 void GPUTracerImpl::Process() { 261 bool GPUTracer::IsTracing() {
262 return (*gpu_trace_srv_category != 0) || (*gpu_trace_dev_category != 0);
263 }
264
265 const std::string& GPUTracer::CurrentName() const {
266 if (last_tracer_source_ >= 0 &&
267 last_tracer_source_ < NUM_TRACER_SOURCES &&
268 !markers_[last_tracer_source_].empty()) {
269 return markers_[last_tracer_source_].back().name_;
270 }
271 return base::EmptyString();
272 }
273
274 scoped_refptr<GPUTrace> GPUTracer::CreateTrace(const std::string& name) {
275 if (enabled_ && *gpu_trace_dev_category)
276 return new GPUTrace(outputter_, name, timer_offset_);
277 else
278 return new GPUTrace(name);
279 }
280
281 void GPUTracer::Process() {
291 process_posted_ = false; 282 process_posted_ = false;
292 ProcessTraces(); 283 ProcessTraces();
293 IssueProcessTask(); 284 IssueProcessTask();
294 } 285 }
295 286
296 void GPUTracerImpl::ProcessTraces() { 287 void GPUTracer::ProcessTraces() {
297 while (!traces_.empty() && traces_.front()->IsAvailable()) { 288 if (!enabled_) {
298 traces_.front()->Process(); 289 while (!traces_.empty() && traces_.front()->IsAvailable()) {
299 traces_.pop_front(); 290 traces_.front()->Process();
300 } 291 traces_.pop_front();
301 } 292 }
302
303 const std::string& GPUTracerImpl::CurrentName() const {
304 if (markers_.empty())
305 return base::EmptyString();
306 return markers_.back().name_;
307 }
308
309 scoped_refptr<GPUTrace> GPUTracerImpl::CreateTrace(
310 const std::string& name) {
311 return new GPUTrace(name);
312 }
313
314 void GPUTracerImpl::IssueProcessTask() {
315 if (traces_.empty() || process_posted_)
316 return; 293 return;
317
318 process_posted_ = true;
319 base::MessageLoop::current()->PostDelayedTask(
320 FROM_HERE,
321 base::Bind(&GPUTracerImpl::Process, base::AsWeakPtr(this)),
322 base::TimeDelta::FromMilliseconds(kProcessInterval));
323 }
324
325 GPUTracerARBTimerQuery::GPUTracerARBTimerQuery(gles2::GLES2Decoder* decoder)
326 : timer_offset_(0), decoder_(decoder) {
327 outputter_ = TraceOutputter::Create("GL_ARB_timer_query");
328 }
329
330 GPUTracerARBTimerQuery::~GPUTracerARBTimerQuery() {
331 }
332
333 scoped_refptr<GPUTrace> GPUTracerARBTimerQuery::CreateTrace(
334 const std::string& name) {
335 if (*gpu_trace_dev_category)
336 return new GPUTrace(outputter_, name, timer_offset_);
337 return GPUTracerImpl::CreateTrace(name);
338 }
339
340 bool GPUTracerARBTimerQuery::BeginDecoding() {
341 if (*gpu_trace_dev_category) {
342 // Make sure timing is synced before tracing
343 if (!gpu_timing_synced_) {
344 CalculateTimerOffset();
345 gpu_timing_synced_ = true;
346 }
347 } else {
348 // If GPU device category is off, invalidate timing sync
349 gpu_timing_synced_ = false;
350 } 294 }
351 295
352 return GPUTracerImpl::BeginDecoding(); 296 TRACE_EVENT0("gpu", "GPUTracer::ProcessTraces");
353 }
354
355 bool GPUTracerARBTimerQuery::EndDecoding() {
356 bool ret = GPUTracerImpl::EndDecoding();
357
358 // NOTE(vmiura_: glFlush() here can help give better trace results,
359 // but it distorts the normal device behavior.
360 return ret;
361 }
362
363 void GPUTracerARBTimerQuery::ProcessTraces() {
364 TRACE_EVENT0("gpu", "GPUTracerARBTimerQuery::ProcessTraces");
365 297
366 // Make owning decoder's GL context current 298 // Make owning decoder's GL context current
367 if (!decoder_->MakeCurrent()) { 299 if (!decoder_->MakeCurrent()) {
368 // Skip subsequent GL calls if MakeCurrent fails 300 // Skip subsequent GL calls if MakeCurrent fails
369 traces_.clear(); 301 traces_.clear();
370 return; 302 return;
371 } 303 }
372 304
373 while (!traces_.empty() && traces_.front()->IsAvailable()) { 305 while (!traces_.empty() && traces_.front()->IsAvailable()) {
374 traces_.front()->Process(); 306 traces_.front()->Process();
375 traces_.pop_front(); 307 traces_.pop_front();
376 } 308 }
377 309
378 // Clear pending traces if there were are any errors 310 // Clear pending traces if there were are any errors
379 GLenum err = glGetError(); 311 GLenum err = glGetError();
380 if (err != GL_NO_ERROR) 312 if (err != GL_NO_ERROR)
381 traces_.clear(); 313 traces_.clear();
382 } 314 }
383 315
384 void GPUTracerARBTimerQuery::CalculateTimerOffset() { 316 void GPUTracer::CalculateTimerOffset() {
385 TRACE_EVENT0("gpu", "GPUTracerARBTimerQuery::CalculateTimerOffset"); 317 if (enabled_) {
318 TRACE_EVENT0("gpu", "GPUTracer::CalculateTimerOffset");
386 319
387 // NOTE(vmiura): It would be better to use glGetInteger64v, however 320 // NOTE(vmiura): It would be better to use glGetInteger64v, however
388 // it's not available everywhere. 321 // it's not available everywhere.
389 GLuint64 gl_now = 0; 322 GLuint64 gl_now = 0;
390 GLuint query; 323 GLuint query;
391 glFinish(); 324 glFinish();
392 glGenQueries(1, &query); 325 glGenQueries(1, &query);
393 glQueryCounter(query, GL_TIMESTAMP); 326 glQueryCounter(query, GL_TIMESTAMP);
394 glFinish(); 327 glFinish();
395 glGetQueryObjectui64v(query, GL_QUERY_RESULT, &gl_now); 328 glGetQueryObjectui64v(query, GL_QUERY_RESULT, &gl_now);
396 base::TimeTicks system_now = base::TimeTicks::NowFromSystemTraceTime(); 329 base::TimeTicks system_now = base::TimeTicks::NowFromSystemTraceTime();
397 330
398 gl_now /= base::Time::kNanosecondsPerMicrosecond; 331 gl_now /= base::Time::kNanosecondsPerMicrosecond;
399 timer_offset_ = system_now.ToInternalValue() - gl_now; 332 timer_offset_ = system_now.ToInternalValue() - gl_now;
400 glDeleteQueries(1, &query); 333 glDeleteQueries(1, &query);
334 }
401 } 335 }
402 336
403 GPUTracer::GPUTracer() {} 337 void GPUTracer::IssueProcessTask() {
338 if (traces_.empty() || process_posted_)
339 return;
404 340
405 GPUTracer::~GPUTracer() {} 341 process_posted_ = true;
406 342 base::MessageLoop::current()->PostDelayedTask(
407 scoped_ptr<GPUTracer> GPUTracer::Create(gles2::GLES2Decoder* decoder) { 343 FROM_HERE,
408 if (gfx::g_driver_gl.ext.b_GL_ARB_timer_query) { 344 base::Bind(&GPUTracer::Process, base::AsWeakPtr(this)),
409 return scoped_ptr<GPUTracer>(new GPUTracerARBTimerQuery(decoder)); 345 base::TimeDelta::FromMilliseconds(kProcessInterval));
410 }
411 return scoped_ptr<GPUTracer>(new GPUTracerImpl());
412 } 346 }
413 347
414 } // namespace gles2 348 } // namespace gles2
415 } // namespace gpu 349 } // namespace gpu
OLDNEW
« no previous file with comments | « gpu/command_buffer/service/gpu_tracer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698