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 443 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
454 } | 454 } |
455 } | 455 } |
456 | 456 |
457 void TileManager::ManageTiles(const GlobalStateThatImpactsTilePriority& state) { | 457 void TileManager::ManageTiles(const GlobalStateThatImpactsTilePriority& state) { |
458 TRACE_EVENT0("cc", "TileManager::ManageTiles"); | 458 TRACE_EVENT0("cc", "TileManager::ManageTiles"); |
459 | 459 |
460 // Update internal state. | 460 // Update internal state. |
461 if (state != global_state_) { | 461 if (state != global_state_) { |
462 global_state_ = state; | 462 global_state_ = state; |
463 prioritized_tiles_dirty_ = true; | 463 prioritized_tiles_dirty_ = true; |
| 464 // Soft limit is used for resource pool such that |
| 465 // memory returns to soft limit after going over. |
464 resource_pool_->SetResourceUsageLimits( | 466 resource_pool_->SetResourceUsageLimits( |
465 global_state_.memory_limit_in_bytes, | 467 global_state_.soft_memory_limit_in_bytes, |
466 global_state_.unused_memory_limit_in_bytes, | 468 global_state_.unused_memory_limit_in_bytes, |
467 global_state_.num_resources_limit); | 469 global_state_.num_resources_limit); |
468 } | 470 } |
469 | 471 |
470 // We need to call CheckForCompletedTasks() once in-between each call | 472 // We need to call CheckForCompletedTasks() once in-between each call |
471 // to ScheduleTasks() to prevent canceled tasks from being scheduled. | 473 // to ScheduleTasks() to prevent canceled tasks from being scheduled. |
472 if (!did_check_for_completed_tasks_since_last_schedule_tasks_) { | 474 if (!did_check_for_completed_tasks_since_last_schedule_tasks_) { |
473 raster_worker_pool_->CheckForCompletedTasks(); | 475 raster_worker_pool_->CheckForCompletedTasks(); |
474 did_check_for_completed_tasks_since_last_schedule_tasks_ = true; | 476 did_check_for_completed_tasks_since_last_schedule_tasks_ = true; |
475 } | 477 } |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
591 // resource(s) was returned. Note that in that case, one also need to | 593 // resource(s) was returned. Note that in that case, one also need to |
592 // invalidate when releasing some resource from the pool. | 594 // invalidate when releasing some resource from the pool. |
593 resource_pool_->CheckBusyResources(); | 595 resource_pool_->CheckBusyResources(); |
594 | 596 |
595 // Now give memory out to the tiles until we're out, and build | 597 // Now give memory out to the tiles until we're out, and build |
596 // the needs-to-be-rasterized queue. | 598 // the needs-to-be-rasterized queue. |
597 all_tiles_that_need_to_be_rasterized_have_memory_ = true; | 599 all_tiles_that_need_to_be_rasterized_have_memory_ = true; |
598 all_tiles_required_for_activation_have_memory_ = true; | 600 all_tiles_required_for_activation_have_memory_ = true; |
599 | 601 |
600 // Cast to prevent overflow. | 602 // Cast to prevent overflow. |
601 int64 bytes_available = | 603 int64 soft_bytes_available = |
602 static_cast<int64>(bytes_releasable_) + | 604 static_cast<int64>(bytes_releasable_) + |
603 static_cast<int64>(global_state_.memory_limit_in_bytes) - | 605 static_cast<int64>(global_state_.soft_memory_limit_in_bytes) - |
| 606 static_cast<int64>(resource_pool_->acquired_memory_usage_bytes()); |
| 607 int64 hard_bytes_available = |
| 608 static_cast<int64>(bytes_releasable_) + |
| 609 static_cast<int64>(global_state_.hard_memory_limit_in_bytes) - |
604 static_cast<int64>(resource_pool_->acquired_memory_usage_bytes()); | 610 static_cast<int64>(resource_pool_->acquired_memory_usage_bytes()); |
605 int resources_available = resources_releasable_ + | 611 int resources_available = resources_releasable_ + |
606 global_state_.num_resources_limit - | 612 global_state_.num_resources_limit - |
607 resource_pool_->acquired_resource_count(); | 613 resource_pool_->acquired_resource_count(); |
608 | 614 size_t soft_bytes_allocatable = |
609 size_t bytes_allocatable = std::max(static_cast<int64>(0), bytes_available); | 615 std::max(static_cast<int64>(0), soft_bytes_available); |
| 616 size_t hard_bytes_allocatable = |
| 617 std::max(static_cast<int64>(0), hard_bytes_available); |
610 size_t resources_allocatable = std::max(0, resources_available); | 618 size_t resources_allocatable = std::max(0, resources_available); |
611 | 619 |
612 size_t bytes_that_exceeded_memory_budget = 0; | 620 size_t bytes_that_exceeded_memory_budget = 0; |
613 size_t bytes_left = bytes_allocatable; | 621 size_t soft_bytes_left = soft_bytes_allocatable; |
| 622 size_t hard_bytes_left = hard_bytes_allocatable; |
| 623 |
614 size_t resources_left = resources_allocatable; | 624 size_t resources_left = resources_allocatable; |
615 bool oomed = false; | 625 bool oomed_soft = false; |
| 626 bool oomed_hard = false; |
616 | 627 |
617 // Memory we assign to raster tasks now will be deducted from our memory | 628 // Memory we assign to raster tasks now will be deducted from our memory |
618 // in future iterations if priorities change. By assigning at most half | 629 // in future iterations if priorities change. By assigning at most half |
619 // the raster limit, we will always have another 50% left even if priorities | 630 // the raster limit, we will always have another 50% left even if priorities |
620 // change completely (assuming we check for completed/cancelled rasters | 631 // change completely (assuming we check for completed/cancelled rasters |
621 // between each call to this function). | 632 // between each call to this function). |
622 size_t max_raster_bytes = max_raster_usage_bytes_ / 2; | 633 size_t max_raster_bytes = max_raster_usage_bytes_ / 2; |
623 size_t raster_bytes = 0; | 634 size_t raster_bytes = 0; |
624 | 635 |
625 unsigned schedule_priority = 1u; | 636 unsigned schedule_priority = 1u; |
(...skipping 11 matching lines...) Expand all Loading... |
637 // If this tile doesn't need a resource, then nothing to do. | 648 // If this tile doesn't need a resource, then nothing to do. |
638 if (!tile_version.requires_resource()) | 649 if (!tile_version.requires_resource()) |
639 continue; | 650 continue; |
640 | 651 |
641 // If the tile is not needed, free it up. | 652 // If the tile is not needed, free it up. |
642 if (mts.bin == NEVER_BIN) { | 653 if (mts.bin == NEVER_BIN) { |
643 FreeResourcesForTile(tile); | 654 FreeResourcesForTile(tile); |
644 continue; | 655 continue; |
645 } | 656 } |
646 | 657 |
647 size_t bytes_if_allocated = BytesConsumedIfAllocated(tile); | 658 const bool tile_uses_hard_limit = mts.bin <= NOW_BIN; |
648 size_t raster_bytes_if_rastered = raster_bytes + bytes_if_allocated; | 659 const size_t bytes_if_allocated = BytesConsumedIfAllocated(tile); |
| 660 const size_t raster_bytes_if_rastered = raster_bytes + bytes_if_allocated; |
| 661 const size_t tile_bytes_left = |
| 662 (tile_uses_hard_limit) ? hard_bytes_left : soft_bytes_left; |
649 | 663 |
650 size_t tile_bytes = 0; | 664 size_t tile_bytes = 0; |
651 size_t tile_resources = 0; | 665 size_t tile_resources = 0; |
652 | 666 |
653 // It costs to maintain a resource. | 667 // It costs to maintain a resource. |
654 for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) { | 668 for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) { |
655 if (mts.tile_versions[mode].resource_) { | 669 if (mts.tile_versions[mode].resource_) { |
656 tile_bytes += bytes_if_allocated; | 670 tile_bytes += bytes_if_allocated; |
657 tile_resources++; | 671 tile_resources++; |
658 } | 672 } |
659 } | 673 } |
660 | 674 |
661 // Allow lower priority tiles with initialized resources to keep | 675 // Allow lower priority tiles with initialized resources to keep |
662 // their memory by only assigning memory to new raster tasks if | 676 // their memory by only assigning memory to new raster tasks if |
663 // they can be scheduled. | 677 // they can be scheduled. |
664 if (raster_bytes_if_rastered <= max_raster_bytes) { | 678 if (raster_bytes_if_rastered <= max_raster_bytes) { |
665 // If we don't have the required version, and it's not in flight | 679 // If we don't have the required version, and it's not in flight |
666 // then we'll have to pay to create a new task. | 680 // then we'll have to pay to create a new task. |
667 if (!tile_version.resource_ && tile_version.raster_task_.is_null()) { | 681 if (!tile_version.resource_ && tile_version.raster_task_.is_null()) { |
668 tile_bytes += bytes_if_allocated; | 682 tile_bytes += bytes_if_allocated; |
669 tile_resources++; | 683 tile_resources++; |
670 } | 684 } |
671 } | 685 } |
672 | 686 |
673 // Tile is OOM. | 687 // Tile is OOM. |
674 if (tile_bytes > bytes_left || tile_resources > resources_left) { | 688 if (tile_bytes > tile_bytes_left || tile_resources > resources_left) { |
675 FreeResourcesForTile(tile); | 689 FreeResourcesForTile(tile); |
676 | 690 |
677 // This tile was already on screen and now its resources have been | 691 // This tile was already on screen and now its resources have been |
678 // released. In order to prevent checkerboarding, set this tile as | 692 // released. In order to prevent checkerboarding, set this tile as |
679 // rasterize on demand immediately. | 693 // rasterize on demand immediately. |
680 if (mts.visible_and_ready_to_draw && use_rasterize_on_demand_) | 694 if (mts.visible_and_ready_to_draw && use_rasterize_on_demand_) |
681 tile_version.set_rasterize_on_demand(); | 695 tile_version.set_rasterize_on_demand(); |
682 | 696 |
683 oomed = true; | 697 oomed_soft = true; |
684 bytes_that_exceeded_memory_budget += tile_bytes; | 698 if (tile_uses_hard_limit) { |
| 699 oomed_hard = true; |
| 700 bytes_that_exceeded_memory_budget += tile_bytes; |
| 701 } |
685 } else { | 702 } else { |
686 bytes_left -= tile_bytes; | |
687 resources_left -= tile_resources; | 703 resources_left -= tile_resources; |
688 | 704 hard_bytes_left -= tile_bytes; |
| 705 soft_bytes_left = |
| 706 (soft_bytes_left > tile_bytes) ? soft_bytes_left - tile_bytes : 0; |
689 if (tile_version.resource_) | 707 if (tile_version.resource_) |
690 continue; | 708 continue; |
691 } | 709 } |
692 | 710 |
693 DCHECK(!tile_version.resource_); | 711 DCHECK(!tile_version.resource_); |
694 | 712 |
695 // Tile shouldn't be rasterized if |tiles_that_need_to_be_rasterized| | 713 // Tile shouldn't be rasterized if |tiles_that_need_to_be_rasterized| |
696 // has reached it's limit or we've failed to assign gpu memory to this | 714 // has reached it's limit or we've failed to assign gpu memory to this |
697 // or any higher priority tile. Preventing tiles that fit into memory | 715 // or any higher priority tile. Preventing tiles that fit into memory |
698 // budget to be rasterized when higher priority tile is oom is | 716 // budget to be rasterized when higher priority tile is oom is |
699 // important for two reasons: | 717 // important for two reasons: |
700 // 1. Tile size should not impact raster priority. | 718 // 1. Tile size should not impact raster priority. |
701 // 2. Tiles with existing raster task could otherwise incorrectly | 719 // 2. Tiles with existing raster task could otherwise incorrectly |
702 // be added as they are not affected by |bytes_allocatable|. | 720 // be added as they are not affected by |bytes_allocatable|. |
703 if (oomed || raster_bytes_if_rastered > max_raster_bytes) { | 721 if (oomed_soft || raster_bytes_if_rastered > max_raster_bytes) { |
704 all_tiles_that_need_to_be_rasterized_have_memory_ = false; | 722 all_tiles_that_need_to_be_rasterized_have_memory_ = false; |
705 if (tile->required_for_activation()) | 723 if (tile->required_for_activation()) |
706 all_tiles_required_for_activation_have_memory_ = false; | 724 all_tiles_required_for_activation_have_memory_ = false; |
707 it.DisablePriorityOrdering(); | 725 it.DisablePriorityOrdering(); |
708 continue; | 726 continue; |
709 } | 727 } |
710 | 728 |
711 raster_bytes = raster_bytes_if_rastered; | 729 raster_bytes = raster_bytes_if_rastered; |
712 tiles_that_need_to_be_rasterized->push_back(tile); | 730 tiles_that_need_to_be_rasterized->push_back(tile); |
713 } | 731 } |
714 | 732 |
715 ever_exceeded_memory_budget_ |= bytes_that_exceeded_memory_budget > 0; | 733 // OOM reporting uses hard-limit, soft-OOM is normal depending on limit. |
| 734 ever_exceeded_memory_budget_ |= oomed_hard; |
716 if (ever_exceeded_memory_budget_) { | 735 if (ever_exceeded_memory_budget_) { |
717 TRACE_COUNTER_ID2("cc", | 736 TRACE_COUNTER_ID2("cc", |
718 "over_memory_budget", | 737 "over_memory_budget", |
719 this, | 738 this, |
720 "budget", | 739 "budget", |
721 global_state_.memory_limit_in_bytes, | 740 global_state_.hard_memory_limit_in_bytes, |
722 "over", | 741 "over", |
723 bytes_that_exceeded_memory_budget); | 742 bytes_that_exceeded_memory_budget); |
724 } | 743 } |
725 memory_stats_from_last_assign_.total_budget_in_bytes = | 744 memory_stats_from_last_assign_.total_budget_in_bytes = |
726 global_state_.memory_limit_in_bytes; | 745 global_state_.hard_memory_limit_in_bytes; |
727 memory_stats_from_last_assign_.bytes_allocated = | 746 memory_stats_from_last_assign_.bytes_allocated = |
728 bytes_allocatable - bytes_left; | 747 hard_bytes_allocatable - hard_bytes_left; |
729 memory_stats_from_last_assign_.bytes_unreleasable = | 748 memory_stats_from_last_assign_.bytes_unreleasable = |
730 bytes_allocatable - bytes_releasable_; | 749 hard_bytes_allocatable - bytes_releasable_; |
731 memory_stats_from_last_assign_.bytes_over = bytes_that_exceeded_memory_budget; | 750 memory_stats_from_last_assign_.bytes_over = bytes_that_exceeded_memory_budget; |
732 } | 751 } |
733 | 752 |
734 void TileManager::FreeResourceForTile(Tile* tile, RasterMode mode) { | 753 void TileManager::FreeResourceForTile(Tile* tile, RasterMode mode) { |
735 ManagedTileState& mts = tile->managed_state(); | 754 ManagedTileState& mts = tile->managed_state(); |
736 if (mts.tile_versions[mode].resource_) { | 755 if (mts.tile_versions[mode].resource_) { |
737 resource_pool_->ReleaseResource(mts.tile_versions[mode].resource_.Pass()); | 756 resource_pool_->ReleaseResource(mts.tile_versions[mode].resource_.Pass()); |
738 | 757 |
739 DCHECK_GE(bytes_releasable_, BytesConsumedIfAllocated(tile)); | 758 DCHECK_GE(bytes_releasable_, BytesConsumedIfAllocated(tile)); |
740 DCHECK_GE(resources_releasable_, 1u); | 759 DCHECK_GE(resources_releasable_, 1u); |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
957 flags)); | 976 flags)); |
958 DCHECK(tiles_.find(tile->id()) == tiles_.end()); | 977 DCHECK(tiles_.find(tile->id()) == tiles_.end()); |
959 | 978 |
960 tiles_[tile->id()] = tile; | 979 tiles_[tile->id()] = tile; |
961 used_layer_counts_[tile->layer_id()]++; | 980 used_layer_counts_[tile->layer_id()]++; |
962 prioritized_tiles_dirty_ = true; | 981 prioritized_tiles_dirty_ = true; |
963 return tile; | 982 return tile; |
964 } | 983 } |
965 | 984 |
966 } // namespace cc | 985 } // namespace cc |
OLD | NEW |