Check for some potential subheap allocation failures.

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
This commit is contained in:
jvanverth 2016-06-16 14:05:09 -07:00 committed by Commit bot
parent b6095ae05b
commit 6dc3af4499
3 changed files with 45 additions and 1 deletions

View 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);

View 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);

View File

@ -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) {