OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "GrVkMemory.h" | 8 #include "GrVkMemory.h" |
9 | 9 |
10 #include "GrVkGpu.h" | 10 #include "GrVkGpu.h" |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
235 } else if (VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL == layout) { | 235 } else if (VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL == layout) { |
236 flags = VK_ACCESS_TRANSFER_WRITE_BIT; | 236 flags = VK_ACCESS_TRANSFER_WRITE_BIT; |
237 } else if (VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL == layout) { | 237 } else if (VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL == layout) { |
238 flags = VK_ACCESS_TRANSFER_READ_BIT; | 238 flags = VK_ACCESS_TRANSFER_READ_BIT; |
239 } else if (VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL == layout) { | 239 } else if (VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL == layout) { |
240 flags = VK_ACCESS_SHADER_READ_BIT; | 240 flags = VK_ACCESS_SHADER_READ_BIT; |
241 } | 241 } |
242 return flags; | 242 return flags; |
243 } | 243 } |
244 | 244 |
245 GrVkSubHeap::GrVkSubHeap(const GrVkGpu* gpu, uint32_t memoryTypeIndex, | 245 bool GrVkFreeListAlloc::alloc(VkDeviceSize requestedSize, |
246 VkDeviceSize size, VkDeviceSize alignment) | 246 VkDeviceSize* allocOffset, VkDeviceSize* allocSize
) { |
247 : fGpu(gpu) | 247 VkDeviceSize alignedSize = align_size(requestedSize, fAlignment); |
248 , fMemoryTypeIndex(memoryTypeIndex) { | |
249 | |
250 VkMemoryAllocateInfo allocInfo = { | |
251 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // sType | |
252 NULL, // pNext | |
253 size, // allocationSize | |
254 memoryTypeIndex, // memoryTypeIndex | |
255 }; | |
256 | |
257 VkResult err = GR_VK_CALL(gpu->vkInterface(), AllocateMemory(gpu->device(), | |
258 &allocInfo, | |
259 nullptr, | |
260 &fAlloc)); | |
261 | |
262 if (VK_SUCCESS == err) { | |
263 fSize = size; | |
264 fAlignment = alignment; | |
265 fFreeSize = size; | |
266 fLargestBlockSize = size; | |
267 fLargestBlockOffset = 0; | |
268 | |
269 Block* block = fFreeList.addToTail(); | |
270 block->fOffset = 0; | |
271 block->fSize = fSize; | |
272 } else { | |
273 fSize = 0; | |
274 fAlignment = 0; | |
275 fFreeSize = 0; | |
276 fLargestBlockSize = 0; | |
277 } | |
278 } | |
279 | |
280 GrVkSubHeap::~GrVkSubHeap() { | |
281 const GrVkInterface* iface = fGpu->vkInterface(); | |
282 GR_VK_CALL(iface, FreeMemory(fGpu->device(), fAlloc, nullptr)); | |
283 | |
284 fFreeList.reset(); | |
285 } | |
286 | |
287 bool GrVkSubHeap::alloc(VkDeviceSize size, GrVkAlloc* alloc) { | |
288 VkDeviceSize alignedSize = align_size(size, fAlignment); | |
289 | 248 |
290 // find the smallest block big enough for our allocation | 249 // find the smallest block big enough for our allocation |
291 FreeList::Iter iter = fFreeList.headIter(); | 250 FreeList::Iter iter = fFreeList.headIter(); |
292 FreeList::Iter bestFitIter; | 251 FreeList::Iter bestFitIter; |
293 VkDeviceSize bestFitSize = fSize + 1; | 252 VkDeviceSize bestFitSize = fSize + 1; |
294 VkDeviceSize secondLargestSize = 0; | 253 VkDeviceSize secondLargestSize = 0; |
295 VkDeviceSize secondLargestOffset = 0; | 254 VkDeviceSize secondLargestOffset = 0; |
296 while (iter.get()) { | 255 while (iter.get()) { |
297 Block* block = iter.get(); | 256 Block* block = iter.get(); |
298 // need to adjust size to match desired alignment | 257 // need to adjust size to match desired alignment |
299 SkASSERT(align_size(block->fOffset, fAlignment) - block->fOffset == 0); | 258 SkASSERT(align_size(block->fOffset, fAlignment) - block->fOffset == 0); |
300 if (block->fSize >= alignedSize && block->fSize < bestFitSize) { | 259 if (block->fSize >= alignedSize && block->fSize < bestFitSize) { |
301 bestFitIter = iter; | 260 bestFitIter = iter; |
302 bestFitSize = block->fSize; | 261 bestFitSize = block->fSize; |
303 } | 262 } |
304 if (secondLargestSize < block->fSize && block->fOffset != fLargestBlockO
ffset) { | 263 if (secondLargestSize < block->fSize && block->fOffset != fLargestBlockO
ffset) { |
305 secondLargestSize = block->fSize; | 264 secondLargestSize = block->fSize; |
306 secondLargestOffset = block->fOffset; | 265 secondLargestOffset = block->fOffset; |
307 } | 266 } |
308 iter.next(); | 267 iter.next(); |
309 } | 268 } |
310 SkASSERT(secondLargestSize <= fLargestBlockSize); | 269 SkASSERT(secondLargestSize <= fLargestBlockSize); |
311 | 270 |
312 Block* bestFit = bestFitIter.get(); | 271 Block* bestFit = bestFitIter.get(); |
313 if (bestFit) { | 272 if (bestFit) { |
314 alloc->fMemory = fAlloc; | |
315 SkASSERT(align_size(bestFit->fOffset, fAlignment) == bestFit->fOffset); | 273 SkASSERT(align_size(bestFit->fOffset, fAlignment) == bestFit->fOffset); |
316 alloc->fOffset = bestFit->fOffset; | 274 *allocOffset = bestFit->fOffset; |
317 alloc->fSize = alignedSize; | 275 *allocSize = alignedSize; |
318 // adjust or remove current block | 276 // adjust or remove current block |
319 VkDeviceSize originalBestFitOffset = bestFit->fOffset; | 277 VkDeviceSize originalBestFitOffset = bestFit->fOffset; |
320 if (bestFit->fSize > alignedSize) { | 278 if (bestFit->fSize > alignedSize) { |
321 bestFit->fOffset += alignedSize; | 279 bestFit->fOffset += alignedSize; |
322 bestFit->fSize -= alignedSize; | 280 bestFit->fSize -= alignedSize; |
323 if (fLargestBlockOffset == originalBestFitOffset) { | 281 if (fLargestBlockOffset == originalBestFitOffset) { |
324 if (bestFit->fSize >= secondLargestSize) { | 282 if (bestFit->fSize >= secondLargestSize) { |
325 fLargestBlockSize = bestFit->fSize; | 283 fLargestBlockSize = bestFit->fSize; |
326 fLargestBlockOffset = bestFit->fOffset; | 284 fLargestBlockOffset = bestFit->fOffset; |
327 } else { | 285 } else { |
(...skipping 27 matching lines...) Expand all Loading... |
355 Block* block = iter.get(); | 313 Block* block = iter.get(); |
356 if (largestSize < block->fSize) { | 314 if (largestSize < block->fSize) { |
357 largestSize = block->fSize; | 315 largestSize = block->fSize; |
358 } | 316 } |
359 iter.next(); | 317 iter.next(); |
360 } | 318 } |
361 SkASSERT(largestSize == fLargestBlockSize); | 319 SkASSERT(largestSize == fLargestBlockSize); |
362 #endif | 320 #endif |
363 } | 321 } |
364 fFreeSize -= alignedSize; | 322 fFreeSize -= alignedSize; |
365 SkASSERT(alloc->fSize > 0); | 323 SkASSERT(allocSize > 0); |
366 | 324 |
367 return true; | 325 return true; |
368 } | 326 } |
369 | 327 |
370 SkDebugf("Can't allocate %d bytes, %d bytes available, largest free block %d
\n", alignedSize, fFreeSize, fLargestBlockSize); | 328 SkDebugf("Can't allocate %d bytes, %d bytes available, largest free block %d
\n", alignedSize, fFreeSize, fLargestBlockSize); |
371 | 329 |
372 return false; | 330 return false; |
373 } | 331 } |
374 | 332 |
375 | 333 void GrVkFreeListAlloc::free(VkDeviceSize allocOffset, VkDeviceSize allocSize) { |
376 void GrVkSubHeap::free(const GrVkAlloc& alloc) { | |
377 SkASSERT(alloc.fMemory == fAlloc); | |
378 | |
379 // find the block right after this allocation | 334 // find the block right after this allocation |
380 FreeList::Iter iter = fFreeList.headIter(); | 335 FreeList::Iter iter = fFreeList.headIter(); |
381 FreeList::Iter prev; | 336 FreeList::Iter prev; |
382 while (iter.get() && iter.get()->fOffset < alloc.fOffset) { | 337 while (iter.get() && iter.get()->fOffset < allocOffset) { |
383 prev = iter; | 338 prev = iter; |
384 iter.next(); | 339 iter.next(); |
385 } | 340 } |
386 // we have four cases: | 341 // we have four cases: |
387 // we exactly follow the previous one | 342 // we exactly follow the previous one |
388 Block* block; | 343 Block* block; |
389 if (prev.get() && prev.get()->fOffset + prev.get()->fSize == alloc.fOffset)
{ | 344 if (prev.get() && prev.get()->fOffset + prev.get()->fSize == allocOffset) { |
390 block = prev.get(); | 345 block = prev.get(); |
391 block->fSize += alloc.fSize; | 346 block->fSize += allocSize; |
392 if (block->fOffset == fLargestBlockOffset) { | 347 if (block->fOffset == fLargestBlockOffset) { |
393 fLargestBlockSize = block->fSize; | 348 fLargestBlockSize = block->fSize; |
394 } | 349 } |
395 // and additionally we may exactly precede the next one | 350 // and additionally we may exactly precede the next one |
396 if (iter.get() && iter.get()->fOffset == alloc.fOffset + alloc.fSize) { | 351 if (iter.get() && iter.get()->fOffset == allocOffset + allocSize) { |
397 block->fSize += iter.get()->fSize; | 352 block->fSize += iter.get()->fSize; |
398 if (iter.get()->fOffset == fLargestBlockOffset) { | 353 if (iter.get()->fOffset == fLargestBlockOffset) { |
399 fLargestBlockOffset = block->fOffset; | 354 fLargestBlockOffset = block->fOffset; |
400 fLargestBlockSize = block->fSize; | 355 fLargestBlockSize = block->fSize; |
401 } | 356 } |
402 fFreeList.remove(iter.get()); | 357 fFreeList.remove(iter.get()); |
403 } | 358 } |
404 // or we only exactly proceed the next one | 359 // or we only exactly proceed the next one |
405 } else if (iter.get() && iter.get()->fOffset == alloc.fOffset + alloc.fSize)
{ | 360 } else if (iter.get() && iter.get()->fOffset == allocOffset + allocSize) { |
406 block = iter.get(); | 361 block = iter.get(); |
407 block->fSize += alloc.fSize; | 362 block->fSize += allocSize; |
408 if (block->fOffset == fLargestBlockOffset) { | 363 if (block->fOffset == fLargestBlockOffset) { |
409 fLargestBlockOffset = alloc.fOffset; | 364 fLargestBlockOffset = allocOffset; |
410 fLargestBlockSize = block->fSize; | 365 fLargestBlockSize = block->fSize; |
411 } | 366 } |
412 block->fOffset = alloc.fOffset; | 367 block->fOffset = allocOffset; |
413 // or we fall somewhere in between, with gaps | 368 // or we fall somewhere in between, with gaps |
414 } else { | 369 } else { |
415 block = fFreeList.addBefore(iter); | 370 block = fFreeList.addBefore(iter); |
416 block->fOffset = alloc.fOffset; | 371 block->fOffset = allocOffset; |
417 block->fSize = alloc.fSize; | 372 block->fSize = allocSize; |
418 } | 373 } |
419 fFreeSize += alloc.fSize; | 374 fFreeSize += allocSize; |
420 if (block->fSize > fLargestBlockSize) { | 375 if (block->fSize > fLargestBlockSize) { |
421 fLargestBlockSize = block->fSize; | 376 fLargestBlockSize = block->fSize; |
422 fLargestBlockOffset = block->fOffset; | 377 fLargestBlockOffset = block->fOffset; |
423 } | 378 } |
424 | 379 |
425 #ifdef SK_DEBUG | 380 #ifdef SK_DEBUG |
426 VkDeviceSize largestSize = 0; | 381 VkDeviceSize largestSize = 0; |
427 iter = fFreeList.headIter(); | 382 iter = fFreeList.headIter(); |
428 while (iter.get()) { | 383 while (iter.get()) { |
429 Block* block = iter.get(); | 384 Block* block = iter.get(); |
430 if (largestSize < block->fSize) { | 385 if (largestSize < block->fSize) { |
431 largestSize = block->fSize; | 386 largestSize = block->fSize; |
432 } | 387 } |
433 iter.next(); | 388 iter.next(); |
434 } | 389 } |
435 SkASSERT(fLargestBlockSize == largestSize); | 390 SkASSERT(fLargestBlockSize == largestSize); |
436 #endif | 391 #endif |
437 } | 392 } |
438 | 393 |
439 GrVkHeap::~GrVkHeap() { | 394 GrVkSubHeap::GrVkSubHeap(const GrVkGpu* gpu, uint32_t memoryTypeIndex, |
| 395 VkDeviceSize size, VkDeviceSize alignment) |
| 396 : INHERITED(size, alignment) |
| 397 , fGpu(gpu) |
| 398 , fMemoryTypeIndex(memoryTypeIndex) { |
| 399 |
| 400 VkMemoryAllocateInfo allocInfo = { |
| 401 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // sType |
| 402 NULL, // pNext |
| 403 size, // allocationSize |
| 404 memoryTypeIndex, // memoryTypeIndex |
| 405 }; |
| 406 |
| 407 VkResult err = GR_VK_CALL(gpu->vkInterface(), AllocateMemory(gpu->device(), |
| 408 &allocInfo, |
| 409 nullptr, |
| 410 &fAlloc)); |
| 411 if (VK_SUCCESS != err) { |
| 412 this->reset(); |
| 413 } |
| 414 } |
| 415 |
| 416 GrVkSubHeap::~GrVkSubHeap() { |
| 417 const GrVkInterface* iface = fGpu->vkInterface(); |
| 418 GR_VK_CALL(iface, FreeMemory(fGpu->device(), fAlloc, nullptr)); |
| 419 } |
| 420 |
| 421 bool GrVkSubHeap::alloc(VkDeviceSize size, GrVkAlloc* alloc) { |
| 422 alloc->fMemory = fAlloc; |
| 423 return INHERITED::alloc(size, &alloc->fOffset, &alloc->fSize); |
| 424 } |
| 425 |
| 426 void GrVkSubHeap::free(const GrVkAlloc& alloc) { |
| 427 SkASSERT(alloc.fMemory == fAlloc); |
| 428 |
| 429 INHERITED::free(alloc.fOffset, alloc.fSize); |
440 } | 430 } |
441 | 431 |
442 bool GrVkHeap::subAlloc(VkDeviceSize size, VkDeviceSize alignment, | 432 bool GrVkHeap::subAlloc(VkDeviceSize size, VkDeviceSize alignment, |
443 uint32_t memoryTypeIndex, GrVkAlloc* alloc) { | 433 uint32_t memoryTypeIndex, GrVkAlloc* alloc) { |
444 VkDeviceSize alignedSize = align_size(size, alignment); | 434 VkDeviceSize alignedSize = align_size(size, alignment); |
445 | 435 |
446 // if requested is larger than our subheap allocation, just alloc directly | 436 // if requested is larger than our subheap allocation, just alloc directly |
447 if (alignedSize > fSubHeapSize) { | 437 if (alignedSize > fSubHeapSize) { |
448 VkMemoryAllocateInfo allocInfo = { | 438 VkMemoryAllocateInfo allocInfo = { |
449 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // sType | 439 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // sType |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
558 fSubHeaps[i]->free(alloc); | 548 fSubHeaps[i]->free(alloc); |
559 fUsedSize -= alloc.fSize; | 549 fUsedSize -= alloc.fSize; |
560 return true; | 550 return true; |
561 } | 551 } |
562 } | 552 } |
563 | 553 |
564 return false; | 554 return false; |
565 } | 555 } |
566 | 556 |
567 | 557 |
OLD | NEW |