OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |