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

Side by Side Diff: content/common/gpu/gpu_command_buffer_stub.cc

Issue 1315713007: gpu: Reduce GL context switches used to check pending queries. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: webview fix Created 5 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
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 "base/bind.h" 5 #include "base/bind.h"
6 #include "base/bind_helpers.h" 6 #include "base/bind_helpers.h"
7 #include "base/command_line.h" 7 #include "base/command_line.h"
8 #include "base/hash.h" 8 #include "base/hash.h"
9 #include "base/json/json_writer.h" 9 #include "base/json/json_writer.h"
10 #include "base/memory/shared_memory.h" 10 #include "base/memory/shared_memory.h"
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
192 gpu_preference_(gpu_preference), 192 gpu_preference_(gpu_preference),
193 use_virtualized_gl_context_(use_virtualized_gl_context), 193 use_virtualized_gl_context_(use_virtualized_gl_context),
194 stream_id_(stream_id), 194 stream_id_(stream_id),
195 route_id_(route_id), 195 route_id_(route_id),
196 surface_id_(surface_id), 196 surface_id_(surface_id),
197 software_(software), 197 software_(software),
198 last_flush_count_(0), 198 last_flush_count_(0),
199 last_memory_allocation_valid_(false), 199 last_memory_allocation_valid_(false),
200 watchdog_(watchdog), 200 watchdog_(watchdog),
201 sync_point_wait_count_(0), 201 sync_point_wait_count_(0),
202 delayed_work_scheduled_(false),
203 previous_messages_processed_(0), 202 previous_messages_processed_(0),
204 active_url_(active_url), 203 active_url_(active_url),
205 total_gpu_memory_(0) { 204 total_gpu_memory_(0) {
206 active_url_hash_ = base::Hash(active_url.possibly_invalid_spec()); 205 active_url_hash_ = base::Hash(active_url.possibly_invalid_spec());
207 FastSetActiveURL(active_url_, active_url_hash_); 206 FastSetActiveURL(active_url_, active_url_hash_);
208 207
209 gpu::gles2::ContextCreationAttribHelper attrib_parser; 208 gpu::gles2::ContextCreationAttribHelper attrib_parser;
210 attrib_parser.Parse(requested_attribs_); 209 attrib_parser.Parse(requested_attribs_);
211 210
212 if (share_group) { 211 if (share_group) {
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
306 OnSetClientHasMemoryAllocationChangedCallback) 305 OnSetClientHasMemoryAllocationChangedCallback)
307 IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_CreateImage, OnCreateImage); 306 IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_CreateImage, OnCreateImage);
308 IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_DestroyImage, OnDestroyImage); 307 IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_DestroyImage, OnDestroyImage);
309 IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_CreateStreamTexture, 308 IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_CreateStreamTexture,
310 OnCreateStreamTexture) 309 OnCreateStreamTexture)
311 IPC_MESSAGE_UNHANDLED(handled = false) 310 IPC_MESSAGE_UNHANDLED(handled = false)
312 IPC_END_MESSAGE_MAP() 311 IPC_END_MESSAGE_MAP()
313 312
314 CheckCompleteWaits(); 313 CheckCompleteWaits();
315 314
315 // Ensure that any delayed work that was created will be handled.
316 if (have_context) { 316 if (have_context) {
317 // Ensure that any delayed work that was created will be handled. 317 if (scheduler_)
318 ScheduleDelayedWork(kHandleMoreWorkPeriodMs); 318 scheduler_->ProcessPendingQueries();
319 ScheduleDelayedWork(
320 base::TimeDelta::FromMilliseconds(kHandleMoreWorkPeriodMs));
319 } 321 }
320 322
321 DCHECK(handled); 323 DCHECK(handled);
322 return handled; 324 return handled;
323 } 325 }
324 326
325 bool GpuCommandBufferStub::Send(IPC::Message* message) { 327 bool GpuCommandBufferStub::Send(IPC::Message* message) {
326 return channel_->Send(message); 328 return channel_->Send(message);
327 } 329 }
328 330
329 bool GpuCommandBufferStub::IsScheduled() { 331 bool GpuCommandBufferStub::IsScheduled() {
330 return (!scheduler_.get() || scheduler_->IsScheduled()); 332 return (!scheduler_.get() || scheduler_->IsScheduled());
331 } 333 }
332 334
333 bool GpuCommandBufferStub::HasMoreWork() { 335 void GpuCommandBufferStub::PollWork() {
334 return scheduler_.get() && scheduler_->HasMoreWork(); 336 // Post another delayed task if we have not yet reached the time at which
337 // we should process delayed work.
338 base::TimeTicks current_time = base::TimeTicks::Now();
339 DCHECK(!process_delayed_work_time_.is_null());
340 if (process_delayed_work_time_ > current_time) {
341 task_runner_->PostDelayedTask(
dshwang 2015/09/01 08:56:10 do we have to delay one more? PollWork() is alread
reveman 2015/09/01 15:54:11 That's what this patch is supposed to improve. If
dshwang 2015/09/01 16:15:50 How is it possible |process_delayed_work_time_ > c
reveman 2015/09/01 16:25:17 ScheduleDelayedWork is called as a result of perfo
dshwang 2015/09/01 16:32:17 I understand, thx for explanation.
dshwang 2015/09/01 16:37:00 Is it possible for idle tasks and pending query to
reveman 2015/09/01 17:02:07 Pending queries are processed each time we process
342 FROM_HERE, base::Bind(&GpuCommandBufferStub::PollWork, AsWeakPtr()),
343 process_delayed_work_time_ - current_time);
344 return;
345 }
346 process_delayed_work_time_ = base::TimeTicks();
347
348 PerformWork();
335 } 349 }
336 350
337 void GpuCommandBufferStub::PollWork() { 351 void GpuCommandBufferStub::PerformWork() {
338 TRACE_EVENT0("gpu", "GpuCommandBufferStub::PollWork"); 352 TRACE_EVENT0("gpu", "GpuCommandBufferStub::PerformWork");
339 delayed_work_scheduled_ = false; 353
340 FastSetActiveURL(active_url_, active_url_hash_); 354 FastSetActiveURL(active_url_, active_url_hash_);
341 if (decoder_.get() && !MakeCurrent()) 355 if (decoder_.get() && !MakeCurrent())
342 return; 356 return;
343 357
344 if (scheduler_) { 358 if (scheduler_) {
345 uint64 current_messages_processed = 359 uint64 current_messages_processed =
346 channel()->gpu_channel_manager()->MessagesProcessed(); 360 channel()->gpu_channel_manager()->MessagesProcessed();
347 // We're idle when no messages were processed or scheduled. 361 // We're idle when no messages were processed or scheduled.
348 bool is_idle = 362 bool is_idle =
349 (previous_messages_processed_ == current_messages_processed) && 363 (previous_messages_processed_ == current_messages_processed) &&
350 !channel()->gpu_channel_manager()->HandleMessagesScheduled(); 364 !channel()->gpu_channel_manager()->HandleMessagesScheduled();
351 if (!is_idle && !last_idle_time_.is_null()) { 365 if (!is_idle && !last_idle_time_.is_null()) {
352 base::TimeDelta time_since_idle = 366 base::TimeDelta time_since_idle =
353 base::TimeTicks::Now() - last_idle_time_; 367 base::TimeTicks::Now() - last_idle_time_;
354 base::TimeDelta max_time_since_idle = 368 base::TimeDelta max_time_since_idle =
355 base::TimeDelta::FromMilliseconds(kMaxTimeSinceIdleMs); 369 base::TimeDelta::FromMilliseconds(kMaxTimeSinceIdleMs);
356 370
357 // Force idle when it's been too long since last time we were idle. 371 // Force idle when it's been too long since last time we were idle.
358 if (time_since_idle > max_time_since_idle) 372 if (time_since_idle > max_time_since_idle)
359 is_idle = true; 373 is_idle = true;
360 } 374 }
361 375
362 if (is_idle) { 376 if (is_idle) {
363 last_idle_time_ = base::TimeTicks::Now(); 377 last_idle_time_ = base::TimeTicks::Now();
364 scheduler_->PerformIdleWork(); 378 scheduler_->PerformIdleWork();
365 } 379 }
380
381 scheduler_->ProcessPendingQueries();
no sievers 2015/09/16 21:04:35 Why do we really treat pending queries different f
reveman 2015/09/16 23:12:08 I'm not that familiar with the current use cases f
no sievers 2015/09/17 00:34:38 ok sounds good. i was just thinking that because w
366 } 382 }
367 ScheduleDelayedWork(kHandleMoreWorkPeriodBusyMs); 383
384 ScheduleDelayedWork(
385 base::TimeDelta::FromMilliseconds(kHandleMoreWorkPeriodBusyMs));
368 } 386 }
369 387
370 bool GpuCommandBufferStub::HasUnprocessedCommands() { 388 bool GpuCommandBufferStub::HasUnprocessedCommands() {
371 if (command_buffer_) { 389 if (command_buffer_) {
372 gpu::CommandBuffer::State state = command_buffer_->GetLastState(); 390 gpu::CommandBuffer::State state = command_buffer_->GetLastState();
373 return command_buffer_->GetPutOffset() != state.get_offset && 391 return command_buffer_->GetPutOffset() != state.get_offset &&
374 !gpu::error::IsError(state.error); 392 !gpu::error::IsError(state.error);
375 } 393 }
376 return false; 394 return false;
377 } 395 }
378 396
379 void GpuCommandBufferStub::ScheduleDelayedWork(int64 delay) { 397 void GpuCommandBufferStub::ScheduleDelayedWork(base::TimeDelta delay) {
380 if (!HasMoreWork()) { 398 bool has_more_work = scheduler_.get() && (scheduler_->HasPendingQueries() ||
399 scheduler_->HasMoreIdleWork());
dshwang 2015/09/01 08:56:10 very nice :)
400 if (!has_more_work) {
381 last_idle_time_ = base::TimeTicks(); 401 last_idle_time_ = base::TimeTicks();
382 return; 402 return;
383 } 403 }
384 404
385 if (delayed_work_scheduled_) 405 base::TimeTicks current_time = base::TimeTicks::Now();
406 // |process_delayed_work_time_| is set if processing of delayed work is
407 // already scheduled. Just update the time if already scheduled.
408 if (!process_delayed_work_time_.is_null()) {
409 process_delayed_work_time_ = current_time + delay;
no sievers 2015/09/16 21:04:35 This keeps pushing out the time though if called r
reveman 2015/09/16 23:12:08 Improved the comment in the header file to make th
386 return; 410 return;
387 delayed_work_scheduled_ = true; 411 }
388 412
389 // Idle when no messages are processed between now and when 413 // Idle when no messages are processed between now and when
390 // PollWork is called. 414 // PollWork is called.
391 previous_messages_processed_ = 415 previous_messages_processed_ =
392 channel()->gpu_channel_manager()->MessagesProcessed(); 416 channel()->gpu_channel_manager()->MessagesProcessed();
393 if (last_idle_time_.is_null()) 417 if (last_idle_time_.is_null())
394 last_idle_time_ = base::TimeTicks::Now(); 418 last_idle_time_ = current_time;
395 419
396 // IsScheduled() returns true after passing all unschedule fences 420 // IsScheduled() returns true after passing all unschedule fences
397 // and this is when we can start performing idle work. Idle work 421 // and this is when we can start performing idle work. Idle work
398 // is done synchronously so we can set delay to 0 and instead poll 422 // is done synchronously so we can set delay to 0 and instead poll
399 // for more work at the rate idle work is performed. This also ensures 423 // for more work at the rate idle work is performed. This also ensures
400 // that idle work is done as efficiently as possible without any 424 // that idle work is done as efficiently as possible without any
401 // unnecessary delays. 425 // unnecessary delays.
402 if (scheduler_.get() && 426 if (scheduler_.get() &&
403 scheduler_->IsScheduled() && 427 scheduler_->IsScheduled() &&
404 scheduler_->HasMoreIdleWork()) { 428 scheduler_->HasMoreIdleWork()) {
dshwang 2015/09/01 08:56:10 Don't we need to check (scheduler_->HasPendingQuer
reveman 2015/09/01 15:54:11 This code is only for handling idle work. Pending
405 delay = 0; 429 delay = base::TimeDelta();
406 } 430 }
407 431
432 process_delayed_work_time_ = current_time + delay;
408 task_runner_->PostDelayedTask( 433 task_runner_->PostDelayedTask(
409 FROM_HERE, base::Bind(&GpuCommandBufferStub::PollWork, AsWeakPtr()), 434 FROM_HERE, base::Bind(&GpuCommandBufferStub::PollWork, AsWeakPtr()),
410 base::TimeDelta::FromMilliseconds(delay)); 435 delay);
411 } 436 }
412 437
413 bool GpuCommandBufferStub::MakeCurrent() { 438 bool GpuCommandBufferStub::MakeCurrent() {
414 if (decoder_->MakeCurrent()) 439 if (decoder_->MakeCurrent())
415 return true; 440 return true;
416 DLOG(ERROR) << "Context lost because MakeCurrent failed."; 441 DLOG(ERROR) << "Context lost because MakeCurrent failed.";
417 command_buffer_->SetContextLostReason(decoder_->GetContextLostReason()); 442 command_buffer_->SetContextLostReason(decoder_->GetContextLostReason());
418 command_buffer_->SetParseError(gpu::error::kLostContext); 443 command_buffer_->SetParseError(gpu::error::kLostContext);
419 CheckContextLost(); 444 CheckContextLost();
420 return false; 445 return false;
(...skipping 759 matching lines...) Expand 10 before | Expand all | Expand 10 after
1180 result)); 1205 result));
1181 } 1206 }
1182 1207
1183 void GpuCommandBufferStub::SendUpdateVSyncParameters(base::TimeTicks timebase, 1208 void GpuCommandBufferStub::SendUpdateVSyncParameters(base::TimeTicks timebase,
1184 base::TimeDelta interval) { 1209 base::TimeDelta interval) {
1185 Send(new GpuCommandBufferMsg_UpdateVSyncParameters(route_id_, timebase, 1210 Send(new GpuCommandBufferMsg_UpdateVSyncParameters(route_id_, timebase,
1186 interval)); 1211 interval));
1187 } 1212 }
1188 1213
1189 } // namespace content 1214 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698