/* * Copyright 2015 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef GrVkMemory_DEFINED #define GrVkMemory_DEFINED #include "GrVkBuffer.h" #include "SkTArray.h" #include "SkTLList.h" #include "vk/GrVkDefines.h" #include "vk/GrVkTypes.h" class GrVkGpu; namespace GrVkMemory { /** * Allocates vulkan device memory and binds it to the gpu's device for the given object. * Returns true if allocation succeeded. */ bool AllocAndBindBufferMemory(const GrVkGpu* gpu, VkBuffer buffer, GrVkBuffer::Type type, bool dynamic, GrVkAlloc* alloc); void FreeBufferMemory(const GrVkGpu* gpu, GrVkBuffer::Type type, const GrVkAlloc& alloc); bool AllocAndBindImageMemory(const GrVkGpu* gpu, VkImage image, bool linearTiling, GrVkAlloc* alloc); void FreeImageMemory(const GrVkGpu* gpu, bool linearTiling, const GrVkAlloc& alloc); VkPipelineStageFlags LayoutToPipelineStageFlags(const VkImageLayout layout); VkAccessFlags LayoutToSrcAccessMask(const VkImageLayout layout); void FlushMappedAlloc(const GrVkGpu* gpu, const GrVkAlloc& alloc); void InvalidateMappedAlloc(const GrVkGpu* gpu, const GrVkAlloc& alloc); } class GrVkFreeListAlloc { public: 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(); } VkDeviceSize size() const { return fSize; } VkDeviceSize alignment() const { return fAlignment; } VkDeviceSize freeSize() const { return fFreeSize; } VkDeviceSize largestBlockSize() const { return fLargestBlockSize; } bool unallocated() const { return fSize == fFreeSize; } 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(); } struct Block { VkDeviceSize fOffset; VkDeviceSize fSize; }; typedef SkTLList<Block, 16> FreeList; VkDeviceSize fSize; VkDeviceSize fAlignment; VkDeviceSize fFreeSize; VkDeviceSize fLargestBlockSize; VkDeviceSize fLargestBlockOffset; FreeList fFreeList; }; class GrVkSubHeap : public GrVkFreeListAlloc { public: GrVkSubHeap(const GrVkGpu* gpu, uint32_t memoryTypeIndex, uint32_t heapIndex, 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; #ifdef SK_DEBUG uint32_t fHeapIndex; #endif uint32_t fMemoryTypeIndex; VkDeviceMemory fAlloc; typedef GrVkFreeListAlloc INHERITED; }; class GrVkHeap { public: enum Strategy { kSubAlloc_Strategy, // alloc large subheaps and suballoc within them kSingleAlloc_Strategy // alloc/recycle an individual subheap per object }; GrVkHeap(const GrVkGpu* gpu, Strategy strategy, VkDeviceSize subHeapSize) : fGpu(gpu) , fSubHeapSize(subHeapSize) , fAllocSize(0) , fUsedSize(0) { if (strategy == kSubAlloc_Strategy) { fAllocFunc = &GrVkHeap::subAlloc; } else { fAllocFunc = &GrVkHeap::singleAlloc; } } ~GrVkHeap() {} VkDeviceSize allocSize() const { return fAllocSize; } VkDeviceSize usedSize() const { return fUsedSize; } bool alloc(VkDeviceSize size, VkDeviceSize alignment, uint32_t memoryTypeIndex, uint32_t heapIndex, GrVkAlloc* alloc) { SkASSERT(size > 0); return (*this.*fAllocFunc)(size, alignment, memoryTypeIndex, heapIndex, alloc); } bool free(const GrVkAlloc& alloc); private: typedef bool (GrVkHeap::*AllocFunc)(VkDeviceSize size, VkDeviceSize alignment, uint32_t memoryTypeIndex, uint32_t heapIndex, GrVkAlloc* alloc); bool subAlloc(VkDeviceSize size, VkDeviceSize alignment, uint32_t memoryTypeIndex, uint32_t heapIndex, GrVkAlloc* alloc); bool singleAlloc(VkDeviceSize size, VkDeviceSize alignment, uint32_t memoryTypeIndex, uint32_t heapIndex, GrVkAlloc* alloc); const GrVkGpu* fGpu; VkDeviceSize fSubHeapSize; VkDeviceSize fAllocSize; VkDeviceSize fUsedSize; AllocFunc fAllocFunc; SkTArray<std::unique_ptr<GrVkSubHeap>> fSubHeaps; }; #endif