| OLD | NEW |
| 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 "content/common/gpu/gpu_memory_manager.h" | 5 #include "content/common/gpu/gpu_memory_manager.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 49 GpuChannelManager* channel_manager, | 49 GpuChannelManager* channel_manager, |
| 50 uint64 max_surfaces_with_frontbuffer_soft_limit) | 50 uint64 max_surfaces_with_frontbuffer_soft_limit) |
| 51 : channel_manager_(channel_manager), | 51 : channel_manager_(channel_manager), |
| 52 use_nonuniform_memory_policy_(false), | 52 use_nonuniform_memory_policy_(false), |
| 53 manage_immediate_scheduled_(false), | 53 manage_immediate_scheduled_(false), |
| 54 max_surfaces_with_frontbuffer_soft_limit_( | 54 max_surfaces_with_frontbuffer_soft_limit_( |
| 55 max_surfaces_with_frontbuffer_soft_limit), | 55 max_surfaces_with_frontbuffer_soft_limit), |
| 56 bytes_available_gpu_memory_(0), | 56 bytes_available_gpu_memory_(0), |
| 57 bytes_available_gpu_memory_overridden_(false), | 57 bytes_available_gpu_memory_overridden_(false), |
| 58 bytes_minimum_per_client_(0), | 58 bytes_minimum_per_client_(0), |
| 59 bytes_minimum_per_client_overridden_(false), | 59 bytes_default_per_client_(0), |
| 60 bytes_nonvisible_available_gpu_memory_(0), | 60 bytes_nonvisible_available_gpu_memory_(0), |
| 61 bytes_allocated_managed_current_(0), | 61 bytes_allocated_managed_current_(0), |
| 62 bytes_allocated_managed_visible_(0), | 62 bytes_allocated_managed_visible_(0), |
| 63 bytes_allocated_managed_nonvisible_(0), | 63 bytes_allocated_managed_nonvisible_(0), |
| 64 bytes_allocated_unmanaged_current_(0), | 64 bytes_allocated_unmanaged_current_(0), |
| 65 bytes_allocated_historical_max_(0), | 65 bytes_allocated_historical_max_(0), |
| 66 bytes_allocated_unmanaged_high_(0), | 66 bytes_allocated_unmanaged_high_(0), |
| 67 bytes_allocated_unmanaged_low_(0), | 67 bytes_allocated_unmanaged_low_(0), |
| 68 bytes_unmanaged_limit_step_(kBytesAllocatedUnmanagedStep), | 68 bytes_unmanaged_limit_step_(kBytesAllocatedUnmanagedStep), |
| 69 window_count_has_been_received_(false), | 69 window_count_has_been_received_(false), |
| 70 window_count_(0), | 70 window_count_(0), |
| 71 disable_schedule_manage_(false) | 71 disable_schedule_manage_(false) |
| 72 { | 72 { |
| 73 CommandLine* command_line = CommandLine::ForCurrentProcess(); | 73 CommandLine* command_line = CommandLine::ForCurrentProcess(); |
| 74 |
| 75 #if defined(OS_ANDROID) |
| 76 bytes_default_per_client_ = 32 * 1024 * 1024; |
| 77 bytes_minimum_per_client_ = 32 * 1024 * 1024; |
| 78 #else |
| 79 bytes_default_per_client_ = 64 * 1024 * 1024; |
| 80 bytes_minimum_per_client_ = 64 * 1024 * 1024; |
| 81 #endif |
| 82 |
| 74 if (command_line->HasSwitch(switches::kForceGpuMemAvailableMb)) { | 83 if (command_line->HasSwitch(switches::kForceGpuMemAvailableMb)) { |
| 75 base::StringToUint64( | 84 base::StringToUint64( |
| 76 command_line->GetSwitchValueASCII(switches::kForceGpuMemAvailableMb), | 85 command_line->GetSwitchValueASCII(switches::kForceGpuMemAvailableMb), |
| 77 &bytes_available_gpu_memory_); | 86 &bytes_available_gpu_memory_); |
| 78 bytes_available_gpu_memory_ *= 1024 * 1024; | 87 bytes_available_gpu_memory_ *= 1024 * 1024; |
| 79 bytes_available_gpu_memory_overridden_ = true; | 88 bytes_available_gpu_memory_overridden_ = true; |
| 80 } else | 89 } else |
| 81 bytes_available_gpu_memory_ = GetDefaultAvailableGpuMemory(); | 90 bytes_available_gpu_memory_ = GetDefaultAvailableGpuMemory(); |
| 82 UpdateNonvisibleAvailableGpuMemory(); | 91 UpdateNonvisibleAvailableGpuMemory(); |
| 83 } | 92 } |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 131 #if defined(OS_ANDROID) || defined(OS_CHROMEOS) | 140 #if defined(OS_ANDROID) || defined(OS_CHROMEOS) |
| 132 return bytes_available_gpu_memory_; | 141 return bytes_available_gpu_memory_; |
| 133 #else | 142 #else |
| 134 // This is to avoid allowing a single page on to use a full 256MB of memory | 143 // This is to avoid allowing a single page on to use a full 256MB of memory |
| 135 // (the current total limit). Long-scroll pages will hit this limit, | 144 // (the current total limit). Long-scroll pages will hit this limit, |
| 136 // resulting in instability on some platforms (e.g, issue 141377). | 145 // resulting in instability on some platforms (e.g, issue 141377). |
| 137 return bytes_available_gpu_memory_ / 2; | 146 return bytes_available_gpu_memory_ / 2; |
| 138 #endif | 147 #endif |
| 139 } | 148 } |
| 140 | 149 |
| 141 uint64 GpuMemoryManager::GetMinimumClientAllocation() const { | |
| 142 if (bytes_minimum_per_client_overridden_) | |
| 143 return bytes_minimum_per_client_; | |
| 144 #if defined(OS_ANDROID) | |
| 145 return 32 * 1024 * 1024; | |
| 146 #elif defined(OS_CHROMEOS) | |
| 147 return 64 * 1024 * 1024; | |
| 148 #else | |
| 149 return 64 * 1024 * 1024; | |
| 150 #endif | |
| 151 } | |
| 152 | |
| 153 uint64 GpuMemoryManager::CalcAvailableFromViewportArea(int viewport_area) { | 150 uint64 GpuMemoryManager::CalcAvailableFromViewportArea(int viewport_area) { |
| 154 // We can't query available GPU memory from the system on Android, but | 151 // We can't query available GPU memory from the system on Android, but |
| 155 // 18X the viewport and 50% of the dalvik heap size give us a good | 152 // 18X the viewport and 50% of the dalvik heap size give us a good |
| 156 // estimate of available GPU memory on a wide range of devices. | 153 // estimate of available GPU memory on a wide range of devices. |
| 157 const int kViewportMultiplier = 18; | 154 const int kViewportMultiplier = 18; |
| 158 const unsigned int kComponentsPerPixel = 4; // GraphicsContext3D::RGBA | 155 const unsigned int kComponentsPerPixel = 4; // GraphicsContext3D::RGBA |
| 159 const unsigned int kBytesPerComponent = 1; // sizeof(GC3Dubyte) | 156 const unsigned int kBytesPerComponent = 1; // sizeof(GC3Dubyte) |
| 160 uint64 viewport_limit = viewport_area * kViewportMultiplier * | 157 uint64 viewport_limit = viewport_area * kViewportMultiplier * |
| 161 kComponentsPerPixel * | 158 kComponentsPerPixel * |
| 162 kBytesPerComponent; | 159 kBytesPerComponent; |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 382 GpuMemoryManagerClientState* client_state, | 379 GpuMemoryManagerClientState* client_state, |
| 383 const GpuManagedMemoryStats& stats) | 380 const GpuManagedMemoryStats& stats) |
| 384 { | 381 { |
| 385 TrackValueChanged(client_state->managed_memory_stats_.bytes_allocated, | 382 TrackValueChanged(client_state->managed_memory_stats_.bytes_allocated, |
| 386 stats.bytes_allocated, | 383 stats.bytes_allocated, |
| 387 client_state->visible_ ? | 384 client_state->visible_ ? |
| 388 &bytes_allocated_managed_visible_ : | 385 &bytes_allocated_managed_visible_ : |
| 389 &bytes_allocated_managed_nonvisible_); | 386 &bytes_allocated_managed_nonvisible_); |
| 390 client_state->managed_memory_stats_ = stats; | 387 client_state->managed_memory_stats_ = stats; |
| 391 | 388 |
| 389 // If this is the first time that stats have been received for this |
| 390 // client, use them immediately. |
| 391 if (!client_state->managed_memory_stats_received_) { |
| 392 client_state->managed_memory_stats_received_ = true; |
| 393 ScheduleManage(kScheduleManageNow); |
| 394 return; |
| 395 } |
| 396 |
| 392 if (use_nonuniform_memory_policy_) { | 397 if (use_nonuniform_memory_policy_) { |
| 393 // If these statistics sit outside of the range that we used in our | 398 // If these statistics sit outside of the range that we used in our |
| 394 // computation of memory allocations then recompute the allocations. | 399 // computation of memory allocations then recompute the allocations. |
| 395 if (client_state->managed_memory_stats_.bytes_nice_to_have > | 400 if (client_state->managed_memory_stats_.bytes_nice_to_have > |
| 396 client_state->bytes_nicetohave_limit_high_) { | 401 client_state->bytes_nicetohave_limit_high_) { |
| 397 ScheduleManage(kScheduleManageNow); | 402 ScheduleManage(kScheduleManageNow); |
| 398 } else if (client_state->managed_memory_stats_.bytes_nice_to_have < | 403 } else if (client_state->managed_memory_stats_.bytes_nice_to_have < |
| 399 client_state->bytes_nicetohave_limit_low_) { | 404 client_state->bytes_nicetohave_limit_low_) { |
| 400 ScheduleManage(kScheduleManageLater); | 405 ScheduleManage(kScheduleManageLater); |
| 401 } | 406 } |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 554 return bytes_sum_limit / bytes_size; | 559 return bytes_sum_limit / bytes_size; |
| 555 } | 560 } |
| 556 | 561 |
| 557 uint64 GpuMemoryManager::ComputeClientAllocationWhenVisible( | 562 uint64 GpuMemoryManager::ComputeClientAllocationWhenVisible( |
| 558 GpuMemoryManagerClientState* client_state, | 563 GpuMemoryManagerClientState* client_state, |
| 559 uint64 bytes_above_required_cap, | 564 uint64 bytes_above_required_cap, |
| 560 uint64 bytes_above_minimum_cap, | 565 uint64 bytes_above_minimum_cap, |
| 561 uint64 bytes_overall_cap) { | 566 uint64 bytes_overall_cap) { |
| 562 GpuManagedMemoryStats* stats = &client_state->managed_memory_stats_; | 567 GpuManagedMemoryStats* stats = &client_state->managed_memory_stats_; |
| 563 | 568 |
| 569 if (!client_state->managed_memory_stats_received_) |
| 570 return GetDefaultClientAllocation(); |
| 571 |
| 564 uint64 bytes_required = 9 * stats->bytes_required / 8; | 572 uint64 bytes_required = 9 * stats->bytes_required / 8; |
| 565 bytes_required = std::min(bytes_required, GetMaximumClientAllocation()); | 573 bytes_required = std::min(bytes_required, GetMaximumClientAllocation()); |
| 566 bytes_required = std::max(bytes_required, GetMinimumClientAllocation()); | 574 bytes_required = std::max(bytes_required, GetMinimumClientAllocation()); |
| 567 | 575 |
| 568 uint64 bytes_nicetohave = 4 * stats->bytes_nice_to_have / 3; | 576 uint64 bytes_nicetohave = 4 * stats->bytes_nice_to_have / 3; |
| 569 bytes_nicetohave = std::min(bytes_nicetohave, GetMaximumClientAllocation()); | 577 bytes_nicetohave = std::min(bytes_nicetohave, GetMaximumClientAllocation()); |
| 570 bytes_nicetohave = std::max(bytes_nicetohave, GetMinimumClientAllocation()); | 578 bytes_nicetohave = std::max(bytes_nicetohave, GetMinimumClientAllocation()); |
| 571 bytes_nicetohave = std::max(bytes_nicetohave, bytes_required); | 579 bytes_nicetohave = std::max(bytes_nicetohave, bytes_required); |
| 572 | 580 |
| 573 uint64 allocation = GetMinimumClientAllocation(); | 581 uint64 allocation = GetMinimumClientAllocation(); |
| 574 allocation += std::min(bytes_required - GetMinimumClientAllocation(), | 582 allocation += std::min(bytes_required - GetMinimumClientAllocation(), |
| 575 bytes_above_minimum_cap); | 583 bytes_above_minimum_cap); |
| 576 allocation += std::min(bytes_nicetohave - bytes_required, | 584 allocation += std::min(bytes_nicetohave - bytes_required, |
| 577 bytes_above_required_cap); | 585 bytes_above_required_cap); |
| 578 allocation = std::min(allocation, | 586 allocation = std::min(allocation, |
| 579 bytes_overall_cap); | 587 bytes_overall_cap); |
| 580 return allocation; | 588 return allocation; |
| 581 } | 589 } |
| 582 | 590 |
| 583 uint64 GpuMemoryManager::ComputeClientAllocationWhenNonvisible( | 591 uint64 GpuMemoryManager::ComputeClientAllocationWhenNonvisible( |
| 584 GpuMemoryManagerClientState* client_state) { | 592 GpuMemoryManagerClientState* client_state) { |
| 593 |
| 594 if (!client_state->managed_memory_stats_received_) |
| 595 return 0; |
| 596 |
| 585 return 9 * client_state->managed_memory_stats_.bytes_required / 8; | 597 return 9 * client_state->managed_memory_stats_.bytes_required / 8; |
| 586 } | 598 } |
| 587 | 599 |
| 588 void GpuMemoryManager::ComputeVisibleSurfacesAllocationsNonuniform() { | 600 void GpuMemoryManager::ComputeVisibleSurfacesAllocationsNonuniform() { |
| 589 uint64 bytes_available_total = GetAvailableGpuMemory(); | 601 uint64 bytes_available_total = GetAvailableGpuMemory(); |
| 590 uint64 bytes_above_required_cap = std::numeric_limits<uint64>::max(); | 602 uint64 bytes_above_required_cap = std::numeric_limits<uint64>::max(); |
| 591 uint64 bytes_above_minimum_cap = std::numeric_limits<uint64>::max(); | 603 uint64 bytes_above_minimum_cap = std::numeric_limits<uint64>::max(); |
| 592 uint64 bytes_overall_cap_visible = GetMaximumClientAllocation(); | 604 uint64 bytes_overall_cap_visible = GetMaximumClientAllocation(); |
| 593 | 605 |
| 594 // Compute memory usage at three levels | 606 // Compute memory usage at three levels |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 748 bytes_available_nonvisible_adjusted) | 760 bytes_available_nonvisible_adjusted) |
| 749 client_state->bytes_allocation_when_nonvisible_ = 0; | 761 client_state->bytes_allocation_when_nonvisible_ = 0; |
| 750 } | 762 } |
| 751 | 763 |
| 752 // Compute which currently nonvisible clients should keep their contents. | 764 // Compute which currently nonvisible clients should keep their contents. |
| 753 for (ClientStateList::const_iterator it = clients_nonvisible_mru_.begin(); | 765 for (ClientStateList::const_iterator it = clients_nonvisible_mru_.begin(); |
| 754 it != clients_nonvisible_mru_.end(); | 766 it != clients_nonvisible_mru_.end(); |
| 755 ++it) { | 767 ++it) { |
| 756 GpuMemoryManagerClientState* client_state = *it; | 768 GpuMemoryManagerClientState* client_state = *it; |
| 757 | 769 |
| 770 // If this client is nonvisible and has already had its contents discarded, |
| 771 // don't re-generate the contents until the client becomes visible again. |
| 772 if (!client_state->bytes_allocation_when_nonvisible_) |
| 773 continue; |
| 774 |
| 758 client_state->bytes_allocation_when_nonvisible_ = | 775 client_state->bytes_allocation_when_nonvisible_ = |
| 759 ComputeClientAllocationWhenNonvisible(client_state); | 776 ComputeClientAllocationWhenNonvisible(client_state); |
| 760 | 777 |
| 761 // Take into account all more recently used nonvisible clients, and only if | 778 // Take into account all more recently used nonvisible clients, and only if |
| 762 // this client still fits, all it to keep its contents. | 779 // this client still fits, all it to keep its contents. |
| 763 if (bytes_allocated_nonvisible + | 780 if (bytes_allocated_nonvisible + |
| 764 client_state->bytes_allocation_when_nonvisible_ > | 781 client_state->bytes_allocation_when_nonvisible_ > |
| 765 bytes_allocated_nonvisible) { | 782 bytes_available_nonvisible) { |
| 766 client_state->bytes_allocation_when_nonvisible_ = 0; | 783 client_state->bytes_allocation_when_nonvisible_ = 0; |
| 767 } | 784 } |
| 768 bytes_allocated_nonvisible += | 785 bytes_allocated_nonvisible += |
| 769 client_state->bytes_allocation_when_nonvisible_; | 786 client_state->bytes_allocation_when_nonvisible_; |
| 770 } | 787 } |
| 771 } | 788 } |
| 772 | 789 |
| 773 void GpuMemoryManager::AssignSurfacesAllocationsNonuniform() { | 790 void GpuMemoryManager::AssignSurfacesAllocationsNonuniform() { |
| 774 // Compute allocation when for all clients. | 791 // Compute allocation when for all clients. |
| 775 ComputeVisibleSurfacesAllocationsNonuniform(); | 792 ComputeVisibleSurfacesAllocationsNonuniform(); |
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1025 | 1042 |
| 1026 void GpuMemoryManager::RemoveClientFromList( | 1043 void GpuMemoryManager::RemoveClientFromList( |
| 1027 GpuMemoryManagerClientState* client_state) { | 1044 GpuMemoryManagerClientState* client_state) { |
| 1028 DCHECK(client_state->list_iterator_valid_); | 1045 DCHECK(client_state->list_iterator_valid_); |
| 1029 ClientStateList* client_list = GetClientList(client_state); | 1046 ClientStateList* client_list = GetClientList(client_state); |
| 1030 client_list->erase(client_state->list_iterator_); | 1047 client_list->erase(client_state->list_iterator_); |
| 1031 client_state->list_iterator_valid_ = false; | 1048 client_state->list_iterator_valid_ = false; |
| 1032 } | 1049 } |
| 1033 | 1050 |
| 1034 } // namespace content | 1051 } // namespace content |
| OLD | NEW |