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

Side by Side Diff: cc/resources/tile_manager.cc

Issue 140673009: CC/GPU: Add a soft limit to the compositor. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Use CC Setting. Created 6 years, 10 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/resources/tile_manager.h ('k') | cc/resources/tile_priority.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 The Chromium Authors. All rights reserved. 1 // Copyright 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 "cc/resources/tile_manager.h" 5 #include "cc/resources/tile_manager.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <limits> 8 #include <limits>
9 #include <string> 9 #include <string>
10 10
(...skipping 459 matching lines...) Expand 10 before | Expand all | Expand 10 after
470 mts.visible_and_ready_to_draw ? NOW_AND_READY_TO_DRAW_BIN : mts.bin; 470 mts.visible_and_ready_to_draw ? NOW_AND_READY_TO_DRAW_BIN : mts.bin;
471 471
472 // Insert the tile into a priority set. 472 // Insert the tile into a priority set.
473 tiles->InsertTile(tile, priority_bin); 473 tiles->InsertTile(tile, priority_bin);
474 } 474 }
475 } 475 }
476 476
477 void TileManager::ManageTiles(const GlobalStateThatImpactsTilePriority& state) { 477 void TileManager::ManageTiles(const GlobalStateThatImpactsTilePriority& state) {
478 TRACE_EVENT0("cc", "TileManager::ManageTiles"); 478 TRACE_EVENT0("cc", "TileManager::ManageTiles");
479 479
480 // Update internal state. 480 // Update internal state. We use the soft-limit for the resource-pool
481 // such that we will reduce to that limit after going over.
481 if (state != global_state_) { 482 if (state != global_state_) {
482 global_state_ = state; 483 global_state_ = state;
483 prioritized_tiles_dirty_ = true; 484 prioritized_tiles_dirty_ = true;
484 resource_pool_->SetResourceUsageLimits( 485 resource_pool_->SetResourceUsageLimits(
485 global_state_.memory_limit_in_bytes, 486 global_state_.soft_memory_limit_in_bytes,
486 global_state_.unused_memory_limit_in_bytes, 487 global_state_.unused_memory_limit_in_bytes,
487 global_state_.num_resources_limit); 488 global_state_.num_resources_limit);
488 } 489 }
489 490
490 // We need to call CheckForCompletedTasks() once in-between each call 491 // We need to call CheckForCompletedTasks() once in-between each call
491 // to ScheduleTasks() to prevent canceled tasks from being scheduled. 492 // to ScheduleTasks() to prevent canceled tasks from being scheduled.
492 if (!did_check_for_completed_tasks_since_last_schedule_tasks_) { 493 if (!did_check_for_completed_tasks_since_last_schedule_tasks_) {
493 raster_worker_pool_->CheckForCompletedTasks(); 494 raster_worker_pool_->CheckForCompletedTasks();
494 did_check_for_completed_tasks_since_last_schedule_tasks_ = true; 495 did_check_for_completed_tasks_since_last_schedule_tasks_ = true;
495 } 496 }
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
611 // resource(s) was returned. Note that in that case, one also need to 612 // resource(s) was returned. Note that in that case, one also need to
612 // invalidate when releasing some resource from the pool. 613 // invalidate when releasing some resource from the pool.
613 resource_pool_->CheckBusyResources(); 614 resource_pool_->CheckBusyResources();
614 615
615 // Now give memory out to the tiles until we're out, and build 616 // Now give memory out to the tiles until we're out, and build
616 // the needs-to-be-rasterized queue. 617 // the needs-to-be-rasterized queue.
617 all_tiles_that_need_to_be_rasterized_have_memory_ = true; 618 all_tiles_that_need_to_be_rasterized_have_memory_ = true;
618 all_tiles_required_for_activation_have_memory_ = true; 619 all_tiles_required_for_activation_have_memory_ = true;
619 620
620 // Cast to prevent overflow. 621 // Cast to prevent overflow.
621 int64 bytes_available = 622 int64 soft_bytes_available =
vmpstr 2014/02/12 22:19:36 maybe visible_bytes_available and repaint_bytes_av
vmpstr 2014/02/12 22:20:20 s/repaint/prepaint/
epennerAtGoogle 2014/02/12 23:08:46 Arg! That's what I called it before! ;) I can cha
vmpstr 2014/02/12 23:21:04 Yeah, I see the problem. I guess soft/hard is OK,
622 static_cast<int64>(bytes_releasable_) + 623 static_cast<int64>(bytes_releasable_) +
623 static_cast<int64>(global_state_.memory_limit_in_bytes) - 624 static_cast<int64>(global_state_.soft_memory_limit_in_bytes) -
625 static_cast<int64>(resource_pool_->acquired_memory_usage_bytes());
626 int64 hard_bytes_available =
627 static_cast<int64>(bytes_releasable_) +
628 static_cast<int64>(global_state_.hard_memory_limit_in_bytes) -
624 static_cast<int64>(resource_pool_->acquired_memory_usage_bytes()); 629 static_cast<int64>(resource_pool_->acquired_memory_usage_bytes());
625 int resources_available = resources_releasable_ + 630 int resources_available = resources_releasable_ +
626 global_state_.num_resources_limit - 631 global_state_.num_resources_limit -
627 resource_pool_->acquired_resource_count(); 632 resource_pool_->acquired_resource_count();
628 633 size_t soft_bytes_allocatable =
629 size_t bytes_allocatable = std::max(static_cast<int64>(0), bytes_available); 634 std::max(static_cast<int64>(0), soft_bytes_available);
635 size_t hard_bytes_allocatable =
636 std::max(static_cast<int64>(0), hard_bytes_available);
630 size_t resources_allocatable = std::max(0, resources_available); 637 size_t resources_allocatable = std::max(0, resources_available);
631 638
632 size_t bytes_that_exceeded_memory_budget = 0; 639 size_t bytes_that_exceeded_memory_budget = 0;
633 size_t bytes_left = bytes_allocatable; 640 int64 soft_bytes_left = soft_bytes_allocatable;
641 int64 hard_bytes_left = hard_bytes_allocatable;
642
634 size_t resources_left = resources_allocatable; 643 size_t resources_left = resources_allocatable;
635 bool oomed = false; 644 bool oomed_soft = false;
645 bool oomed_hard = false;
636 646
637 // Memory we assign to raster tasks now will be deducted from our memory 647 // Memory we assign to raster tasks now will be deducted from our memory
638 // in future iterations if priorities change. By assigning at most half 648 // in future iterations if priorities change. By assigning at most half
639 // the raster limit, we will always have another 50% left even if priorities 649 // the raster limit, we will always have another 50% left even if priorities
640 // change completely (assuming we check for completed/cancelled rasters 650 // change completely (assuming we check for completed/cancelled rasters
641 // between each call to this function). 651 // between each call to this function).
642 size_t max_raster_bytes = max_raster_usage_bytes_ / 2; 652 size_t max_raster_bytes = max_raster_usage_bytes_ / 2;
643 size_t raster_bytes = 0; 653 size_t raster_bytes = 0;
644 654
645 unsigned schedule_priority = 1u; 655 unsigned schedule_priority = 1u;
(...skipping 11 matching lines...) Expand all
657 // If this tile doesn't need a resource, then nothing to do. 667 // If this tile doesn't need a resource, then nothing to do.
658 if (!tile_version.requires_resource()) 668 if (!tile_version.requires_resource())
659 continue; 669 continue;
660 670
661 // If the tile is not needed, free it up. 671 // If the tile is not needed, free it up.
662 if (mts.bin == NEVER_BIN) { 672 if (mts.bin == NEVER_BIN) {
663 FreeResourcesForTile(tile); 673 FreeResourcesForTile(tile);
664 continue; 674 continue;
665 } 675 }
666 676
667 size_t bytes_if_allocated = BytesConsumedIfAllocated(tile); 677 const size_t bytes_if_allocated = BytesConsumedIfAllocated(tile);
668 size_t raster_bytes_if_rastered = raster_bytes + bytes_if_allocated; 678 const size_t raster_bytes_if_rastered = raster_bytes + bytes_if_allocated;
679 const size_t tile_bytes_left =
680 (mts.bin == NOW_BIN) ? hard_bytes_left : soft_bytes_left;
vmpstr 2014/02/12 22:19:36 So in SMOOTHNESS_TAKES_PRIORITY, we prioritize the
epennerAtGoogle 2014/02/12 23:08:46 I had to deal with this sticky case before when we
vmpstr 2014/02/12 23:21:04 I guess the exception is NEW_CONTENT_TAKES_PRIORIT
669 681
670 size_t tile_bytes = 0; 682 size_t tile_bytes = 0;
671 size_t tile_resources = 0; 683 size_t tile_resources = 0;
672 684
685
reveman 2014/02/12 20:08:02 nit: no need for this line. I'm surprised the pres
epennerAtGoogle 2014/02/12 21:54:34 Sorry I didn't rerun git cl format. Done.
673 // It costs to maintain a resource. 686 // It costs to maintain a resource.
674 for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) { 687 for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) {
675 if (mts.tile_versions[mode].resource_) { 688 if (mts.tile_versions[mode].resource_) {
676 tile_bytes += bytes_if_allocated; 689 tile_bytes += bytes_if_allocated;
677 tile_resources++; 690 tile_resources++;
678 } 691 }
679 } 692 }
680 693
681 // Allow lower priority tiles with initialized resources to keep 694 // Allow lower priority tiles with initialized resources to keep
682 // their memory by only assigning memory to new raster tasks if 695 // their memory by only assigning memory to new raster tasks if
683 // they can be scheduled. 696 // they can be scheduled.
684 if (raster_bytes_if_rastered <= max_raster_bytes) { 697 if (raster_bytes_if_rastered <= max_raster_bytes) {
685 // If we don't have the required version, and it's not in flight 698 // If we don't have the required version, and it's not in flight
686 // then we'll have to pay to create a new task. 699 // then we'll have to pay to create a new task.
687 if (!tile_version.resource_ && tile_version.raster_task_.is_null()) { 700 if (!tile_version.resource_ && tile_version.raster_task_.is_null()) {
688 tile_bytes += bytes_if_allocated; 701 tile_bytes += bytes_if_allocated;
689 tile_resources++; 702 tile_resources++;
690 } 703 }
691 } 704 }
692 705
693 // Tile is OOM. 706 // Tile is OOM.
694 if (tile_bytes > bytes_left || tile_resources > resources_left) { 707 if (tile_bytes > tile_bytes_left || tile_resources > resources_left) {
695 FreeResourcesForTile(tile); 708 FreeResourcesForTile(tile);
696 709
697 // This tile was already on screen and now its resources have been 710 // This tile was already on screen and now its resources have been
698 // released. In order to prevent checkerboarding, set this tile as 711 // released. In order to prevent checkerboarding, set this tile as
699 // rasterize on demand immediately. 712 // rasterize on demand immediately.
700 if (mts.visible_and_ready_to_draw) 713 if (mts.visible_and_ready_to_draw)
701 tile_version.set_rasterize_on_demand(); 714 tile_version.set_rasterize_on_demand();
702 715
703 oomed = true; 716 oomed_soft = true;
704 bytes_that_exceeded_memory_budget += tile_bytes; 717 if (mts.bin == NOW_BIN) {
718 oomed_hard = true;
719 bytes_that_exceeded_memory_budget += tile_bytes;
720 }
705 } else { 721 } else {
706 bytes_left -= tile_bytes; 722 hard_bytes_left -= tile_bytes;
723 soft_bytes_left -= tile_bytes;
724 soft_bytes_left = std::max<int64>(0, soft_bytes_left);
reveman 2014/02/12 20:08:02 does it hurt to let this go negative? in that case
epennerAtGoogle 2014/02/12 21:54:34 Do you mean make it unsigned and add a if-statemen
reveman 2014/02/12 22:14:52 I was thinking you'd keep this signed and just let
725
707 resources_left -= tile_resources; 726 resources_left -= tile_resources;
708 727
709 if (tile_version.resource_) 728 if (tile_version.resource_)
710 continue; 729 continue;
711 } 730 }
712 731
713 DCHECK(!tile_version.resource_); 732 DCHECK(!tile_version.resource_);
714 733
715 // Tile shouldn't be rasterized if |tiles_that_need_to_be_rasterized| 734 // Tile shouldn't be rasterized if |tiles_that_need_to_be_rasterized|
716 // has reached it's limit or we've failed to assign gpu memory to this 735 // has reached it's limit or we've failed to assign gpu memory to this
717 // or any higher priority tile. Preventing tiles that fit into memory 736 // or any higher priority tile. Preventing tiles that fit into memory
718 // budget to be rasterized when higher priority tile is oom is 737 // budget to be rasterized when higher priority tile is oom is
719 // important for two reasons: 738 // important for two reasons:
720 // 1. Tile size should not impact raster priority. 739 // 1. Tile size should not impact raster priority.
721 // 2. Tiles with existing raster task could otherwise incorrectly 740 // 2. Tiles with existing raster task could otherwise incorrectly
722 // be added as they are not affected by |bytes_allocatable|. 741 // be added as they are not affected by |bytes_allocatable|.
723 if (oomed || raster_bytes_if_rastered > max_raster_bytes) { 742 if (oomed_soft || raster_bytes_if_rastered > max_raster_bytes) {
724 all_tiles_that_need_to_be_rasterized_have_memory_ = false; 743 all_tiles_that_need_to_be_rasterized_have_memory_ = false;
725 if (tile->required_for_activation()) 744 if (tile->required_for_activation())
726 all_tiles_required_for_activation_have_memory_ = false; 745 all_tiles_required_for_activation_have_memory_ = false;
727 it.DisablePriorityOrdering(); 746 it.DisablePriorityOrdering();
728 continue; 747 continue;
729 } 748 }
730 749
731 raster_bytes = raster_bytes_if_rastered; 750 raster_bytes = raster_bytes_if_rastered;
732 tiles_that_need_to_be_rasterized->push_back(tile); 751 tiles_that_need_to_be_rasterized->push_back(tile);
733 } 752 }
734 753
735 ever_exceeded_memory_budget_ |= bytes_that_exceeded_memory_budget > 0; 754 // OOM reporting uses hard-limit, soft-OOM is normal depending on limit.
755 ever_exceeded_memory_budget_ |= oomed_hard;
736 if (ever_exceeded_memory_budget_) { 756 if (ever_exceeded_memory_budget_) {
737 TRACE_COUNTER_ID2("cc", 757 TRACE_COUNTER_ID2("cc",
738 "over_memory_budget", 758 "over_memory_budget",
739 this, 759 this,
740 "budget", 760 "budget",
741 global_state_.memory_limit_in_bytes, 761 global_state_.hard_memory_limit_in_bytes,
742 "over", 762 "over",
743 bytes_that_exceeded_memory_budget); 763 bytes_that_exceeded_memory_budget);
744 } 764 }
745 memory_stats_from_last_assign_.total_budget_in_bytes = 765 memory_stats_from_last_assign_.total_budget_in_bytes =
746 global_state_.memory_limit_in_bytes; 766 global_state_.hard_memory_limit_in_bytes;
747 memory_stats_from_last_assign_.bytes_allocated = 767 memory_stats_from_last_assign_.bytes_allocated =
748 bytes_allocatable - bytes_left; 768 hard_bytes_allocatable - hard_bytes_left;
749 memory_stats_from_last_assign_.bytes_unreleasable = 769 memory_stats_from_last_assign_.bytes_unreleasable =
750 bytes_allocatable - bytes_releasable_; 770 hard_bytes_allocatable - bytes_releasable_;
751 memory_stats_from_last_assign_.bytes_over = bytes_that_exceeded_memory_budget; 771 memory_stats_from_last_assign_.bytes_over = bytes_that_exceeded_memory_budget;
752 } 772 }
753 773
754 void TileManager::FreeResourceForTile(Tile* tile, RasterMode mode) { 774 void TileManager::FreeResourceForTile(Tile* tile, RasterMode mode) {
755 ManagedTileState& mts = tile->managed_state(); 775 ManagedTileState& mts = tile->managed_state();
756 if (mts.tile_versions[mode].resource_) { 776 if (mts.tile_versions[mode].resource_) {
757 resource_pool_->ReleaseResource(mts.tile_versions[mode].resource_.Pass()); 777 resource_pool_->ReleaseResource(mts.tile_versions[mode].resource_.Pass());
758 778
759 DCHECK_GE(bytes_releasable_, BytesConsumedIfAllocated(tile)); 779 DCHECK_GE(bytes_releasable_, BytesConsumedIfAllocated(tile));
760 DCHECK_GE(resources_releasable_, 1u); 780 DCHECK_GE(resources_releasable_, 1u);
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
975 flags)); 995 flags));
976 DCHECK(tiles_.find(tile->id()) == tiles_.end()); 996 DCHECK(tiles_.find(tile->id()) == tiles_.end());
977 997
978 tiles_[tile->id()] = tile; 998 tiles_[tile->id()] = tile;
979 used_layer_counts_[tile->layer_id()]++; 999 used_layer_counts_[tile->layer_id()]++;
980 prioritized_tiles_dirty_ = true; 1000 prioritized_tiles_dirty_ = true;
981 return tile; 1001 return tile;
982 } 1002 }
983 1003
984 } // namespace cc 1004 } // namespace cc
OLDNEW
« no previous file with comments | « cc/resources/tile_manager.h ('k') | cc/resources/tile_priority.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698