Pull out freelist allocation from GrVkSubHeap

BUG=skia:5031
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128673002

Review-Url: https://codereview.chromium.org/2128673002
This commit is contained in:
jvanverth 2016-07-07 07:16:42 -07:00 committed by Commit bot
parent 552882f768
commit 82356cc41f
2 changed files with 102 additions and 79 deletions

View File

@ -242,50 +242,9 @@ VkAccessFlags GrVkMemory::LayoutToSrcAccessMask(const VkImageLayout layout) {
return flags;
}
GrVkSubHeap::GrVkSubHeap(const GrVkGpu* gpu, uint32_t memoryTypeIndex,
VkDeviceSize size, VkDeviceSize alignment)
: fGpu(gpu)
, fMemoryTypeIndex(memoryTypeIndex) {
VkMemoryAllocateInfo allocInfo = {
VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // sType
NULL, // pNext
size, // allocationSize
memoryTypeIndex, // memoryTypeIndex
};
VkResult err = GR_VK_CALL(gpu->vkInterface(), AllocateMemory(gpu->device(),
&allocInfo,
nullptr,
&fAlloc));
if (VK_SUCCESS == err) {
fSize = size;
fAlignment = alignment;
fFreeSize = size;
fLargestBlockSize = size;
fLargestBlockOffset = 0;
Block* block = fFreeList.addToTail();
block->fOffset = 0;
block->fSize = fSize;
} else {
fSize = 0;
fAlignment = 0;
fFreeSize = 0;
fLargestBlockSize = 0;
}
}
GrVkSubHeap::~GrVkSubHeap() {
const GrVkInterface* iface = fGpu->vkInterface();
GR_VK_CALL(iface, FreeMemory(fGpu->device(), fAlloc, nullptr));
fFreeList.reset();
}
bool GrVkSubHeap::alloc(VkDeviceSize size, GrVkAlloc* alloc) {
VkDeviceSize alignedSize = align_size(size, fAlignment);
bool GrVkFreeListAlloc::alloc(VkDeviceSize requestedSize,
VkDeviceSize* allocOffset, VkDeviceSize* allocSize) {
VkDeviceSize alignedSize = align_size(requestedSize, fAlignment);
// find the smallest block big enough for our allocation
FreeList::Iter iter = fFreeList.headIter();
@ -311,10 +270,9 @@ bool GrVkSubHeap::alloc(VkDeviceSize size, GrVkAlloc* alloc) {
Block* bestFit = bestFitIter.get();
if (bestFit) {
alloc->fMemory = fAlloc;
SkASSERT(align_size(bestFit->fOffset, fAlignment) == bestFit->fOffset);
alloc->fOffset = bestFit->fOffset;
alloc->fSize = alignedSize;
*allocOffset = bestFit->fOffset;
*allocSize = alignedSize;
// adjust or remove current block
VkDeviceSize originalBestFitOffset = bestFit->fOffset;
if (bestFit->fSize > alignedSize) {
@ -362,38 +320,35 @@ bool GrVkSubHeap::alloc(VkDeviceSize size, GrVkAlloc* alloc) {
#endif
}
fFreeSize -= alignedSize;
SkASSERT(alloc->fSize > 0);
SkASSERT(allocSize > 0);
return true;
}
SkDebugf("Can't allocate %d bytes, %d bytes available, largest free block %d\n", alignedSize, fFreeSize, fLargestBlockSize);
return false;
}
void GrVkSubHeap::free(const GrVkAlloc& alloc) {
SkASSERT(alloc.fMemory == fAlloc);
void GrVkFreeListAlloc::free(VkDeviceSize allocOffset, VkDeviceSize allocSize) {
// find the block right after this allocation
FreeList::Iter iter = fFreeList.headIter();
FreeList::Iter prev;
while (iter.get() && iter.get()->fOffset < alloc.fOffset) {
while (iter.get() && iter.get()->fOffset < allocOffset) {
prev = iter;
iter.next();
}
}
// we have four cases:
// we exactly follow the previous one
Block* block;
if (prev.get() && prev.get()->fOffset + prev.get()->fSize == alloc.fOffset) {
if (prev.get() && prev.get()->fOffset + prev.get()->fSize == allocOffset) {
block = prev.get();
block->fSize += alloc.fSize;
block->fSize += allocSize;
if (block->fOffset == fLargestBlockOffset) {
fLargestBlockSize = block->fSize;
}
// and additionally we may exactly precede the next one
if (iter.get() && iter.get()->fOffset == alloc.fOffset + alloc.fSize) {
if (iter.get() && iter.get()->fOffset == allocOffset + allocSize) {
block->fSize += iter.get()->fSize;
if (iter.get()->fOffset == fLargestBlockOffset) {
fLargestBlockOffset = block->fOffset;
@ -402,21 +357,21 @@ void GrVkSubHeap::free(const GrVkAlloc& alloc) {
fFreeList.remove(iter.get());
}
// or we only exactly proceed the next one
} else if (iter.get() && iter.get()->fOffset == alloc.fOffset + alloc.fSize) {
} else if (iter.get() && iter.get()->fOffset == allocOffset + allocSize) {
block = iter.get();
block->fSize += alloc.fSize;
block->fSize += allocSize;
if (block->fOffset == fLargestBlockOffset) {
fLargestBlockOffset = alloc.fOffset;
fLargestBlockOffset = allocOffset;
fLargestBlockSize = block->fSize;
}
block->fOffset = alloc.fOffset;
block->fOffset = allocOffset;
// or we fall somewhere in between, with gaps
} else {
block = fFreeList.addBefore(iter);
block->fOffset = alloc.fOffset;
block->fSize = alloc.fSize;
block->fOffset = allocOffset;
block->fSize = allocSize;
}
fFreeSize += alloc.fSize;
fFreeSize += allocSize;
if (block->fSize > fLargestBlockSize) {
fLargestBlockSize = block->fSize;
fLargestBlockOffset = block->fOffset;
@ -436,7 +391,42 @@ void GrVkSubHeap::free(const GrVkAlloc& alloc) {
#endif
}
GrVkHeap::~GrVkHeap() {
GrVkSubHeap::GrVkSubHeap(const GrVkGpu* gpu, uint32_t memoryTypeIndex,
VkDeviceSize size, VkDeviceSize alignment)
: INHERITED(size, alignment)
, fGpu(gpu)
, fMemoryTypeIndex(memoryTypeIndex) {
VkMemoryAllocateInfo allocInfo = {
VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // sType
NULL, // pNext
size, // allocationSize
memoryTypeIndex, // memoryTypeIndex
};
VkResult err = GR_VK_CALL(gpu->vkInterface(), AllocateMemory(gpu->device(),
&allocInfo,
nullptr,
&fAlloc));
if (VK_SUCCESS != err) {
this->reset();
}
}
GrVkSubHeap::~GrVkSubHeap() {
const GrVkInterface* iface = fGpu->vkInterface();
GR_VK_CALL(iface, FreeMemory(fGpu->device(), fAlloc, nullptr));
}
bool GrVkSubHeap::alloc(VkDeviceSize size, GrVkAlloc* alloc) {
alloc->fMemory = fAlloc;
return INHERITED::alloc(size, &alloc->fOffset, &alloc->fSize);
}
void GrVkSubHeap::free(const GrVkAlloc& alloc) {
SkASSERT(alloc.fMemory == fAlloc);
INHERITED::free(alloc.fOffset, alloc.fSize);
}
bool GrVkHeap::subAlloc(VkDeviceSize size, VkDeviceSize alignment,

View File

@ -39,42 +39,75 @@ namespace GrVkMemory {
VkAccessFlags LayoutToSrcAccessMask(const VkImageLayout layout);
}
class GrVkSubHeap {
class GrVkFreeListAlloc {
public:
GrVkSubHeap(const GrVkGpu* gpu, uint32_t memoryTypeIndex,
VkDeviceSize size, VkDeviceSize alignment);
~GrVkSubHeap();
GrVkFreeListAlloc(VkDeviceSize size, VkDeviceSize alignment)
: fSize(size)
, fAlignment(alignment)
, fFreeSize(size)
, fLargestBlockSize(size)
, fLargestBlockOffset(0) {
Block* block = fFreeList.addToTail();
block->fOffset = 0;
block->fSize = fSize;
}
~GrVkFreeListAlloc() {
this->reset();
}
uint32_t memoryTypeIndex() const { return fMemoryTypeIndex; }
VkDeviceSize size() const { return fSize; }
VkDeviceSize alignment() const { return fAlignment; }
VkDeviceSize freeSize() const { return fFreeSize; }
VkDeviceSize largestBlockSize() const { return fLargestBlockSize; }
VkDeviceMemory memory() { return fAlloc; }
bool unallocated() const { return fSize == fFreeSize; }
bool alloc(VkDeviceSize size, GrVkAlloc* alloc);
void free(const GrVkAlloc& alloc);
protected:
bool alloc(VkDeviceSize requestedSize, VkDeviceSize* allocOffset, VkDeviceSize* allocSize);
void free(VkDeviceSize allocOffset, VkDeviceSize allocSize);
void reset() {
fSize = 0;
fAlignment = 0;
fFreeSize = 0;
fLargestBlockSize = 0;
fFreeList.reset();
}
private:
struct Block {
VkDeviceSize fOffset;
VkDeviceSize fSize;
};
typedef SkTLList<Block, 16> FreeList;
const GrVkGpu* fGpu;
uint32_t fMemoryTypeIndex;
VkDeviceSize fSize;
VkDeviceSize fAlignment;
VkDeviceSize fFreeSize;
VkDeviceSize fLargestBlockSize;
VkDeviceSize fLargestBlockOffset;
VkDeviceMemory fAlloc;
FreeList fFreeList;
};
class GrVkSubHeap : public GrVkFreeListAlloc {
public:
GrVkSubHeap(const GrVkGpu* gpu, uint32_t memoryTypeIndex,
VkDeviceSize size, VkDeviceSize alignment);
~GrVkSubHeap();
uint32_t memoryTypeIndex() const { return fMemoryTypeIndex; }
VkDeviceMemory memory() { return fAlloc; }
bool alloc(VkDeviceSize requestedSize, GrVkAlloc* alloc);
void free(const GrVkAlloc& alloc);
private:
const GrVkGpu* fGpu;
uint32_t fMemoryTypeIndex;
VkDeviceMemory fAlloc;
typedef GrVkFreeListAlloc INHERITED;
};
class GrVkHeap {
public:
enum Strategy {
@ -94,7 +127,7 @@ public:
}
}
~GrVkHeap();
~GrVkHeap() {}
VkDeviceSize allocSize() const { return fAllocSize; }
VkDeviceSize usedSize() const { return fUsedSize; }