Check for some potential subheap allocation failures.
authorjvanverth <jvanverth@google.com>
Thu, 16 Jun 2016 21:05:09 +0000 (14:05 -0700)
committerCommit bot <commit-bot@chromium.org>
Thu, 16 Jun 2016 21:05:09 +0000 (14:05 -0700)
Need to make sure we can allocate areas larger than our specified
subheap sizes, and deal with potential fragmentation in the main
system heap.
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2072763002

Review-Url: https://codereview.chromium.org/2072763002

src/gpu/vk/GrVkMemory.cpp
src/gpu/vk/GrVkMemory.h
tests/VkHeapTests.cpp

index 984e3271b0716df82d9c6a22912b9a783af609e4..7ad9b45987f9e5637c909596607237238cbc3dd1 100644 (file)
@@ -360,6 +360,7 @@ bool GrVkSubHeap::alloc(VkDeviceSize size, GrVkAlloc* alloc) {
 #endif
         }
         fFreeSize -= alignedSize;
+        SkASSERT(alloc->fSize > 0);
 
         return true;
     }
@@ -440,6 +441,28 @@ bool GrVkHeap::subAlloc(VkDeviceSize size, VkDeviceSize alignment,
                         uint32_t memoryTypeIndex, GrVkAlloc* alloc) {
     VkDeviceSize alignedSize = align_size(size, alignment);
 
+    // if requested is larger than our subheap allocation, just alloc directly
+    if (alignedSize > fSubHeapSize) {
+        VkMemoryAllocateInfo allocInfo = {
+            VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,      // sType
+            NULL,                                        // pNext
+            size,                                        // allocationSize
+            memoryTypeIndex,                             // memoryTypeIndex
+        };
+
+        VkResult err = GR_VK_CALL(fGpu->vkInterface(), AllocateMemory(fGpu->device(),
+                                                                      &allocInfo,
+                                                                      nullptr,
+                                                                      &alloc->fMemory));
+        if (VK_SUCCESS != err) {
+            return false;
+        }
+        alloc->fOffset = 0;
+        alloc->fSize = 0;    // hint that this is not a subheap allocation
+        
+        return true;
+    }
+
     // first try to find a subheap that fits our allocation request
     int bestFitIndex = -1;
     VkDeviceSize bestFitSize = 0x7FFFFFFF;
@@ -460,11 +483,19 @@ bool GrVkHeap::subAlloc(VkDeviceSize size, VkDeviceSize alignment,
             return true;
         }
         return false;
-    } 
+    }
 
     // need to allocate a new subheap
     SkAutoTDelete<GrVkSubHeap>& subHeap = fSubHeaps.push_back();
     subHeap.reset(new GrVkSubHeap(fGpu, memoryTypeIndex, fSubHeapSize, alignment));
+    // try to recover from failed allocation by only allocating what we need
+    if (subHeap->size() == 0) {
+        VkDeviceSize alignedSize = align_size(size, alignment);
+        subHeap.reset(new GrVkSubHeap(fGpu, memoryTypeIndex, alignedSize, alignment));
+        if (subHeap->size() == 0) {
+            return false;
+        }
+    }
     fAllocSize += fSubHeapSize;
     if (subHeap->alloc(size, alloc)) {
         fUsedSize += alloc->fSize;
@@ -513,6 +544,13 @@ bool GrVkHeap::singleAlloc(VkDeviceSize size, VkDeviceSize alignment,
 }
 
 bool GrVkHeap::free(const GrVkAlloc& alloc) {
+    // a size of 0 means we're using the system heap
+    if (0 == alloc.fSize) {
+        const GrVkInterface* iface = fGpu->vkInterface();
+        GR_VK_CALL(iface, FreeMemory(fGpu->device(), alloc.fMemory, nullptr));
+        return true;
+    }
+
     for (auto i = 0; i < fSubHeaps.count(); ++i) {
         if (fSubHeaps[i]->memory() == alloc.fMemory) {
             fSubHeaps[i]->free(alloc);
index 417fb5a1e050c41e552f164cd58a647f4c3a18c5..44c82867218dc189be44458e47cb7ea0b5dc80f8 100644 (file)
@@ -100,6 +100,7 @@ public:
 
     bool alloc(VkDeviceSize size, VkDeviceSize alignment, uint32_t memoryTypeIndex, 
                GrVkAlloc* alloc) {
+        SkASSERT(size > 0);
         return (*this.*fAllocFunc)(size, alignment, memoryTypeIndex, alloc);
     }
     bool free(const GrVkAlloc& alloc);
index 29990257a95f66b6a729cdfa170b204bc7d5eb3c..c4a9beb5f23d14248e188090fadccf2a23409ae7 100755 (executable)
@@ -155,6 +155,11 @@ void suballoc_test(skiatest::Reporter* reporter, GrContext* context) {
     REPORTER_ASSERT(reporter, heap.allocSize() == 128 * 1024 && heap.usedSize() == 40 * 1024);
     heap.free(alloc3);
     REPORTER_ASSERT(reporter, heap.allocSize() == 128 * 1024 && heap.usedSize() == 0 * 1024);
+    // heap should not grow here (allocating more than subheap size)
+    REPORTER_ASSERT(reporter, heap.alloc(128 * 1024, kAlignment, kHeapIndex, &alloc0));
+    REPORTER_ASSERT(reporter, 0 == alloc0.fSize);
+    REPORTER_ASSERT(reporter, heap.allocSize() == 128 * 1024 && heap.usedSize() == 0 * 1024);
+    heap.free(alloc0);
 }
 
 void singlealloc_test(skiatest::Reporter* reporter, GrContext* context) {