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

Side by Side Diff: cc/output/output_surface.cc

Issue 560123002: cc:: Add LatencyQuery logic back into OutputSurface. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 3 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 | « cc/output/output_surface.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) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 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 "cc/output/output_surface.h" 5 #include "cc/output/output_surface.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <set> 8 #include <set>
9 #include <string> 9 #include <string>
10 #include <vector> 10 #include <vector>
11 11
12 #include "base/bind.h" 12 #include "base/bind.h"
13 #include "base/debug/trace_event.h" 13 #include "base/debug/trace_event.h"
14 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "base/message_loop/message_loop.h" 15 #include "base/message_loop/message_loop.h"
16 #include "base/metrics/histogram.h" 16 #include "base/metrics/histogram.h"
17 #include "base/strings/string_split.h" 17 #include "base/strings/string_split.h"
18 #include "base/strings/string_util.h" 18 #include "base/strings/string_util.h"
19 #include "cc/output/compositor_frame.h" 19 #include "cc/output/compositor_frame.h"
20 #include "cc/output/compositor_frame_ack.h" 20 #include "cc/output/compositor_frame_ack.h"
21 #include "cc/output/managed_memory_policy.h" 21 #include "cc/output/managed_memory_policy.h"
22 #include "cc/output/output_surface_client.h" 22 #include "cc/output/output_surface_client.h"
23 #include "cc/scheduler/delay_based_time_source.h" 23 #include "cc/scheduler/delay_based_time_source.h"
24 #include "gpu/GLES2/gl2extchromium.h"
24 #include "gpu/command_buffer/client/context_support.h" 25 #include "gpu/command_buffer/client/context_support.h"
25 #include "gpu/command_buffer/client/gles2_interface.h" 26 #include "gpu/command_buffer/client/gles2_interface.h"
26 #include "ui/gfx/frame_time.h" 27 #include "ui/gfx/frame_time.h"
27 #include "ui/gfx/geometry/rect.h" 28 #include "ui/gfx/geometry/rect.h"
28 #include "ui/gfx/geometry/size.h" 29 #include "ui/gfx/geometry/size.h"
29 30
30 using std::set; 31 using std::set;
31 using std::string; 32 using std::string;
32 using std::vector; 33 using std::vector;
33 34
35 namespace {
36
37 const size_t kGpuLatencyHistorySize = 60;
38 const double kGpuLatencyEstimationPercentile = 100.0;
brianderson 2014/09/10 22:36:34 In other cases where we record history, we've seen
39 }
40
34 namespace cc { 41 namespace cc {
35 42
36 OutputSurface::OutputSurface( 43 OutputSurface::OutputSurface(
37 const scoped_refptr<ContextProvider>& context_provider) 44 const scoped_refptr<ContextProvider>& context_provider)
38 : client_(NULL), 45 : client_(NULL),
39 context_provider_(context_provider), 46 context_provider_(context_provider),
40 device_scale_factor_(-1), 47 device_scale_factor_(-1),
41 external_stencil_test_enabled_(false), 48 external_stencil_test_enabled_(false),
42 weak_ptr_factory_(this) { 49 weak_ptr_factory_(this),
50 gpu_latency_history_(kGpuLatencyHistorySize) {
43 } 51 }
44 52
45 OutputSurface::OutputSurface(scoped_ptr<SoftwareOutputDevice> software_device) 53 OutputSurface::OutputSurface(scoped_ptr<SoftwareOutputDevice> software_device)
46 : client_(NULL), 54 : client_(NULL),
47 software_device_(software_device.Pass()), 55 software_device_(software_device.Pass()),
48 device_scale_factor_(-1), 56 device_scale_factor_(-1),
49 external_stencil_test_enabled_(false), 57 external_stencil_test_enabled_(false),
50 weak_ptr_factory_(this) { 58 weak_ptr_factory_(this),
59 gpu_latency_history_(kGpuLatencyHistorySize) {
51 } 60 }
52 61
53 OutputSurface::OutputSurface( 62 OutputSurface::OutputSurface(
54 const scoped_refptr<ContextProvider>& context_provider, 63 const scoped_refptr<ContextProvider>& context_provider,
55 scoped_ptr<SoftwareOutputDevice> software_device) 64 scoped_ptr<SoftwareOutputDevice> software_device)
56 : client_(NULL), 65 : client_(NULL),
57 context_provider_(context_provider), 66 context_provider_(context_provider),
58 software_device_(software_device.Pass()), 67 software_device_(software_device.Pass()),
59 device_scale_factor_(-1), 68 device_scale_factor_(-1),
60 external_stencil_test_enabled_(false), 69 external_stencil_test_enabled_(false),
61 weak_ptr_factory_(this) { 70 weak_ptr_factory_(this),
71 gpu_latency_history_(kGpuLatencyHistorySize) {
62 } 72 }
63 73
64 void OutputSurface::CommitVSyncParameters(base::TimeTicks timebase, 74 void OutputSurface::CommitVSyncParameters(base::TimeTicks timebase,
65 base::TimeDelta interval) { 75 base::TimeDelta interval) {
66 TRACE_EVENT2("cc", 76 TRACE_EVENT2("cc",
67 "OutputSurface::CommitVSyncParameters", 77 "OutputSurface::CommitVSyncParameters",
68 "timebase", 78 "timebase",
69 (timebase - base::TimeTicks()).InSecondsF(), 79 (timebase - base::TimeTicks()).InSecondsF(),
70 "interval", 80 "interval",
71 interval.InSecondsF()); 81 interval.InSecondsF());
72 client_->CommitVSyncParameters(timebase, interval); 82 client_->CommitVSyncParameters(timebase, interval);
73 } 83 }
74 84
75 // Forwarded to OutputSurfaceClient 85 // Forwarded to OutputSurfaceClient
76 void OutputSurface::SetNeedsRedrawRect(const gfx::Rect& damage_rect) { 86 void OutputSurface::SetNeedsRedrawRect(const gfx::Rect& damage_rect) {
77 TRACE_EVENT0("cc", "OutputSurface::SetNeedsRedrawRect"); 87 TRACE_EVENT0("cc", "OutputSurface::SetNeedsRedrawRect");
78 client_->SetNeedsRedrawRect(damage_rect); 88 client_->SetNeedsRedrawRect(damage_rect);
79 } 89 }
80 90
81 void OutputSurface::ReclaimResources(const CompositorFrameAck* ack) { 91 void OutputSurface::ReclaimResources(const CompositorFrameAck* ack) {
82 client_->ReclaimResources(ack); 92 client_->ReclaimResources(ack);
83 } 93 }
84 94
85 void OutputSurface::DidLoseOutputSurface() { 95 void OutputSurface::DidLoseOutputSurface() {
86 TRACE_EVENT0("cc", "OutputSurface::DidLoseOutputSurface"); 96 TRACE_EVENT0("cc", "OutputSurface::DidLoseOutputSurface");
97 pending_gpu_latency_query_ids_.clear();
98 available_gpu_latency_query_ids_.clear();
87 client_->DidLoseOutputSurface(); 99 client_->DidLoseOutputSurface();
88 } 100 }
89 101
90 void OutputSurface::SetExternalStencilTest(bool enabled) { 102 void OutputSurface::SetExternalStencilTest(bool enabled) {
91 external_stencil_test_enabled_ = enabled; 103 external_stencil_test_enabled_ = enabled;
92 } 104 }
93 105
94 void OutputSurface::SetExternalDrawConstraints( 106 void OutputSurface::SetExternalDrawConstraints(
95 const gfx::Transform& transform, 107 const gfx::Transform& transform,
96 const gfx::Rect& viewport, 108 const gfx::Rect& viewport,
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 } 186 }
175 187
176 void OutputSurface::ReleaseContextProvider() { 188 void OutputSurface::ReleaseContextProvider() {
177 DCHECK(client_); 189 DCHECK(client_);
178 DCHECK(context_provider_.get()); 190 DCHECK(context_provider_.get());
179 ResetContext3d(); 191 ResetContext3d();
180 } 192 }
181 193
182 void OutputSurface::ResetContext3d() { 194 void OutputSurface::ResetContext3d() {
183 if (context_provider_.get()) { 195 if (context_provider_.get()) {
196 while (!pending_gpu_latency_query_ids_.empty()) {
197 unsigned query_id = pending_gpu_latency_query_ids_.front();
198 pending_gpu_latency_query_ids_.pop_front();
199 context_provider_->ContextGL()->DeleteQueriesEXT(1, &query_id);
200 }
201 while (!available_gpu_latency_query_ids_.empty()) {
202 unsigned query_id = available_gpu_latency_query_ids_.front();
203 available_gpu_latency_query_ids_.pop_front();
204 context_provider_->ContextGL()->DeleteQueriesEXT(1, &query_id);
205 }
184 context_provider_->SetLostContextCallback( 206 context_provider_->SetLostContextCallback(
185 ContextProvider::LostContextCallback()); 207 ContextProvider::LostContextCallback());
186 context_provider_->SetMemoryPolicyChangedCallback( 208 context_provider_->SetMemoryPolicyChangedCallback(
187 ContextProvider::MemoryPolicyChangedCallback()); 209 ContextProvider::MemoryPolicyChangedCallback());
188 if (gpu::ContextSupport* support = context_provider_->ContextSupport()) 210 if (gpu::ContextSupport* support = context_provider_->ContextSupport())
189 support->SetSwapBuffersCompleteCallback(base::Closure()); 211 support->SetSwapBuffersCompleteCallback(base::Closure());
190 } 212 }
191 context_provider_ = NULL; 213 context_provider_ = NULL;
192 } 214 }
193 215
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
229 void OutputSurface::SwapBuffers(CompositorFrame* frame) { 251 void OutputSurface::SwapBuffers(CompositorFrame* frame) {
230 if (frame->software_frame_data) { 252 if (frame->software_frame_data) {
231 PostSwapBuffersComplete(); 253 PostSwapBuffersComplete();
232 client_->DidSwapBuffers(); 254 client_->DidSwapBuffers();
233 return; 255 return;
234 } 256 }
235 257
236 DCHECK(context_provider_.get()); 258 DCHECK(context_provider_.get());
237 DCHECK(frame->gl_frame_data); 259 DCHECK(frame->gl_frame_data);
238 260
261 UpdateAndMeasureGpuLatency();
239 if (frame->gl_frame_data->sub_buffer_rect == 262 if (frame->gl_frame_data->sub_buffer_rect ==
240 gfx::Rect(frame->gl_frame_data->size)) { 263 gfx::Rect(frame->gl_frame_data->size)) {
241 context_provider_->ContextSupport()->Swap(); 264 context_provider_->ContextSupport()->Swap();
242 } else { 265 } else {
243 context_provider_->ContextSupport()->PartialSwapBuffers( 266 context_provider_->ContextSupport()->PartialSwapBuffers(
244 frame->gl_frame_data->sub_buffer_rect); 267 frame->gl_frame_data->sub_buffer_rect);
245 } 268 }
246 269
247 client_->DidSwapBuffers(); 270 client_->DidSwapBuffers();
248 } 271 }
249 272
273 base::TimeDelta OutputSurface::GpuLatencyEstimate() {
274 if (context_provider_.get() && !capabilities_.adjust_deadline_for_parent)
275 return gpu_latency_history_.Percentile(kGpuLatencyEstimationPercentile);
276 else
277 return base::TimeDelta();
278 }
279
280 void OutputSurface::UpdateAndMeasureGpuLatency() {
281 // We only care about GPU latency for surfaces that do not have a parent
282 // compositor, since surfaces that do have a parent compositor can use
283 // mailboxes or delegated rendering to send frames to their parent without
284 // incurring GPU latency.
285 if (capabilities_.adjust_deadline_for_parent)
286 return;
287
288 while (pending_gpu_latency_query_ids_.size()) {
brianderson 2014/09/10 22:36:35 Can you add a comment indicating this loop collect
289 unsigned query_id = pending_gpu_latency_query_ids_.front();
290 unsigned query_complete = 1;
291 context_provider_->ContextGL()->GetQueryObjectuivEXT(
292 query_id, GL_QUERY_RESULT_AVAILABLE_EXT, &query_complete);
293 if (!query_complete)
294 break;
295
296 unsigned value = 0;
297 context_provider_->ContextGL()->GetQueryObjectuivEXT(
298 query_id, GL_QUERY_RESULT_EXT, &value);
299 pending_gpu_latency_query_ids_.pop_front();
300 available_gpu_latency_query_ids_.push_back(query_id);
301
302 base::TimeDelta latency = base::TimeDelta::FromMicroseconds(value);
303 base::TimeDelta latency_estimate = GpuLatencyEstimate();
304 gpu_latency_history_.InsertSample(latency);
305
306 base::TimeDelta latency_overestimate;
307 base::TimeDelta latency_underestimate;
308 if (latency > latency_estimate)
309 latency_underestimate = latency - latency_estimate;
310 else
311 latency_overestimate = latency_estimate - latency;
312 UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.GpuLatency",
313 latency,
314 base::TimeDelta::FromMilliseconds(1),
315 base::TimeDelta::FromMilliseconds(100),
316 50);
317 UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.GpuLatencyUnderestimate",
318 latency_underestimate,
319 base::TimeDelta::FromMilliseconds(1),
320 base::TimeDelta::FromMilliseconds(100),
321 50);
322 UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.GpuLatencyOverestimate",
323 latency_overestimate,
324 base::TimeDelta::FromMilliseconds(1),
325 base::TimeDelta::FromMilliseconds(100),
326 50);
327 }
328
329 unsigned gpu_latency_query_id;
brianderson 2014/09/10 22:36:35 A comment would hlep here too.
330 if (available_gpu_latency_query_ids_.size()) {
331 gpu_latency_query_id = available_gpu_latency_query_ids_.front();
332 available_gpu_latency_query_ids_.pop_front();
333 } else {
334 context_provider_->ContextGL()->GenQueriesEXT(1, &gpu_latency_query_id);
335 }
336
337 context_provider_->ContextGL()->BeginQueryEXT(GL_LATENCY_QUERY_CHROMIUM,
brianderson 2014/09/10 22:36:35 And here.
338 gpu_latency_query_id);
339 context_provider_->ContextGL()->EndQueryEXT(GL_LATENCY_QUERY_CHROMIUM);
340 pending_gpu_latency_query_ids_.push_back(gpu_latency_query_id);
341 }
342
250 void OutputSurface::PostSwapBuffersComplete() { 343 void OutputSurface::PostSwapBuffersComplete() {
251 base::MessageLoop::current()->PostTask( 344 base::MessageLoop::current()->PostTask(
252 FROM_HERE, 345 FROM_HERE,
253 base::Bind(&OutputSurface::OnSwapBuffersComplete, 346 base::Bind(&OutputSurface::OnSwapBuffersComplete,
254 weak_ptr_factory_.GetWeakPtr())); 347 weak_ptr_factory_.GetWeakPtr()));
255 } 348 }
256 349
257 // We don't post tasks bound to the client directly since they might run 350 // We don't post tasks bound to the client directly since they might run
258 // after the OutputSurface has been destroyed. 351 // after the OutputSurface has been destroyed.
259 void OutputSurface::OnSwapBuffersComplete() { 352 void OutputSurface::OnSwapBuffersComplete() {
260 client_->DidSwapBuffersComplete(); 353 client_->DidSwapBuffersComplete();
261 } 354 }
262 355
263 void OutputSurface::SetMemoryPolicy(const ManagedMemoryPolicy& policy) { 356 void OutputSurface::SetMemoryPolicy(const ManagedMemoryPolicy& policy) {
264 TRACE_EVENT1("cc", "OutputSurface::SetMemoryPolicy", 357 TRACE_EVENT1("cc", "OutputSurface::SetMemoryPolicy",
265 "bytes_limit_when_visible", policy.bytes_limit_when_visible); 358 "bytes_limit_when_visible", policy.bytes_limit_when_visible);
266 // Just ignore the memory manager when it says to set the limit to zero 359 // Just ignore the memory manager when it says to set the limit to zero
267 // bytes. This will happen when the memory manager thinks that the renderer 360 // bytes. This will happen when the memory manager thinks that the renderer
268 // is not visible (which the renderer knows better). 361 // is not visible (which the renderer knows better).
269 if (policy.bytes_limit_when_visible) 362 if (policy.bytes_limit_when_visible)
270 client_->SetMemoryPolicy(policy); 363 client_->SetMemoryPolicy(policy);
271 } 364 }
272 365
273 } // namespace cc 366 } // namespace cc
OLDNEW
« no previous file with comments | « cc/output/output_surface.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698