OLD | NEW |
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/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
78 void TraceOutputter::TraceServiceEnd(const std::string& category, | 78 void TraceOutputter::TraceServiceEnd(const std::string& category, |
79 const std::string& name) { | 79 const std::string& name) { |
80 TRACE_EVENT_COPY_END1(TRACE_DISABLED_BY_DEFAULT("gpu.service"), | 80 TRACE_EVENT_COPY_END1(TRACE_DISABLED_BY_DEFAULT("gpu.service"), |
81 name.c_str(), "gl_category", category.c_str()); | 81 name.c_str(), "gl_category", category.c_str()); |
82 } | 82 } |
83 | 83 |
84 GPUTrace::GPUTrace(scoped_refptr<Outputter> outputter, | 84 GPUTrace::GPUTrace(scoped_refptr<Outputter> outputter, |
85 gfx::GPUTimingClient* gpu_timing_client, | 85 gfx::GPUTimingClient* gpu_timing_client, |
86 const std::string& category, | 86 const std::string& category, |
87 const std::string& name, | 87 const std::string& name, |
88 const bool enabled) | 88 const bool tracing_service, |
| 89 const bool tracing_device) |
89 : category_(category), | 90 : category_(category), |
90 name_(name), | 91 name_(name), |
91 outputter_(outputter), | 92 outputter_(outputter), |
92 enabled_(enabled) { | 93 service_enabled_(tracing_service), |
93 if (gpu_timing_client->IsAvailable() && | 94 device_enabled_(tracing_device) { |
| 95 if (tracing_device && |
| 96 gpu_timing_client->IsAvailable() && |
94 gpu_timing_client->IsTimerOffsetAvailable()) { | 97 gpu_timing_client->IsTimerOffsetAvailable()) { |
95 gpu_timer_ = gpu_timing_client->CreateGPUTimer(); | 98 gpu_timer_ = gpu_timing_client->CreateGPUTimer(); |
96 } | 99 } |
97 } | 100 } |
98 | 101 |
99 GPUTrace::~GPUTrace() { | 102 GPUTrace::~GPUTrace() { |
100 } | 103 } |
101 | 104 |
102 void GPUTrace::Start(bool trace_service) { | 105 void GPUTrace::Destroy(bool have_context) { |
103 if (trace_service) { | 106 if (gpu_timer_.get()) { |
| 107 gpu_timer_->Destroy(have_context); |
| 108 } |
| 109 } |
| 110 |
| 111 void GPUTrace::Start() { |
| 112 if (service_enabled_) { |
104 outputter_->TraceServiceBegin(category_, name_); | 113 outputter_->TraceServiceBegin(category_, name_); |
105 } | 114 } |
106 if (gpu_timer_.get()) { | 115 if (gpu_timer_.get()) { |
107 gpu_timer_->Start(); | 116 gpu_timer_->Start(); |
108 } | 117 } |
109 } | 118 } |
110 | 119 |
111 void GPUTrace::End(bool tracing_service) { | 120 void GPUTrace::End() { |
112 if (gpu_timer_.get()) { | 121 if (gpu_timer_.get()) { |
113 gpu_timer_->End(); | 122 gpu_timer_->End(); |
114 } | 123 } |
115 if (tracing_service) { | 124 if (service_enabled_) { |
116 outputter_->TraceServiceEnd(category_, name_); | 125 outputter_->TraceServiceEnd(category_, name_); |
117 } | 126 } |
118 } | 127 } |
119 | 128 |
120 bool GPUTrace::IsAvailable() { | 129 bool GPUTrace::IsAvailable() { |
121 return !gpu_timer_.get() || gpu_timer_->IsAvailable(); | 130 return !gpu_timer_.get() || gpu_timer_->IsAvailable(); |
122 } | 131 } |
123 | 132 |
124 void GPUTrace::Process() { | 133 void GPUTrace::Process() { |
125 if (gpu_timer_.get()) { | 134 if (gpu_timer_.get()) { |
(...skipping 19 matching lines...) Expand all Loading... |
145 if (context) { | 154 if (context) { |
146 gpu_timing_client_ = context->CreateGPUTimingClient(); | 155 gpu_timing_client_ = context->CreateGPUTimingClient(); |
147 } else { | 156 } else { |
148 gpu_timing_client_ = new gfx::GPUTimingClient(); | 157 gpu_timing_client_ = new gfx::GPUTimingClient(); |
149 } | 158 } |
150 } | 159 } |
151 | 160 |
152 GPUTracer::~GPUTracer() { | 161 GPUTracer::~GPUTracer() { |
153 } | 162 } |
154 | 163 |
| 164 void GPUTracer::Destroy(bool have_context) { |
| 165 for (int n = 0; n < NUM_TRACER_SOURCES; n++) { |
| 166 for (size_t i = 0; i < markers_[n].size(); i++) { |
| 167 TraceMarker& marker = markers_[n][i]; |
| 168 if (marker.trace_.get()) { |
| 169 marker.trace_->Destroy(have_context); |
| 170 marker.trace_ = 0; |
| 171 } |
| 172 } |
| 173 } |
| 174 |
| 175 ClearFinishedTraces(have_context); |
| 176 } |
| 177 |
155 bool GPUTracer::BeginDecoding() { | 178 bool GPUTracer::BeginDecoding() { |
156 if (gpu_executing_) | 179 if (gpu_executing_) |
157 return false; | 180 return false; |
158 | 181 |
159 if (!outputter_) { | 182 if (!outputter_) { |
160 outputter_ = CreateOutputter(gpu_timing_client_->GetTimerTypeName()); | 183 outputter_ = CreateOutputter(gpu_timing_client_->GetTimerTypeName()); |
161 } | 184 } |
162 | 185 |
163 if (*gpu_trace_dev_category == '\0') { | 186 if (*gpu_trace_dev_category == '\0') { |
164 // If GPU device category is off, invalidate timing sync. | 187 // If GPU device category is off, invalidate timing sync. |
165 gpu_timing_client_->InvalidateTimerOffset(); | 188 gpu_timing_client_->InvalidateTimerOffset(); |
166 } | 189 } |
167 | 190 |
168 gpu_executing_ = true; | 191 gpu_executing_ = true; |
169 if (IsTracing()) { | 192 if (IsTracing()) { |
170 gpu_timing_client_->CheckAndResetTimerErrors(); | 193 gpu_timing_client_->CheckAndResetTimerErrors(); |
171 // Begin a Trace for all active markers | 194 // Begin a Trace for all active markers |
172 for (int n = 0; n < NUM_TRACER_SOURCES; n++) { | 195 for (int n = 0; n < NUM_TRACER_SOURCES; n++) { |
173 for (size_t i = 0; i < markers_[n].size(); i++) { | 196 for (size_t i = 0; i < markers_[n].size(); i++) { |
174 TraceMarker& trace_marker = markers_[n][i]; | 197 TraceMarker& trace_marker = markers_[n][i]; |
175 trace_marker.trace_ = | 198 trace_marker.trace_ = |
176 new GPUTrace(outputter_, gpu_timing_client_.get(), | 199 new GPUTrace(outputter_, gpu_timing_client_.get(), |
177 trace_marker.category_, trace_marker.name_, | 200 trace_marker.category_, trace_marker.name_, |
| 201 *gpu_trace_srv_category != 0, |
178 *gpu_trace_dev_category != 0); | 202 *gpu_trace_dev_category != 0); |
179 trace_marker.trace_->Start(*gpu_trace_srv_category != 0); | 203 trace_marker.trace_->Start(); |
180 } | 204 } |
181 } | 205 } |
182 } | 206 } |
183 return true; | 207 return true; |
184 } | 208 } |
185 | 209 |
186 bool GPUTracer::EndDecoding() { | 210 bool GPUTracer::EndDecoding() { |
187 if (!gpu_executing_) | 211 if (!gpu_executing_) |
188 return false; | 212 return false; |
189 | 213 |
190 // End Trace for all active markers | 214 // End Trace for all active markers |
191 if (IsTracing()) { | 215 if (IsTracing()) { |
192 for (int n = 0; n < NUM_TRACER_SOURCES; n++) { | 216 for (int n = 0; n < NUM_TRACER_SOURCES; n++) { |
193 for (size_t i = 0; i < markers_[n].size(); i++) { | 217 for (size_t i = 0; i < markers_[n].size(); i++) { |
194 TraceMarker& marker = markers_[n][i]; | 218 TraceMarker& marker = markers_[n][i]; |
195 if (marker.trace_.get()) { | 219 if (marker.trace_.get()) { |
196 marker.trace_->End(*gpu_trace_srv_category != 0); | 220 marker.trace_->End(); |
197 if (marker.trace_->IsEnabled()) | |
198 traces_.push_back(marker.trace_); | |
199 | 221 |
200 markers_[n][i].trace_ = 0; | 222 finished_traces_.push_back(marker.trace_); |
| 223 marker.trace_ = 0; |
201 } | 224 } |
202 } | 225 } |
203 } | 226 } |
204 IssueProcessTask(); | 227 IssueProcessTask(); |
205 } | 228 } |
206 | 229 |
207 gpu_executing_ = false; | 230 gpu_executing_ = false; |
208 | 231 |
209 // NOTE(vmiura): glFlush() here can help give better trace results, | 232 // NOTE(vmiura): glFlush() here can help give better trace results, |
210 // but it distorts the normal device behavior. | 233 // but it distorts the normal device behavior. |
211 return true; | 234 return true; |
212 } | 235 } |
213 | 236 |
214 bool GPUTracer::Begin(const std::string& category, const std::string& name, | 237 bool GPUTracer::Begin(const std::string& category, const std::string& name, |
215 GpuTracerSource source) { | 238 GpuTracerSource source) { |
216 if (!gpu_executing_) | 239 if (!gpu_executing_) |
217 return false; | 240 return false; |
218 | 241 |
219 DCHECK(source >= 0 && source < NUM_TRACER_SOURCES); | 242 DCHECK(source >= 0 && source < NUM_TRACER_SOURCES); |
220 | 243 |
221 // Push new marker from given 'source' | 244 // Push new marker from given 'source' |
222 markers_[source].push_back(TraceMarker(category, name)); | 245 markers_[source].push_back(TraceMarker(category, name)); |
223 | 246 |
224 // Create trace | 247 // Create trace |
225 if (IsTracing()) { | 248 if (IsTracing()) { |
226 scoped_refptr<GPUTrace> trace = new GPUTrace( | 249 scoped_refptr<GPUTrace> trace = new GPUTrace( |
227 outputter_, gpu_timing_client_.get(), category, name, | 250 outputter_, gpu_timing_client_.get(), category, name, |
| 251 *gpu_trace_srv_category != 0, |
228 *gpu_trace_dev_category != 0); | 252 *gpu_trace_dev_category != 0); |
229 trace->Start(*gpu_trace_srv_category != 0); | 253 trace->Start(); |
230 markers_[source].back().trace_ = trace; | 254 markers_[source].back().trace_ = trace; |
231 } | 255 } |
232 | 256 |
233 return true; | 257 return true; |
234 } | 258 } |
235 | 259 |
236 bool GPUTracer::End(GpuTracerSource source) { | 260 bool GPUTracer::End(GpuTracerSource source) { |
237 if (!gpu_executing_) | 261 if (!gpu_executing_) |
238 return false; | 262 return false; |
239 | 263 |
240 DCHECK(source >= 0 && source < NUM_TRACER_SOURCES); | 264 DCHECK(source >= 0 && source < NUM_TRACER_SOURCES); |
241 | 265 |
242 // Pop last marker with matching 'source' | 266 // Pop last marker with matching 'source' |
243 if (!markers_[source].empty()) { | 267 if (!markers_[source].empty()) { |
244 if (IsTracing()) { | 268 scoped_refptr<GPUTrace> trace = markers_[source].back().trace_; |
245 scoped_refptr<GPUTrace> trace = markers_[source].back().trace_; | 269 if (trace.get()) { |
246 if (trace.get()) { | 270 if (IsTracing()) { |
247 trace->End(*gpu_trace_srv_category != 0); | 271 trace->End(); |
248 if (trace->IsEnabled()) | |
249 traces_.push_back(trace); | |
250 IssueProcessTask(); | |
251 } | 272 } |
| 273 |
| 274 finished_traces_.push_back(trace); |
| 275 IssueProcessTask(); |
252 } | 276 } |
253 | 277 |
254 markers_[source].pop_back(); | 278 markers_[source].pop_back(); |
255 return true; | 279 return true; |
256 } | 280 } |
257 return false; | 281 return false; |
258 } | 282 } |
259 | 283 |
260 bool GPUTracer::IsTracing() { | 284 bool GPUTracer::IsTracing() { |
261 return (*gpu_trace_srv_category != 0) || (*gpu_trace_dev_category != 0); | 285 return (*gpu_trace_srv_category != 0) || (*gpu_trace_dev_category != 0); |
(...skipping 29 matching lines...) Expand all Loading... |
291 } | 315 } |
292 | 316 |
293 void GPUTracer::Process() { | 317 void GPUTracer::Process() { |
294 process_posted_ = false; | 318 process_posted_ = false; |
295 ProcessTraces(); | 319 ProcessTraces(); |
296 IssueProcessTask(); | 320 IssueProcessTask(); |
297 } | 321 } |
298 | 322 |
299 void GPUTracer::ProcessTraces() { | 323 void GPUTracer::ProcessTraces() { |
300 if (!gpu_timing_client_->IsAvailable()) { | 324 if (!gpu_timing_client_->IsAvailable()) { |
301 traces_.clear(); | 325 ClearFinishedTraces(false); |
302 return; | 326 return; |
303 } | 327 } |
304 | 328 |
305 TRACE_EVENT0("gpu", "GPUTracer::ProcessTraces"); | 329 TRACE_EVENT0("gpu", "GPUTracer::ProcessTraces"); |
306 | 330 |
307 // Make owning decoder's GL context current | 331 // Make owning decoder's GL context current |
308 if (!decoder_->MakeCurrent()) { | 332 if (!decoder_->MakeCurrent()) { |
309 // Skip subsequent GL calls if MakeCurrent fails | 333 // Skip subsequent GL calls if MakeCurrent fails |
310 traces_.clear(); | 334 ClearFinishedTraces(false); |
311 return; | 335 return; |
312 } | 336 } |
313 | 337 |
314 // Check if timers are still valid (e.g: a disjoint operation | 338 // Check if timers are still valid (e.g: a disjoint operation |
315 // might have occurred.) | 339 // might have occurred.) |
316 if (gpu_timing_client_->CheckAndResetTimerErrors()) | 340 if (gpu_timing_client_->CheckAndResetTimerErrors()) { |
317 traces_.clear(); | 341 ClearFinishedTraces(true); |
| 342 } |
318 | 343 |
319 while (!traces_.empty() && traces_.front()->IsAvailable()) { | 344 while (!finished_traces_.empty()) { |
320 traces_.front()->Process(); | 345 scoped_refptr<GPUTrace>& trace = finished_traces_.front(); |
321 traces_.pop_front(); | 346 if (trace->IsDeviceTraceEnabled()) { |
| 347 if (!finished_traces_.front()->IsAvailable()) |
| 348 break; |
| 349 finished_traces_.front()->Process(); |
| 350 } |
| 351 finished_traces_.front()->Destroy(true); |
| 352 finished_traces_.pop_front(); |
322 } | 353 } |
323 | 354 |
324 // Clear pending traces if there were are any errors | 355 // Clear pending traces if there were are any errors |
325 GLenum err = glGetError(); | 356 GLenum err = glGetError(); |
326 if (err != GL_NO_ERROR) | 357 if (err != GL_NO_ERROR) |
327 traces_.clear(); | 358 ClearFinishedTraces(true); |
| 359 } |
| 360 |
| 361 void GPUTracer::ClearFinishedTraces(bool have_context) { |
| 362 while (!finished_traces_.empty()) { |
| 363 finished_traces_.front()->Destroy(have_context); |
| 364 finished_traces_.pop_front(); |
| 365 } |
328 } | 366 } |
329 | 367 |
330 void GPUTracer::IssueProcessTask() { | 368 void GPUTracer::IssueProcessTask() { |
331 if (traces_.empty() || process_posted_) | 369 if (finished_traces_.empty() || process_posted_) |
332 return; | 370 return; |
333 | 371 |
334 process_posted_ = true; | 372 process_posted_ = true; |
335 PostTask(); | 373 PostTask(); |
336 } | 374 } |
337 | 375 |
338 } // namespace gles2 | 376 } // namespace gles2 |
339 } // namespace gpu | 377 } // namespace gpu |
OLD | NEW |