1 /* 2 * Copyright 2015 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef GrVkMemory_DEFINED 9 #define GrVkMemory_DEFINED 10 11 #include "GrVkBuffer.h" 12 #include "SkTArray.h" 13 #include "SkTLList.h" 14 #include "vk/GrVkDefines.h" 15 #include "vk/GrVkTypes.h" 16 17 class GrVkGpu; 18 19 namespace GrVkMemory { 20 /** 21 * Allocates vulkan device memory and binds it to the gpu's device for the given object. 22 * Returns true if allocation succeeded. 23 */ 24 bool AllocAndBindBufferMemory(const GrVkGpu* gpu, 25 VkBuffer buffer, 26 GrVkBuffer::Type type, 27 bool dynamic, 28 GrVkAlloc* alloc); 29 void FreeBufferMemory(const GrVkGpu* gpu, GrVkBuffer::Type type, const GrVkAlloc& alloc); 30 31 bool AllocAndBindImageMemory(const GrVkGpu* gpu, 32 VkImage image, 33 bool linearTiling, 34 GrVkAlloc* alloc); 35 void FreeImageMemory(const GrVkGpu* gpu, bool linearTiling, const GrVkAlloc& alloc); 36 37 VkPipelineStageFlags LayoutToPipelineStageFlags(const VkImageLayout layout); 38 39 VkAccessFlags LayoutToSrcAccessMask(const VkImageLayout layout); 40 41 void FlushMappedAlloc(const GrVkGpu* gpu, const GrVkAlloc& alloc); 42 void InvalidateMappedAlloc(const GrVkGpu* gpu, const GrVkAlloc& alloc); 43 } 44 45 class GrVkFreeListAlloc { 46 public: GrVkFreeListAlloc(VkDeviceSize size,VkDeviceSize alignment)47 GrVkFreeListAlloc(VkDeviceSize size, VkDeviceSize alignment) 48 : fSize(size) 49 , fAlignment(alignment) 50 , fFreeSize(size) 51 , fLargestBlockSize(size) 52 , fLargestBlockOffset(0) { 53 Block* block = fFreeList.addToTail(); 54 block->fOffset = 0; 55 block->fSize = fSize; 56 } ~GrVkFreeListAlloc()57 ~GrVkFreeListAlloc() { 58 this->reset(); 59 } 60 size()61 VkDeviceSize size() const { return fSize; } alignment()62 VkDeviceSize alignment() const { return fAlignment; } freeSize()63 VkDeviceSize freeSize() const { return fFreeSize; } largestBlockSize()64 VkDeviceSize largestBlockSize() const { return fLargestBlockSize; } 65 unallocated()66 bool unallocated() const { return fSize == fFreeSize; } 67 68 protected: 69 bool alloc(VkDeviceSize requestedSize, VkDeviceSize* allocOffset, VkDeviceSize* allocSize); 70 void free(VkDeviceSize allocOffset, VkDeviceSize allocSize); 71 reset()72 void reset() { 73 fSize = 0; 74 fAlignment = 0; 75 fFreeSize = 0; 76 fLargestBlockSize = 0; 77 fFreeList.reset(); 78 } 79 80 struct Block { 81 VkDeviceSize fOffset; 82 VkDeviceSize fSize; 83 }; 84 typedef SkTLList<Block, 16> FreeList; 85 86 VkDeviceSize fSize; 87 VkDeviceSize fAlignment; 88 VkDeviceSize fFreeSize; 89 VkDeviceSize fLargestBlockSize; 90 VkDeviceSize fLargestBlockOffset; 91 FreeList fFreeList; 92 }; 93 94 class GrVkSubHeap : public GrVkFreeListAlloc { 95 public: 96 GrVkSubHeap(const GrVkGpu* gpu, uint32_t memoryTypeIndex, uint32_t heapIndex, 97 VkDeviceSize size, VkDeviceSize alignment); 98 ~GrVkSubHeap(); 99 memoryTypeIndex()100 uint32_t memoryTypeIndex() const { return fMemoryTypeIndex; } memory()101 VkDeviceMemory memory() { return fAlloc; } 102 103 bool alloc(VkDeviceSize requestedSize, GrVkAlloc* alloc); 104 void free(const GrVkAlloc& alloc); 105 106 private: 107 const GrVkGpu* fGpu; 108 #ifdef SK_DEBUG 109 uint32_t fHeapIndex; 110 #endif 111 uint32_t fMemoryTypeIndex; 112 VkDeviceMemory fAlloc; 113 114 typedef GrVkFreeListAlloc INHERITED; 115 }; 116 117 class GrVkHeap { 118 public: 119 enum Strategy { 120 kSubAlloc_Strategy, // alloc large subheaps and suballoc within them 121 kSingleAlloc_Strategy // alloc/recycle an individual subheap per object 122 }; 123 GrVkHeap(const GrVkGpu * gpu,Strategy strategy,VkDeviceSize subHeapSize)124 GrVkHeap(const GrVkGpu* gpu, Strategy strategy, VkDeviceSize subHeapSize) 125 : fGpu(gpu) 126 , fSubHeapSize(subHeapSize) 127 , fAllocSize(0) 128 , fUsedSize(0) { 129 if (strategy == kSubAlloc_Strategy) { 130 fAllocFunc = &GrVkHeap::subAlloc; 131 } else { 132 fAllocFunc = &GrVkHeap::singleAlloc; 133 } 134 } 135 ~GrVkHeap()136 ~GrVkHeap() {} 137 allocSize()138 VkDeviceSize allocSize() const { return fAllocSize; } usedSize()139 VkDeviceSize usedSize() const { return fUsedSize; } 140 alloc(VkDeviceSize size,VkDeviceSize alignment,uint32_t memoryTypeIndex,uint32_t heapIndex,GrVkAlloc * alloc)141 bool alloc(VkDeviceSize size, VkDeviceSize alignment, uint32_t memoryTypeIndex, 142 uint32_t heapIndex, GrVkAlloc* alloc) { 143 SkASSERT(size > 0); 144 return (*this.*fAllocFunc)(size, alignment, memoryTypeIndex, heapIndex, alloc); 145 } 146 bool free(const GrVkAlloc& alloc); 147 148 private: 149 typedef bool (GrVkHeap::*AllocFunc)(VkDeviceSize size, VkDeviceSize alignment, 150 uint32_t memoryTypeIndex, uint32_t heapIndex, 151 GrVkAlloc* alloc); 152 153 bool subAlloc(VkDeviceSize size, VkDeviceSize alignment, 154 uint32_t memoryTypeIndex, uint32_t heapIndex, 155 GrVkAlloc* alloc); 156 bool singleAlloc(VkDeviceSize size, VkDeviceSize alignment, 157 uint32_t memoryTypeIndex, uint32_t heapIndex, 158 GrVkAlloc* alloc); 159 160 const GrVkGpu* fGpu; 161 VkDeviceSize fSubHeapSize; 162 VkDeviceSize fAllocSize; 163 VkDeviceSize fUsedSize; 164 AllocFunc fAllocFunc; 165 SkTArray<std::unique_ptr<GrVkSubHeap>> fSubHeaps; 166 }; 167 #endif 168