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

Side by Side Diff: src/gpu/vk/GrVkMemory.cpp

Issue 2356343003: Some Vulkan memory fixes and cleanup (Closed)
Patch Set: Created 4 years, 2 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
« no previous file with comments | « src/gpu/vk/GrVkMemory.h ('k') | tests/VkHeapTests.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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"
11 #include "GrVkUtil.h" 11 #include "GrVkUtil.h"
12 12
13 #ifdef SK_DEBUG
14 // for simple tracking of how much we're using in each heap
15 // last counter is for non-subheap allocations
16 VkDeviceSize gHeapUsage[VK_MAX_MEMORY_HEAPS+1] = { 0 };
17 #endif
18
13 static bool get_valid_memory_type_index(const VkPhysicalDeviceMemoryProperties& physDevMemProps, 19 static bool get_valid_memory_type_index(const VkPhysicalDeviceMemoryProperties& physDevMemProps,
14 uint32_t typeBits, 20 uint32_t typeBits,
15 VkMemoryPropertyFlags requestedMemFlags, 21 VkMemoryPropertyFlags requestedMemFlags,
16 uint32_t* typeIndex) { 22 uint32_t* typeIndex) {
17 for (uint32_t i = 0; i < physDevMemProps.memoryTypeCount; ++i) { 23 for (uint32_t i = 0; i < physDevMemProps.memoryTypeCount; ++i) {
18 if (typeBits & (1 << i)) { 24 if (typeBits & (1 << i)) {
19 uint32_t supportedFlags = physDevMemProps.memoryTypes[i].propertyFla gs & 25 uint32_t supportedFlags = physDevMemProps.memoryTypes[i].propertyFla gs &
20 requestedMemFlags; 26 requestedMemFlags;
21 if (supportedFlags == requestedMemFlags) { 27 if (supportedFlags == requestedMemFlags) {
22 *typeIndex = i; 28 *typeIndex = i;
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
75 alloc->fFlags = mpf & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT ? 0x0 81 alloc->fFlags = mpf & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT ? 0x0
76 : GrVkAlloc:: kNoncoherent_Flag; 82 : GrVkAlloc:: kNoncoherent_Flag;
77 } else { 83 } else {
78 // device-local memory should always be available for static buffers 84 // device-local memory should always be available for static buffers
79 SkASSERT_RELEASE(get_valid_memory_type_index(phDevMemProps, 85 SkASSERT_RELEASE(get_valid_memory_type_index(phDevMemProps,
80 memReqs.memoryTypeBits, 86 memReqs.memoryTypeBits,
81 VK_MEMORY_PROPERTY_DEVICE_L OCAL_BIT, 87 VK_MEMORY_PROPERTY_DEVICE_L OCAL_BIT,
82 &typeIndex)); 88 &typeIndex));
83 alloc->fFlags = 0x0; 89 alloc->fFlags = 0x0;
84 } 90 }
91 uint32_t heapIndex = phDevMemProps.memoryTypes[typeIndex].heapIndex;
85 92
86 GrVkHeap* heap = gpu->getHeap(buffer_type_to_heap(type)); 93 GrVkHeap* heap = gpu->getHeap(buffer_type_to_heap(type));
87 94
88 if (!heap->alloc(memReqs.size, memReqs.alignment, typeIndex, alloc)) { 95 if (!heap->alloc(memReqs.size, memReqs.alignment, typeIndex, heapIndex, allo c)) {
89 SkDebugf("Failed to alloc buffer\n"); 96 // if static, try to allocate from non-host-visible non-device-local mem ory instead
90 return false; 97 if (dynamic ||
98 !get_valid_memory_type_index(phDevMemProps, memReqs.memoryTypeBits, 0, &typeIndex) ||
99 !heap->alloc(memReqs.size, memReqs.alignment, typeIndex, heapIndex, alloc)) {
egdaniel 2016/09/22 13:25:46 do we need to update heap index between these?
jvanverth1 2016/09/22 14:14:51 Done.
100 SkDebugf("Failed to alloc buffer\n");
101 return false;
102 }
91 } 103 }
92 104
93 // Bind buffer 105 // Bind buffer
94 VkResult err = GR_VK_CALL(iface, BindBufferMemory(device, buffer, 106 VkResult err = GR_VK_CALL(iface, BindBufferMemory(device, buffer,
95 alloc->fMemory, alloc->fOf fset)); 107 alloc->fMemory, alloc->fOf fset));
96 if (err) { 108 if (err) {
97 SkASSERT_RELEASE(heap->free(*alloc)); 109 SkASSERT_RELEASE(heap->free(*alloc));
98 return false; 110 return false;
99 } 111 }
100 112
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
156 VK_MEMORY_PROPERTY_DEVICE_L OCAL_BIT, 168 VK_MEMORY_PROPERTY_DEVICE_L OCAL_BIT,
157 &typeIndex)); 169 &typeIndex));
158 if (memReqs.size <= kMaxSmallImageSize) { 170 if (memReqs.size <= kMaxSmallImageSize) {
159 heap = gpu->getHeap(GrVkGpu::kSmallOptimalImage_Heap); 171 heap = gpu->getHeap(GrVkGpu::kSmallOptimalImage_Heap);
160 } else { 172 } else {
161 heap = gpu->getHeap(GrVkGpu::kOptimalImage_Heap); 173 heap = gpu->getHeap(GrVkGpu::kOptimalImage_Heap);
162 } 174 }
163 alloc->fFlags = 0x0; 175 alloc->fFlags = 0x0;
164 } 176 }
165 177
166 if (!heap->alloc(memReqs.size, memReqs.alignment, typeIndex, alloc)) { 178 uint32_t heapIndex = phDevMemProps.memoryTypes[typeIndex].heapIndex;
167 SkDebugf("Failed to alloc image\n"); 179 if (!heap->alloc(memReqs.size, memReqs.alignment, typeIndex, heapIndex, allo c)) {
168 return false; 180 // if optimal, try to allocate from non-host-visible non-device-local me mory instead
181 if (linearTiling ||
182 !get_valid_memory_type_index(phDevMemProps, memReqs.memoryTypeBits, 0, &typeIndex) ||
183 !heap->alloc(memReqs.size, memReqs.alignment, typeIndex, heapIndex, alloc)) {
184 SkDebugf("Failed to alloc image\n");
185 return false;
186 }
169 } 187 }
170 188
171 // Bind image 189 // Bind image
172 VkResult err = GR_VK_CALL(iface, BindImageMemory(device, image, 190 VkResult err = GR_VK_CALL(iface, BindImageMemory(device, image,
173 alloc->fMemory, alloc->fOffset)); 191 alloc->fMemory, alloc->fOffset));
174 if (err) { 192 if (err) {
175 SkASSERT_RELEASE(heap->free(*alloc)); 193 SkASSERT_RELEASE(heap->free(*alloc));
176 return false; 194 return false;
177 } 195 }
178 196
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after
424 Block* block = iter.get(); 442 Block* block = iter.get();
425 if (largestSize < block->fSize) { 443 if (largestSize < block->fSize) {
426 largestSize = block->fSize; 444 largestSize = block->fSize;
427 } 445 }
428 iter.next(); 446 iter.next();
429 } 447 }
430 SkASSERT(fLargestBlockSize == largestSize); 448 SkASSERT(fLargestBlockSize == largestSize);
431 #endif 449 #endif
432 } 450 }
433 451
434 GrVkSubHeap::GrVkSubHeap(const GrVkGpu* gpu, uint32_t memoryTypeIndex, 452 GrVkSubHeap::GrVkSubHeap(const GrVkGpu* gpu, uint32_t memoryTypeIndex, uint32_t heapIndex,
435 VkDeviceSize size, VkDeviceSize alignment) 453 VkDeviceSize size, VkDeviceSize alignment)
436 : INHERITED(size, alignment) 454 : INHERITED(size, alignment)
437 , fGpu(gpu) 455 , fGpu(gpu)
438 , fMemoryTypeIndex(memoryTypeIndex) { 456 , fMemoryTypeIndex(memoryTypeIndex)
457 , fHeapIndex(heapIndex) {
439 458
440 VkMemoryAllocateInfo allocInfo = { 459 VkMemoryAllocateInfo allocInfo = {
441 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // sType 460 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // sType
442 NULL, // pNext 461 NULL, // pNext
443 size, // allocationSize 462 size, // allocationSize
444 memoryTypeIndex, // memoryTypeIndex 463 memoryTypeIndex, // memoryTypeIndex
445 }; 464 };
446 465
447 VkResult err = GR_VK_CALL(gpu->vkInterface(), AllocateMemory(gpu->device(), 466 VkResult err = GR_VK_CALL(gpu->vkInterface(), AllocateMemory(gpu->device(),
448 &allocInfo, 467 &allocInfo,
449 nullptr, 468 nullptr,
450 &fAlloc)); 469 &fAlloc));
451 if (VK_SUCCESS != err) { 470 if (VK_SUCCESS != err) {
452 this->reset(); 471 this->reset();
472 }
473 #ifdef SK_DEBUG
474 else {
475 gHeapUsage[heapIndex] += size;
453 } 476 }
477 #endif
454 } 478 }
455 479
456 GrVkSubHeap::~GrVkSubHeap() { 480 GrVkSubHeap::~GrVkSubHeap() {
457 const GrVkInterface* iface = fGpu->vkInterface(); 481 const GrVkInterface* iface = fGpu->vkInterface();
458 GR_VK_CALL(iface, FreeMemory(fGpu->device(), fAlloc, nullptr)); 482 GR_VK_CALL(iface, FreeMemory(fGpu->device(), fAlloc, nullptr));
483 #ifdef SK_DEBUG
484 gHeapUsage[fHeapIndex] -= fSize;
485 #endif
459 } 486 }
460 487
461 bool GrVkSubHeap::alloc(VkDeviceSize size, GrVkAlloc* alloc) { 488 bool GrVkSubHeap::alloc(VkDeviceSize size, GrVkAlloc* alloc) {
462 alloc->fMemory = fAlloc; 489 alloc->fMemory = fAlloc;
463 return INHERITED::alloc(size, &alloc->fOffset, &alloc->fSize); 490 return INHERITED::alloc(size, &alloc->fOffset, &alloc->fSize);
464 } 491 }
465 492
466 void GrVkSubHeap::free(const GrVkAlloc& alloc) { 493 void GrVkSubHeap::free(const GrVkAlloc& alloc) {
467 SkASSERT(alloc.fMemory == fAlloc); 494 SkASSERT(alloc.fMemory == fAlloc);
468 495
469 INHERITED::free(alloc.fOffset, alloc.fSize); 496 INHERITED::free(alloc.fOffset, alloc.fSize);
470 } 497 }
471 498
472 bool GrVkHeap::subAlloc(VkDeviceSize size, VkDeviceSize alignment, 499 bool GrVkHeap::subAlloc(VkDeviceSize size, VkDeviceSize alignment,
473 uint32_t memoryTypeIndex, GrVkAlloc* alloc) { 500 uint32_t memoryTypeIndex, uint32_t heapIndex, GrVkAlloc* alloc) {
474 VkDeviceSize alignedSize = align_size(size, alignment); 501 VkDeviceSize alignedSize = align_size(size, alignment);
475 502
476 // if requested is larger than our subheap allocation, just alloc directly 503 // if requested is larger than our subheap allocation, just alloc directly
477 if (alignedSize > fSubHeapSize) { 504 if (alignedSize > fSubHeapSize) {
478 VkMemoryAllocateInfo allocInfo = { 505 VkMemoryAllocateInfo allocInfo = {
479 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // sType 506 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // sType
480 NULL, // pNext 507 NULL, // pNext
481 size, // allocationSize 508 size, // allocationSize
482 memoryTypeIndex, // memoryTypeIndex 509 memoryTypeIndex, // memoryTypeIndex
483 }; 510 };
484 511
485 VkResult err = GR_VK_CALL(fGpu->vkInterface(), AllocateMemory(fGpu->devi ce(), 512 VkResult err = GR_VK_CALL(fGpu->vkInterface(), AllocateMemory(fGpu->devi ce(),
486 &allocInfo , 513 &allocInfo ,
487 nullptr, 514 nullptr,
488 &alloc->fM emory)); 515 &alloc->fM emory));
489 if (VK_SUCCESS != err) { 516 if (VK_SUCCESS != err) {
490 return false; 517 return false;
491 } 518 }
492 alloc->fOffset = 0; 519 alloc->fOffset = 0;
493 alloc->fSize = 0; // hint that this is not a subheap allocation 520 alloc->fSize = 0; // hint that this is not a subheap allocation
521 #ifdef SK_DEBUG
522 gHeapUsage[VK_MAX_MEMORY_HEAPS] += alignedSize;
523 #endif
494 524
495 return true; 525 return true;
496 } 526 }
497 527
498 // first try to find a subheap that fits our allocation request 528 // first try to find a subheap that fits our allocation request
499 int bestFitIndex = -1; 529 int bestFitIndex = -1;
500 VkDeviceSize bestFitSize = 0x7FFFFFFF; 530 VkDeviceSize bestFitSize = 0x7FFFFFFF;
501 for (auto i = 0; i < fSubHeaps.count(); ++i) { 531 for (auto i = 0; i < fSubHeaps.count(); ++i) {
502 if (fSubHeaps[i]->memoryTypeIndex() == memoryTypeIndex && 532 if (fSubHeaps[i]->memoryTypeIndex() == memoryTypeIndex &&
503 fSubHeaps[i]->alignment() == alignment) { 533 fSubHeaps[i]->alignment() == alignment) {
504 VkDeviceSize heapSize = fSubHeaps[i]->largestBlockSize(); 534 VkDeviceSize heapSize = fSubHeaps[i]->largestBlockSize();
505 if (heapSize >= alignedSize && heapSize < bestFitSize) { 535 if (heapSize >= alignedSize && heapSize < bestFitSize) {
506 bestFitIndex = i; 536 bestFitIndex = i;
507 bestFitSize = heapSize; 537 bestFitSize = heapSize;
508 } 538 }
509 } 539 }
510 } 540 }
511 541
512 if (bestFitIndex >= 0) { 542 if (bestFitIndex >= 0) {
513 SkASSERT(fSubHeaps[bestFitIndex]->alignment() == alignment); 543 SkASSERT(fSubHeaps[bestFitIndex]->alignment() == alignment);
514 if (fSubHeaps[bestFitIndex]->alloc(size, alloc)) { 544 if (fSubHeaps[bestFitIndex]->alloc(size, alloc)) {
515 fUsedSize += alloc->fSize; 545 fUsedSize += alloc->fSize;
516 return true; 546 return true;
517 } 547 }
518 return false; 548 return false;
519 } 549 }
520 550
521 // need to allocate a new subheap 551 // need to allocate a new subheap
522 SkAutoTDelete<GrVkSubHeap>& subHeap = fSubHeaps.push_back(); 552 SkAutoTDelete<GrVkSubHeap>& subHeap = fSubHeaps.push_back();
523 subHeap.reset(new GrVkSubHeap(fGpu, memoryTypeIndex, fSubHeapSize, alignment )); 553 subHeap.reset(new GrVkSubHeap(fGpu, memoryTypeIndex, heapIndex, fSubHeapSize , alignment));
524 // try to recover from failed allocation by only allocating what we need 554 // try to recover from failed allocation by only allocating what we need
525 if (subHeap->size() == 0) { 555 if (subHeap->size() == 0) {
526 VkDeviceSize alignedSize = align_size(size, alignment); 556 VkDeviceSize alignedSize = align_size(size, alignment);
527 subHeap.reset(new GrVkSubHeap(fGpu, memoryTypeIndex, alignedSize, alignm ent)); 557 subHeap.reset(new GrVkSubHeap(fGpu, memoryTypeIndex, heapIndex, alignedS ize, alignment));
528 if (subHeap->size() == 0) { 558 if (subHeap->size() == 0) {
529 return false; 559 return false;
530 } 560 }
531 } 561 }
532 fAllocSize += fSubHeapSize; 562 fAllocSize += fSubHeapSize;
533 if (subHeap->alloc(size, alloc)) { 563 if (subHeap->alloc(size, alloc)) {
534 fUsedSize += alloc->fSize; 564 fUsedSize += alloc->fSize;
535 return true; 565 return true;
536 } 566 }
537 567
538 return false; 568 return false;
539 } 569 }
540 570
541 bool GrVkHeap::singleAlloc(VkDeviceSize size, VkDeviceSize alignment, 571 bool GrVkHeap::singleAlloc(VkDeviceSize size, VkDeviceSize alignment,
542 uint32_t memoryTypeIndex, GrVkAlloc* alloc) { 572 uint32_t memoryTypeIndex, uint32_t heapIndex, GrVkAll oc* alloc) {
543 VkDeviceSize alignedSize = align_size(size, alignment); 573 VkDeviceSize alignedSize = align_size(size, alignment);
544 574
545 // first try to find an unallocated subheap that fits our allocation request 575 // first try to find an unallocated subheap that fits our allocation request
546 int bestFitIndex = -1; 576 int bestFitIndex = -1;
547 VkDeviceSize bestFitSize = 0x7FFFFFFF; 577 VkDeviceSize bestFitSize = 0x7FFFFFFF;
548 for (auto i = 0; i < fSubHeaps.count(); ++i) { 578 for (auto i = 0; i < fSubHeaps.count(); ++i) {
549 if (fSubHeaps[i]->memoryTypeIndex() == memoryTypeIndex && 579 if (fSubHeaps[i]->memoryTypeIndex() == memoryTypeIndex &&
550 fSubHeaps[i]->alignment() == alignment && 580 fSubHeaps[i]->alignment() == alignment &&
551 fSubHeaps[i]->unallocated()) { 581 fSubHeaps[i]->unallocated()) {
552 VkDeviceSize heapSize = fSubHeaps[i]->size(); 582 VkDeviceSize heapSize = fSubHeaps[i]->size();
553 if (heapSize >= alignedSize && heapSize < bestFitSize) { 583 if (heapSize >= alignedSize && heapSize < bestFitSize) {
554 bestFitIndex = i; 584 bestFitIndex = i;
555 bestFitSize = heapSize; 585 bestFitSize = heapSize;
556 } 586 }
557 } 587 }
558 } 588 }
559 589
560 if (bestFitIndex >= 0) { 590 if (bestFitIndex >= 0) {
561 SkASSERT(fSubHeaps[bestFitIndex]->alignment() == alignment); 591 SkASSERT(fSubHeaps[bestFitIndex]->alignment() == alignment);
562 if (fSubHeaps[bestFitIndex]->alloc(size, alloc)) { 592 if (fSubHeaps[bestFitIndex]->alloc(size, alloc)) {
563 fUsedSize += alloc->fSize; 593 fUsedSize += alloc->fSize;
564 return true; 594 return true;
565 } 595 }
566 return false; 596 return false;
567 } 597 }
568 598
569 // need to allocate a new subheap 599 // need to allocate a new subheap
570 SkAutoTDelete<GrVkSubHeap>& subHeap = fSubHeaps.push_back(); 600 SkAutoTDelete<GrVkSubHeap>& subHeap = fSubHeaps.push_back();
571 subHeap.reset(new GrVkSubHeap(fGpu, memoryTypeIndex, alignedSize, alignment) ); 601 subHeap.reset(new GrVkSubHeap(fGpu, memoryTypeIndex, heapIndex, alignedSize, alignment));
572 fAllocSize += alignedSize; 602 fAllocSize += alignedSize;
573 if (subHeap->alloc(size, alloc)) { 603 if (subHeap->alloc(size, alloc)) {
574 fUsedSize += alloc->fSize; 604 fUsedSize += alloc->fSize;
575 return true; 605 return true;
576 } 606 }
577 607
578 return false; 608 return false;
579 } 609 }
580 610
581 bool GrVkHeap::free(const GrVkAlloc& alloc) { 611 bool GrVkHeap::free(const GrVkAlloc& alloc) {
582 // a size of 0 means we're using the system heap 612 // a size of 0 means we're using the system heap
583 if (0 == alloc.fSize) { 613 if (0 == alloc.fSize) {
584 const GrVkInterface* iface = fGpu->vkInterface(); 614 const GrVkInterface* iface = fGpu->vkInterface();
585 GR_VK_CALL(iface, FreeMemory(fGpu->device(), alloc.fMemory, nullptr)); 615 GR_VK_CALL(iface, FreeMemory(fGpu->device(), alloc.fMemory, nullptr));
586 return true; 616 return true;
587 } 617 }
588 618
589 for (auto i = 0; i < fSubHeaps.count(); ++i) { 619 for (auto i = 0; i < fSubHeaps.count(); ++i) {
590 if (fSubHeaps[i]->memory() == alloc.fMemory) { 620 if (fSubHeaps[i]->memory() == alloc.fMemory) {
591 fSubHeaps[i]->free(alloc); 621 fSubHeaps[i]->free(alloc);
592 fUsedSize -= alloc.fSize; 622 fUsedSize -= alloc.fSize;
593 return true; 623 return true;
594 } 624 }
595 } 625 }
596 626
597 return false; 627 return false;
598 } 628 }
599 629
600 630
OLDNEW
« no previous file with comments | « src/gpu/vk/GrVkMemory.h ('k') | tests/VkHeapTests.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698