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

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

Issue 9289052: Adding GpuMemoryManager to track GpuCommandBufferStub visibility and last_used_time and dictate mem… (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Changing to use gpu_memory_allocation.h file so it lands first Created 8 years, 11 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "content/common/gpu/gpu_memory_manager.h"
6
7 #if defined(ENABLE_GPU)
8
9 #include "content/common/gpu/gpu_channel_manager.h"
10 #include "content/common/gpu/gpu_channel.h"
11 #include "content/common/gpu/gpu_command_buffer_stub.h"
12
13 #include <vector>
14
15 ////////////////////////////////////////////////////////////////////////////////
16 // Local helpers
17
18 namespace {
19
20 /*
21 * A RenderWidgetDescriptor is used to combine the information various stubs
22 * receive, in order to best infer the RenderWidget's current state.
23 */
24 class RenderWidgetDescriptor {
25 public:
26 RenderWidgetDescriptor(int render_widget_id,
nduca 2012/01/27 10:10:13 This comment applies to this entire patch. but we
27 bool visible,
28 int64 last_used_time,
29 GpuCommandBufferStub* stub)
30 : render_widget_id_(render_widget_id)
31 , visible_(visible)
32 , last_used_time_(last_used_time)
33 , stubs_(1,stub) {
34 }
35
36 public:
37 int render_widget_id() const { return render_widget_id_; }
38 bool visible() const { return visible_; }
39 int64 last_used_time() const { return last_used_time_; }
40 std::vector<GpuCommandBufferStub*> const& stubs() const { return stubs_; }
41
42 // This is a helper function to learn from another descriptor for the same
nduca 2012/01/27 10:10:13 ??? when do you merge? This feels like some seriou
mmocny 2012/01/27 19:51:33 This is a convenience function which I will move o
43 // RenderWidget, thus creating a single more accurate one.
44 void merge(RenderWidgetDescriptor const& other) {
45 DCHECK(render_widget_id_ == other.render_widget_id_);
46 // Check if this RWD has staler data than other:
47 if ((last_used_time_ == GpuCommandBufferStub::kUnknownLastUsedTime) ||
48 (other.last_used_time_ != GpuCommandBufferStub::kUnknownLastUsedTime &&
49 last_used_time_ < other.last_used_time_)) {
50 visible_ = other.visible_;
51 last_used_time_ = other.last_used_time_;
52 }
53 // Either way, merge stubs
54 stubs_.insert(stubs_.end(), other.stubs_.begin(), other.stubs_.end());
55 // TODO(mmocny): DCHECK(confirm-no-duplicates)
56 // This is currently certain to be true, but should state assumptions
57 // since this assumption isn't enforced
58 }
59
60 private:
61 int render_widget_id_;
62
63 bool visible_;
64 int64 last_used_time_;
65
66 std::vector<GpuCommandBufferStub*> stubs_;
67 };
68
69 /*
70 * Used to sort RenderWidgetDescriptors into most-to-least "important" order
71 */
72 struct RenderWidgetDescriptorSorter {
73 bool operator()(RenderWidgetDescriptor* lhs, RenderWidgetDescriptor* rhs) {
74 if (lhs->visible() != rhs->visible()) // Visible RWD first
75 return lhs->visible();
76 else if (lhs->visible()) // Use id as tiebreaker when both are visible
77 return lhs->render_widget_id() < rhs->render_widget_id();
78
79 DCHECK(lhs->last_used_time() != GpuCommandBufferStub::kUnknownLastUsedTime);
80 DCHECK(rhs->last_used_time() != GpuCommandBufferStub::kUnknownLastUsedTime);
81 // Last-used-time order for non visible ones
82 return lhs->last_used_time() > rhs->last_used_time();
83 }
84 };
nduca 2012/01/27 10:10:13 Unit tests, or file a bug and write unit tests aft
mmocny 2012/01/27 19:51:33 This should be easy to test. On 2012/01/27 10:10:
85
86 /*
87 * GetGpuCommandBufferStubs
88 */
89 std::vector<GpuCommandBufferStub*> GetGpuCommandBufferStubs(
90 GpuChannelManager* channel_manager) {
91 std::vector<GpuCommandBufferStub*> ret;
92
93 std::vector<GpuChannel*> channels = channel_manager->GetChannels();
94
95 for (std::vector<GpuChannel*>::const_iterator channel_it = channels.begin();
96 channel_it != channels.end(); ++channel_it ) {
97 GpuChannel* channel = *channel_it;
98 std::vector<GpuCommandBufferStub*> stubs = channel->GetCommandBuffers();
99 ret.insert(ret.end(), stubs.begin(), stubs.end());
100 }
101 return ret;
102 }
103
104 /*
105 * ComputeRenderWidgetDescriptorsFromStubs
106 */
107 std::vector<RenderWidgetDescriptor*> ComputeRenderWidgetDescriptorsFromStubs(
nduca 2012/01/27 10:10:13 Why are you doing this? Why not just get a vector
mmocny 2012/01/27 19:51:33 I promise there was a method to this madness but I
108 std::vector<GpuCommandBufferStub*> stubs) {
109 std::vector<RenderWidgetDescriptor*> ret;
110
111 for (std::vector<GpuCommandBufferStub*>::iterator gcbs_it = stubs.begin();
112 gcbs_it != stubs.end(); ++gcbs_it) {
113 GpuCommandBufferStub* stub = *gcbs_it;
114 std::vector<int> render_widget_ids = stub->render_widget_ids();
115
116 for (std::vector<int>::iterator rwids_it = render_widget_ids.begin();
117 rwids_it != render_widget_ids.end(); ++rwids_it) {
118 RenderWidgetDescriptor* rwd = new RenderWidgetDescriptor(*rwids_it,
119 stub->visible(), stub->last_used_time(), stub);
120
121 // Try to find existing Render Widget
122 for (std::vector<RenderWidgetDescriptor*>::iterator rwds_it = ret.begin();
123 rwds_it != ret.end(); ++rwds_it) {
124 if ((*rwds_it)->render_widget_id() == *rwids_it) {
125 (*rwds_it)->merge(*rwd);
126 rwd = NULL;
127 break;
128 }
129 }
130 if (rwd)
131 ret.push_back(rwd);
132 }
133 }
134
135 return ret;
136 }
137
138 }
139
140 ////////////////////////////////////////////////////////////////////////////////
141 // Constructors/Destructors
142
143 GpuMemoryManager::GpuMemoryManager(GpuChannelManager* channel_manager)
144 : channel_manager_(channel_manager) {
145
146 }
147
148 GpuMemoryManager::~GpuMemoryManager() {
149 }
150
151 ////////////////////////////////////////////////////////////////////////////////
152
153 void GpuMemoryManager::Manage() const {
154 // Compute RenderWidgetDescriptors from GpuCommandBufferStubs
155 std::vector<GpuCommandBufferStub*> stubs = GetGpuCommandBufferStubs(
156 channel_manager_);
157 std::vector<RenderWidgetDescriptor*> render_widget_descriptors =
158 ComputeRenderWidgetDescriptorsFromStubs(stubs);
159
160 // Sort them in {visibility,last_used_time} order using custom sorter
161 std::sort(render_widget_descriptors.begin(), render_widget_descriptors.end(),
162 RenderWidgetDescriptorSorter());
163
164 // TODO(mmocny): What follows is vastly simplified logic based on counts,
165 // should consider actual memory usage and availability.
166
167 // Separate into three sets, identified by render_widget_id
168 // 1. all_buffers: Every visible RenderWidget must have all buffers.
169 // 2. front_buffers: Invisible RenderWidgets can have a frontbuffer if the
170 // the total count is under some soft limit.
171 // 3. no_buffers: The rest should drop all buffers.
172 // TODO(mmocny): all_buffers takes up ~3 times more memory than front_buffers.
173 // Couldn't we have 3 front_buffer per each all_buffer?
174 std::set<int> all_buffers, front_buffers, no_buffers;
175 static const size_t kMaxFrontBufferSoftLimit = 8;
176
177 for (std::vector<RenderWidgetDescriptor*>::iterator rwds_it =
178 render_widget_descriptors.begin();
179 rwds_it != render_widget_descriptors.end(); ++rwds_it) {
180 RenderWidgetDescriptor* rwd = *rwds_it;
181 if (rwd->visible())
182 all_buffers.insert(rwd->render_widget_id());
183 else if ((all_buffers.size() + front_buffers.size()) <
184 kMaxFrontBufferSoftLimit)
185 front_buffers.insert(rwd->render_widget_id());
186 else
187 no_buffers.insert(rwd->render_widget_id());
188 }
189
190 // Now, go through the command buffer stubs, and match their render widgets
191 // up to the buckets we divided. Since they may be associated with
192 // RenderWidgets in various buckets, the most visible one takes priority
193 for (std::vector<GpuCommandBufferStub*>::const_iterator it = stubs.begin();
194 it != stubs.end(); ++it) {
195 GpuCommandBufferStub* stub = *it;
196 GpuMemoryAllocation allocation;
197 std::vector<int> render_widget_ids = stub->render_widget_ids();
198 if (std::find_first_of(all_buffers.begin(), all_buffers.end(),
199 render_widget_ids.begin(), render_widget_ids.end()) !=
200 all_buffers.end()) {
201 allocation.gpuResourceSizeInBytes =
202 GpuMemoryAllocation::kResourceSizeForegroundTab;
203 allocation.hasFrontbuffer = true;
204 allocation.hasBackbuffer = true;
205 } else if (std::find_first_of(front_buffers.begin(), front_buffers.end(),
206 render_widget_ids.begin(), render_widget_ids.end()) !=
207 front_buffers.end()) {
208 allocation.gpuResourceSizeInBytes =
209 GpuMemoryAllocation::kResourceSizeBackgroundTab;
210 allocation.hasFrontbuffer = true;
211 allocation.hasBackbuffer = false;
212 } else {
213 allocation.gpuResourceSizeInBytes =
214 GpuMemoryAllocation::kResourceSizeHibernatedTab;
215 allocation.hasFrontbuffer = false;
216 allocation.hasBackbuffer = false;
217 }
218 stub->SetMemoryAllocation(allocation);
219 }
220 }
221
nduca 2012/01/27 10:10:13 No tests? That is scary. It loosk like we dont ha
Ken Russell (switch to Gerrit) 2012/01/27 19:21:24 +1 to testing this from the start. I haven't been
mmocny 2012/01/27 19:51:33 ok. On 2012/01/27 10:10:13, nduca wrote:
222 ////////////////////////////////////////////////////////////////////////////////
223
224 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698