| 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 |