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, VkDeviceSize offset, 42 VkDeviceSize size); 43 void InvalidateMappedAlloc(const GrVkGpu* gpu, const GrVkAlloc& alloc, VkDeviceSize offset, 44 VkDeviceSize size); 45 } 46 47 class GrVkFreeListAlloc { 48 public: 49 GrVkFreeListAlloc(VkDeviceSize size, VkDeviceSize alignment) 50 : fSize(size) 51 , fAlignment(alignment) 52 , fFreeSize(size) 53 , fLargestBlockSize(size) 54 , fLargestBlockOffset(0) { 55 Block* block = fFreeList.addToTail(); 56 block->fOffset = 0; 57 block->fSize = fSize; 58 } 59 ~GrVkFreeListAlloc() { 60 this->reset(); 61 } 62 63 VkDeviceSize size() const { return fSize; } 64 VkDeviceSize alignment() const { return fAlignment; } 65 VkDeviceSize freeSize() const { return fFreeSize; } 66 VkDeviceSize largestBlockSize() const { return fLargestBlockSize; } 67 68 bool unallocated() const { return fSize == fFreeSize; } 69 70 protected: 71 bool alloc(VkDeviceSize requestedSize, VkDeviceSize* allocOffset, VkDeviceSize* allocSize); 72 void free(VkDeviceSize allocOffset, VkDeviceSize allocSize); 73 74 void reset() { 75 fSize = 0; 76 fAlignment = 0; 77 fFreeSize = 0; 78 fLargestBlockSize = 0; 79 fFreeList.reset(); 80 } 81 82 struct Block { 83 VkDeviceSize fOffset; 84 VkDeviceSize fSize; 85 }; 86 typedef SkTLList<Block, 16> FreeList; 87 88 VkDeviceSize fSize; 89 VkDeviceSize fAlignment; 90 VkDeviceSize fFreeSize; 91 VkDeviceSize fLargestBlockSize; 92 VkDeviceSize fLargestBlockOffset; 93 FreeList fFreeList; 94 }; 95 96 class GrVkSubHeap : public GrVkFreeListAlloc { 97 public: 98 GrVkSubHeap(const GrVkGpu* gpu, uint32_t memoryTypeIndex, uint32_t heapIndex, 99 VkDeviceSize size, VkDeviceSize alignment); 100 ~GrVkSubHeap(); 101 102 uint32_t memoryTypeIndex() const { return fMemoryTypeIndex; } 103 VkDeviceMemory memory() { return fAlloc; } 104 105 bool alloc(VkDeviceSize requestedSize, GrVkAlloc* alloc); 106 void free(const GrVkAlloc& alloc); 107 108 private: 109 const GrVkGpu* fGpu; 110 #ifdef SK_DEBUG 111 uint32_t fHeapIndex; 112 #endif 113 uint32_t fMemoryTypeIndex; 114 VkDeviceMemory fAlloc; 115 116 typedef GrVkFreeListAlloc INHERITED; 117 }; 118 119 class GrVkHeap { 120 public: 121 enum Strategy { 122 kSubAlloc_Strategy, // alloc large subheaps and suballoc within them 123 kSingleAlloc_Strategy // alloc/recycle an individual subheap per object 124 }; 125 126 GrVkHeap(const GrVkGpu* gpu, Strategy strategy, VkDeviceSize subHeapSize) 127 : fGpu(gpu) 128 , fSubHeapSize(subHeapSize) 129 , fAllocSize(0) 130 , fUsedSize(0) { 131 if (strategy == kSubAlloc_Strategy) { 132 fAllocFunc = &GrVkHeap::subAlloc; 133 } else { 134 fAllocFunc = &GrVkHeap::singleAlloc; 135 } 136 } 137 138 ~GrVkHeap() {} 139 140 VkDeviceSize allocSize() const { return fAllocSize; } 141 VkDeviceSize usedSize() const { return fUsedSize; } 142 143 bool alloc(VkDeviceSize size, VkDeviceSize alignment, uint32_t memoryTypeIndex, 144 uint32_t heapIndex, GrVkAlloc* alloc) { 145 SkASSERT(size > 0); 146 alloc->fUsesSystemHeap = false; 147 return (*this.*fAllocFunc)(size, alignment, memoryTypeIndex, heapIndex, alloc); 148 } 149 bool free(const GrVkAlloc& alloc); 150 151 private: 152 typedef bool (GrVkHeap::*AllocFunc)(VkDeviceSize size, VkDeviceSize alignment, 153 uint32_t memoryTypeIndex, uint32_t heapIndex, 154 GrVkAlloc* alloc); 155 156 bool subAlloc(VkDeviceSize size, VkDeviceSize alignment, 157 uint32_t memoryTypeIndex, uint32_t heapIndex, 158 GrVkAlloc* alloc); 159 bool singleAlloc(VkDeviceSize size, VkDeviceSize alignment, 160 uint32_t memoryTypeIndex, uint32_t heapIndex, 161 GrVkAlloc* alloc); 162 163 const GrVkGpu* fGpu; 164 VkDeviceSize fSubHeapSize; 165 VkDeviceSize fAllocSize; 166 VkDeviceSize fUsedSize; 167 AllocFunc fAllocFunc; 168 SkTArray<std::unique_ptr<GrVkSubHeap>> fSubHeaps; 169 }; 170 #endif 171