OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 // This file contains the implementation of the FencedAllocator class. | 5 // This file contains the implementation of the FencedAllocator class. |
6 | 6 |
7 #include "gpu/command_buffer/client/fenced_allocator.h" | 7 #include "gpu/command_buffer/client/fenced_allocator.h" |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 | 10 |
(...skipping 24 matching lines...) Expand all Loading... | |
35 | 35 |
36 FencedAllocator::FencedAllocator(unsigned int size, | 36 FencedAllocator::FencedAllocator(unsigned int size, |
37 CommandBufferHelper *helper) | 37 CommandBufferHelper *helper) |
38 : helper_(helper), | 38 : helper_(helper), |
39 bytes_in_use_(0) { | 39 bytes_in_use_(0) { |
40 Block block = { FREE, 0, RoundDown(size), kUnusedToken }; | 40 Block block = { FREE, 0, RoundDown(size), kUnusedToken }; |
41 blocks_.push_back(block); | 41 blocks_.push_back(block); |
42 } | 42 } |
43 | 43 |
44 FencedAllocator::~FencedAllocator() { | 44 FencedAllocator::~FencedAllocator() { |
45 // Free blocks pending tokens. | 45 // Free blocks pending tokens and serials. |
46 for (unsigned int i = 0; i < blocks_.size(); ++i) { | 46 for (unsigned int i = 0; i < blocks_.size(); ++i) { |
47 if (blocks_[i].state == FREE_PENDING_TOKEN) { | 47 if (blocks_[i].state == FREE_PENDING_TOKEN) { |
48 i = WaitForTokenAndFreeBlock(i); | 48 i = WaitForTokenAndFreeBlock(i); |
49 } else if (blocks_[i].state == FREE_PENDING_SERIAL) { | |
50 Block &block = blocks_[i]; | |
51 block.state = FREE; | |
52 CollapseFreeBlock(i); | |
piman
2014/01/11 02:02:32
This is probably ok in the current use, if we can
jadahl
2014/01/16 16:24:39
Where do you suggest we document this? Here?
| |
49 } | 53 } |
50 } | 54 } |
51 // These checks are not valid if the service has crashed or lost the context. | 55 // These checks are not valid if the service has crashed or lost the context. |
52 // DCHECK_EQ(blocks_.size(), 1u); | 56 // DCHECK_EQ(blocks_.size(), 1u); |
53 // DCHECK_EQ(blocks_[0].state, FREE); | 57 // DCHECK_EQ(blocks_[0].state, FREE); |
54 } | 58 } |
55 | 59 |
56 // Looks for a non-allocated block that is big enough. Search in the FREE | 60 // Looks for a non-allocated block that is big enough. Search in the FREE |
57 // blocks first (for direct usage), first-fit, then in the FREE_PENDING_TOKEN | 61 // blocks first (for direct usage), first-fit, then in the FREE_PENDING_TOKEN |
58 // blocks, waiting for them. The current implementation isn't smart about | 62 // blocks, waiting for them. The current implementation isn't smart about |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
106 void FencedAllocator::FreePendingToken( | 110 void FencedAllocator::FreePendingToken( |
107 FencedAllocator::Offset offset, int32 token) { | 111 FencedAllocator::Offset offset, int32 token) { |
108 BlockIndex index = GetBlockByOffset(offset); | 112 BlockIndex index = GetBlockByOffset(offset); |
109 Block &block = blocks_[index]; | 113 Block &block = blocks_[index]; |
110 if (block.state == IN_USE) | 114 if (block.state == IN_USE) |
111 bytes_in_use_ -= block.size; | 115 bytes_in_use_ -= block.size; |
112 block.state = FREE_PENDING_TOKEN; | 116 block.state = FREE_PENDING_TOKEN; |
113 block.token = token; | 117 block.token = token; |
114 } | 118 } |
115 | 119 |
120 void FencedAllocator::FreePendingSerial( | |
121 FencedAllocator::Offset offset, uint32 serial) { | |
122 BlockIndex index = GetBlockByOffset(offset); | |
123 Block &block = blocks_[index]; | |
124 if (block.state == IN_USE) | |
125 bytes_in_use_ -= block.size; | |
126 block.state = FREE_PENDING_SERIAL; | |
127 block.serial = serial; | |
128 } | |
129 | |
116 // Gets the max of the size of the blocks marked as free. | 130 // Gets the max of the size of the blocks marked as free. |
117 unsigned int FencedAllocator::GetLargestFreeSize() { | 131 unsigned int FencedAllocator::GetLargestFreeSize() { |
118 FreeUnused(); | 132 FreeUnused(); |
119 unsigned int max_size = 0; | 133 unsigned int max_size = 0; |
120 for (unsigned int i = 0; i < blocks_.size(); ++i) { | 134 for (unsigned int i = 0; i < blocks_.size(); ++i) { |
121 Block &block = blocks_[i]; | 135 Block &block = blocks_[i]; |
122 if (block.state == FREE) | 136 if (block.state == FREE) |
123 max_size = std::max(max_size, block.size); | 137 max_size = std::max(max_size, block.size); |
124 } | 138 } |
125 return max_size; | 139 return max_size; |
126 } | 140 } |
127 | 141 |
128 // Gets the size of the largest segment of blocks that are either FREE or | 142 // Gets the size of the largest segment of blocks that are either FREE or |
129 // FREE_PENDING_TOKEN. | 143 // FREE_PENDING_TOKEN. |
130 unsigned int FencedAllocator::GetLargestFreeOrPendingSize() { | 144 unsigned int FencedAllocator::GetLargestFreeOrPendingSize() { |
131 unsigned int max_size = 0; | 145 unsigned int max_size = 0; |
132 unsigned int current_size = 0; | 146 unsigned int current_size = 0; |
133 for (unsigned int i = 0; i < blocks_.size(); ++i) { | 147 for (unsigned int i = 0; i < blocks_.size(); ++i) { |
134 Block &block = blocks_[i]; | 148 Block &block = blocks_[i]; |
135 if (block.state == IN_USE) { | 149 if (block.state == IN_USE || block.state == FREE_PENDING_SERIAL) { |
136 max_size = std::max(max_size, current_size); | 150 max_size = std::max(max_size, current_size); |
137 current_size = 0; | 151 current_size = 0; |
138 } else { | 152 } else { |
139 DCHECK(block.state == FREE || block.state == FREE_PENDING_TOKEN); | 153 DCHECK(block.state == FREE || block.state == FREE_PENDING_TOKEN); |
140 current_size += block.size; | 154 current_size += block.size; |
141 } | 155 } |
142 } | 156 } |
143 return std::max(max_size, current_size); | 157 return std::max(max_size, current_size); |
144 } | 158 } |
145 | 159 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
197 Block &block = blocks_[index]; | 211 Block &block = blocks_[index]; |
198 DCHECK_EQ(block.state, FREE_PENDING_TOKEN); | 212 DCHECK_EQ(block.state, FREE_PENDING_TOKEN); |
199 helper_->WaitForToken(block.token); | 213 helper_->WaitForToken(block.token); |
200 block.state = FREE; | 214 block.state = FREE; |
201 return CollapseFreeBlock(index); | 215 return CollapseFreeBlock(index); |
202 } | 216 } |
203 | 217 |
204 // Frees any blocks pending a token for which the token has been read. | 218 // Frees any blocks pending a token for which the token has been read. |
205 void FencedAllocator::FreeUnused() { | 219 void FencedAllocator::FreeUnused() { |
206 int32 last_token_read = helper_->last_token_read(); | 220 int32 last_token_read = helper_->last_token_read(); |
221 uint32 last_serial_read = helper_->last_serial_read(); | |
207 for (unsigned int i = 0; i < blocks_.size();) { | 222 for (unsigned int i = 0; i < blocks_.size();) { |
208 Block& block = blocks_[i]; | 223 Block& block = blocks_[i]; |
209 if (block.state == FREE_PENDING_TOKEN && block.token <= last_token_read) { | 224 if (block.state == FREE_PENDING_TOKEN && block.token <= last_token_read) { |
210 block.state = FREE; | 225 block.state = FREE; |
211 i = CollapseFreeBlock(i); | 226 i = CollapseFreeBlock(i); |
227 } else if (block.state == FREE_PENDING_SERIAL && | |
228 block.serial <= last_serial_read) { | |
reveman
2014/01/11 23:39:04
maybe use a switch statement here and above
| |
229 block.state = FREE; | |
230 i = CollapseFreeBlock(i); | |
212 } else { | 231 } else { |
213 ++i; | 232 ++i; |
214 } | 233 } |
215 } | 234 } |
216 } | 235 } |
217 | 236 |
218 // If the block is exactly the requested size, simply mark it IN_USE, otherwise | 237 // If the block is exactly the requested size, simply mark it IN_USE, otherwise |
219 // split it and mark the first one (of the requested size) IN_USE. | 238 // split it and mark the first one (of the requested size) IN_USE. |
220 FencedAllocator::Offset FencedAllocator::AllocInBlock(BlockIndex index, | 239 FencedAllocator::Offset FencedAllocator::AllocInBlock(BlockIndex index, |
221 unsigned int size) { | 240 unsigned int size) { |
222 Block &block = blocks_[index]; | 241 Block &block = blocks_[index]; |
223 DCHECK_GE(block.size, size); | 242 DCHECK_GE(block.size, size); |
224 DCHECK_EQ(block.state, FREE); | 243 DCHECK_EQ(block.state, FREE); |
225 Offset offset = block.offset; | 244 Offset offset = block.offset; |
226 bytes_in_use_ += size; | 245 bytes_in_use_ += size; |
227 if (block.size == size) { | 246 if (block.size == size) { |
228 block.state = IN_USE; | 247 block.state = IN_USE; |
229 return offset; | 248 return offset; |
230 } | 249 } |
231 Block newblock = { FREE, offset + size, block.size - size, kUnusedToken}; | 250 Block newblock = { |
251 FREE, offset + size, | |
252 block.size - size, | |
253 kUnusedToken, | |
254 kUnusedSerial | |
255 }; | |
232 block.state = IN_USE; | 256 block.state = IN_USE; |
233 block.size = size; | 257 block.size = size; |
234 // this is the last thing being done because it may invalidate block; | 258 // this is the last thing being done because it may invalidate block; |
235 blocks_.insert(blocks_.begin() + index + 1, newblock); | 259 blocks_.insert(blocks_.begin() + index + 1, newblock); |
236 return offset; | 260 return offset; |
237 } | 261 } |
238 | 262 |
239 // The blocks are in offset order, so we can do a binary search. | 263 // The blocks are in offset order, so we can do a binary search. |
240 FencedAllocator::BlockIndex FencedAllocator::GetBlockByOffset(Offset offset) { | 264 FencedAllocator::BlockIndex FencedAllocator::GetBlockByOffset(Offset offset) { |
241 Block templ = { IN_USE, offset, 0, kUnusedToken }; | 265 Block templ = { |
266 IN_USE, | |
267 offset, | |
268 0, | |
269 kUnusedToken, | |
270 kUnusedSerial | |
271 }; | |
242 Container::iterator it = std::lower_bound(blocks_.begin(), blocks_.end(), | 272 Container::iterator it = std::lower_bound(blocks_.begin(), blocks_.end(), |
243 templ, OffsetCmp()); | 273 templ, OffsetCmp()); |
244 DCHECK(it != blocks_.end() && it->offset == offset); | 274 DCHECK(it != blocks_.end() && it->offset == offset); |
245 return it-blocks_.begin(); | 275 return it-blocks_.begin(); |
246 } | 276 } |
247 | 277 |
248 } // namespace gpu | 278 } // namespace gpu |
OLD | NEW |