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:
parent
552882f768
commit
82356cc41f
@ -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,
|
||||
|
@ -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; }
|
||||
|
Loading…
Reference in New Issue
Block a user