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; return flags;
} }
GrVkSubHeap::GrVkSubHeap(const GrVkGpu* gpu, uint32_t memoryTypeIndex, bool GrVkFreeListAlloc::alloc(VkDeviceSize requestedSize,
VkDeviceSize size, VkDeviceSize alignment) VkDeviceSize* allocOffset, VkDeviceSize* allocSize) {
: fGpu(gpu) VkDeviceSize alignedSize = align_size(requestedSize, fAlignment);
, 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);
// find the smallest block big enough for our allocation // find the smallest block big enough for our allocation
FreeList::Iter iter = fFreeList.headIter(); FreeList::Iter iter = fFreeList.headIter();
@ -311,10 +270,9 @@ bool GrVkSubHeap::alloc(VkDeviceSize size, GrVkAlloc* alloc) {
Block* bestFit = bestFitIter.get(); Block* bestFit = bestFitIter.get();
if (bestFit) { if (bestFit) {
alloc->fMemory = fAlloc;
SkASSERT(align_size(bestFit->fOffset, fAlignment) == bestFit->fOffset); SkASSERT(align_size(bestFit->fOffset, fAlignment) == bestFit->fOffset);
alloc->fOffset = bestFit->fOffset; *allocOffset = bestFit->fOffset;
alloc->fSize = alignedSize; *allocSize = alignedSize;
// adjust or remove current block // adjust or remove current block
VkDeviceSize originalBestFitOffset = bestFit->fOffset; VkDeviceSize originalBestFitOffset = bestFit->fOffset;
if (bestFit->fSize > alignedSize) { if (bestFit->fSize > alignedSize) {
@ -362,38 +320,35 @@ bool GrVkSubHeap::alloc(VkDeviceSize size, GrVkAlloc* alloc) {
#endif #endif
} }
fFreeSize -= alignedSize; fFreeSize -= alignedSize;
SkASSERT(alloc->fSize > 0); SkASSERT(allocSize > 0);
return true; return true;
} }
SkDebugf("Can't allocate %d bytes, %d bytes available, largest free block %d\n", alignedSize, fFreeSize, fLargestBlockSize); SkDebugf("Can't allocate %d bytes, %d bytes available, largest free block %d\n", alignedSize, fFreeSize, fLargestBlockSize);
return false; return false;
} }
void GrVkFreeListAlloc::free(VkDeviceSize allocOffset, VkDeviceSize allocSize) {
void GrVkSubHeap::free(const GrVkAlloc& alloc) {
SkASSERT(alloc.fMemory == fAlloc);
// find the block right after this allocation // find the block right after this allocation
FreeList::Iter iter = fFreeList.headIter(); FreeList::Iter iter = fFreeList.headIter();
FreeList::Iter prev; FreeList::Iter prev;
while (iter.get() && iter.get()->fOffset < alloc.fOffset) { while (iter.get() && iter.get()->fOffset < allocOffset) {
prev = iter; prev = iter;
iter.next(); iter.next();
} }
// we have four cases: // we have four cases:
// we exactly follow the previous one // we exactly follow the previous one
Block* block; 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 = prev.get();
block->fSize += alloc.fSize; block->fSize += allocSize;
if (block->fOffset == fLargestBlockOffset) { if (block->fOffset == fLargestBlockOffset) {
fLargestBlockSize = block->fSize; fLargestBlockSize = block->fSize;
} }
// and additionally we may exactly precede the next one // 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; block->fSize += iter.get()->fSize;
if (iter.get()->fOffset == fLargestBlockOffset) { if (iter.get()->fOffset == fLargestBlockOffset) {
fLargestBlockOffset = block->fOffset; fLargestBlockOffset = block->fOffset;
@ -402,21 +357,21 @@ void GrVkSubHeap::free(const GrVkAlloc& alloc) {
fFreeList.remove(iter.get()); fFreeList.remove(iter.get());
} }
// or we only exactly proceed the next one // 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 = iter.get();
block->fSize += alloc.fSize; block->fSize += allocSize;
if (block->fOffset == fLargestBlockOffset) { if (block->fOffset == fLargestBlockOffset) {
fLargestBlockOffset = alloc.fOffset; fLargestBlockOffset = allocOffset;
fLargestBlockSize = block->fSize; fLargestBlockSize = block->fSize;
} }
block->fOffset = alloc.fOffset; block->fOffset = allocOffset;
// or we fall somewhere in between, with gaps // or we fall somewhere in between, with gaps
} else { } else {
block = fFreeList.addBefore(iter); block = fFreeList.addBefore(iter);
block->fOffset = alloc.fOffset; block->fOffset = allocOffset;
block->fSize = alloc.fSize; block->fSize = allocSize;
} }
fFreeSize += alloc.fSize; fFreeSize += allocSize;
if (block->fSize > fLargestBlockSize) { if (block->fSize > fLargestBlockSize) {
fLargestBlockSize = block->fSize; fLargestBlockSize = block->fSize;
fLargestBlockOffset = block->fOffset; fLargestBlockOffset = block->fOffset;
@ -436,7 +391,42 @@ void GrVkSubHeap::free(const GrVkAlloc& alloc) {
#endif #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, bool GrVkHeap::subAlloc(VkDeviceSize size, VkDeviceSize alignment,

View File

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