1 //
2 // Copyright 2020 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // vma_allocator_wrapper.cpp:
7 // Hides VMA functions so we can use separate warning sets.
8 //
9
10 #include "vk_mem_alloc_wrapper.h"
11
12 #include <vk_mem_alloc.h>
13
14 namespace vma
15 {
16 #define VALIDATE_BLOCK_CREATE_FLAG_BITS(x) \
17 static_assert(static_cast<uint32_t>(x) == \
18 static_cast<uint32_t>(VMA_VIRTUAL_BLOCK_CREATE_##x##_ALGORITHM_BIT), \
19 "VMA enum mismatch")
20 VALIDATE_BLOCK_CREATE_FLAG_BITS(LINEAR);
21 VALIDATE_BLOCK_CREATE_FLAG_BITS(BUDDY);
22
InitAllocator(VkPhysicalDevice physicalDevice,VkDevice device,VkInstance instance,uint32_t apiVersion,VkDeviceSize preferredLargeHeapBlockSize,VmaAllocator * pAllocator)23 VkResult InitAllocator(VkPhysicalDevice physicalDevice,
24 VkDevice device,
25 VkInstance instance,
26 uint32_t apiVersion,
27 VkDeviceSize preferredLargeHeapBlockSize,
28 VmaAllocator *pAllocator)
29 {
30 VmaVulkanFunctions funcs = {};
31 funcs.vkGetPhysicalDeviceProperties = vkGetPhysicalDeviceProperties;
32 funcs.vkGetPhysicalDeviceMemoryProperties = vkGetPhysicalDeviceMemoryProperties;
33 funcs.vkAllocateMemory = vkAllocateMemory;
34 funcs.vkFreeMemory = vkFreeMemory;
35 funcs.vkMapMemory = vkMapMemory;
36 funcs.vkUnmapMemory = vkUnmapMemory;
37 funcs.vkFlushMappedMemoryRanges = vkFlushMappedMemoryRanges;
38 funcs.vkInvalidateMappedMemoryRanges = vkInvalidateMappedMemoryRanges;
39 funcs.vkBindBufferMemory = vkBindBufferMemory;
40 funcs.vkBindImageMemory = vkBindImageMemory;
41 funcs.vkGetBufferMemoryRequirements = vkGetBufferMemoryRequirements;
42 funcs.vkGetImageMemoryRequirements = vkGetImageMemoryRequirements;
43 funcs.vkCreateBuffer = vkCreateBuffer;
44 funcs.vkDestroyBuffer = vkDestroyBuffer;
45 funcs.vkCreateImage = vkCreateImage;
46 funcs.vkDestroyImage = vkDestroyImage;
47 funcs.vkCmdCopyBuffer = vkCmdCopyBuffer;
48 {
49 #if !defined(ANGLE_SHARED_LIBVULKAN)
50 // When the vulkan-loader is statically linked, we need to use the extension
51 // functions defined in ANGLE's rx namespace. When it's dynamically linked
52 // with volk, this will default to the function definitions with no namespace
53 using rx::vkBindBufferMemory2KHR;
54 using rx::vkBindImageMemory2KHR;
55 using rx::vkGetBufferMemoryRequirements2KHR;
56 using rx::vkGetImageMemoryRequirements2KHR;
57 using rx::vkGetPhysicalDeviceMemoryProperties2KHR;
58 #endif // !defined(ANGLE_SHARED_LIBVULKAN)
59 funcs.vkGetBufferMemoryRequirements2KHR = vkGetBufferMemoryRequirements2KHR;
60 funcs.vkGetImageMemoryRequirements2KHR = vkGetImageMemoryRequirements2KHR;
61 funcs.vkBindBufferMemory2KHR = vkBindBufferMemory2KHR;
62 funcs.vkBindImageMemory2KHR = vkBindImageMemory2KHR;
63 funcs.vkGetPhysicalDeviceMemoryProperties2KHR = vkGetPhysicalDeviceMemoryProperties2KHR;
64 }
65
66 VmaAllocatorCreateInfo allocatorInfo = {};
67 allocatorInfo.physicalDevice = physicalDevice;
68 allocatorInfo.device = device;
69 allocatorInfo.instance = instance;
70 allocatorInfo.pVulkanFunctions = &funcs;
71 allocatorInfo.vulkanApiVersion = apiVersion;
72 allocatorInfo.preferredLargeHeapBlockSize = preferredLargeHeapBlockSize;
73
74 return vmaCreateAllocator(&allocatorInfo, pAllocator);
75 }
76
DestroyAllocator(VmaAllocator allocator)77 void DestroyAllocator(VmaAllocator allocator)
78 {
79 vmaDestroyAllocator(allocator);
80 }
81
CreatePool(VmaAllocator allocator,uint32_t memoryTypeIndex,bool buddyAlgorithm,VkDeviceSize blockSize,VmaPool * pPool)82 VkResult CreatePool(VmaAllocator allocator,
83 uint32_t memoryTypeIndex,
84 bool buddyAlgorithm,
85 VkDeviceSize blockSize,
86 VmaPool *pPool)
87 {
88 VmaPoolCreateInfo poolCreateInfo = {};
89 poolCreateInfo.memoryTypeIndex = memoryTypeIndex;
90 poolCreateInfo.flags = VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT;
91 if (buddyAlgorithm)
92 {
93 poolCreateInfo.flags |= VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT;
94 }
95 poolCreateInfo.blockSize = blockSize;
96 poolCreateInfo.maxBlockCount = -1; // unlimited
97 return vmaCreatePool(allocator, &poolCreateInfo, pPool);
98 }
99
DestroyPool(VmaAllocator allocator,VmaPool pool)100 void DestroyPool(VmaAllocator allocator, VmaPool pool)
101 {
102 vmaDestroyPool(allocator, pool);
103 }
104
FreeMemory(VmaAllocator allocator,VmaAllocation allocation)105 void FreeMemory(VmaAllocator allocator, VmaAllocation allocation)
106 {
107 vmaFreeMemory(allocator, allocation);
108 }
109
CreateBuffer(VmaAllocator allocator,const VkBufferCreateInfo * pBufferCreateInfo,VkMemoryPropertyFlags requiredFlags,VkMemoryPropertyFlags preferredFlags,bool persistentlyMapped,uint32_t * pMemoryTypeIndexOut,VkBuffer * pBuffer,VmaAllocation * pAllocation)110 VkResult CreateBuffer(VmaAllocator allocator,
111 const VkBufferCreateInfo *pBufferCreateInfo,
112 VkMemoryPropertyFlags requiredFlags,
113 VkMemoryPropertyFlags preferredFlags,
114 bool persistentlyMapped,
115 uint32_t *pMemoryTypeIndexOut,
116 VkBuffer *pBuffer,
117 VmaAllocation *pAllocation)
118 {
119 VkResult result;
120 VmaAllocationCreateInfo allocationCreateInfo = {};
121 allocationCreateInfo.requiredFlags = requiredFlags;
122 allocationCreateInfo.preferredFlags = preferredFlags;
123 allocationCreateInfo.flags = (persistentlyMapped) ? VMA_ALLOCATION_CREATE_MAPPED_BIT : 0;
124 VmaAllocationInfo allocationInfo = {};
125
126 result = vmaCreateBuffer(allocator, pBufferCreateInfo, &allocationCreateInfo, pBuffer,
127 pAllocation, &allocationInfo);
128 *pMemoryTypeIndexOut = allocationInfo.memoryType;
129
130 return result;
131 }
132
FindMemoryTypeIndexForBufferInfo(VmaAllocator allocator,const VkBufferCreateInfo * pBufferCreateInfo,VkMemoryPropertyFlags requiredFlags,VkMemoryPropertyFlags preferredFlags,bool persistentlyMappedBuffers,uint32_t * pMemoryTypeIndexOut)133 VkResult FindMemoryTypeIndexForBufferInfo(VmaAllocator allocator,
134 const VkBufferCreateInfo *pBufferCreateInfo,
135 VkMemoryPropertyFlags requiredFlags,
136 VkMemoryPropertyFlags preferredFlags,
137 bool persistentlyMappedBuffers,
138 uint32_t *pMemoryTypeIndexOut)
139 {
140 VmaAllocationCreateInfo allocationCreateInfo = {};
141 allocationCreateInfo.requiredFlags = requiredFlags;
142 allocationCreateInfo.preferredFlags = preferredFlags;
143 allocationCreateInfo.flags = (persistentlyMappedBuffers) ? VMA_ALLOCATION_CREATE_MAPPED_BIT : 0;
144
145 return vmaFindMemoryTypeIndexForBufferInfo(allocator, pBufferCreateInfo, &allocationCreateInfo,
146 pMemoryTypeIndexOut);
147 }
148
GetMemoryTypeProperties(VmaAllocator allocator,uint32_t memoryTypeIndex,VkMemoryPropertyFlags * pFlags)149 void GetMemoryTypeProperties(VmaAllocator allocator,
150 uint32_t memoryTypeIndex,
151 VkMemoryPropertyFlags *pFlags)
152 {
153 vmaGetMemoryTypeProperties(allocator, memoryTypeIndex, pFlags);
154 }
155
MapMemory(VmaAllocator allocator,VmaAllocation allocation,void ** ppData)156 VkResult MapMemory(VmaAllocator allocator, VmaAllocation allocation, void **ppData)
157 {
158 return vmaMapMemory(allocator, allocation, ppData);
159 }
160
UnmapMemory(VmaAllocator allocator,VmaAllocation allocation)161 void UnmapMemory(VmaAllocator allocator, VmaAllocation allocation)
162 {
163 return vmaUnmapMemory(allocator, allocation);
164 }
165
FlushAllocation(VmaAllocator allocator,VmaAllocation allocation,VkDeviceSize offset,VkDeviceSize size)166 void FlushAllocation(VmaAllocator allocator,
167 VmaAllocation allocation,
168 VkDeviceSize offset,
169 VkDeviceSize size)
170 {
171 vmaFlushAllocation(allocator, allocation, offset, size);
172 }
173
InvalidateAllocation(VmaAllocator allocator,VmaAllocation allocation,VkDeviceSize offset,VkDeviceSize size)174 void InvalidateAllocation(VmaAllocator allocator,
175 VmaAllocation allocation,
176 VkDeviceSize offset,
177 VkDeviceSize size)
178 {
179 vmaInvalidateAllocation(allocator, allocation, offset, size);
180 }
181
BuildStatsString(VmaAllocator allocator,char ** statsString,VkBool32 detailedMap)182 void BuildStatsString(VmaAllocator allocator, char **statsString, VkBool32 detailedMap)
183 {
184 vmaBuildStatsString(allocator, statsString, detailedMap);
185 }
186
FreeStatsString(VmaAllocator allocator,char * statsString)187 void FreeStatsString(VmaAllocator allocator, char *statsString)
188 {
189 vmaFreeStatsString(allocator, statsString);
190 }
191
192 // VmaVirtualBlock implementation
CreateVirtualBlock(VkDeviceSize size,VirtualBlockCreateFlags flags,VmaVirtualBlock * pVirtualBlock)193 VkResult CreateVirtualBlock(VkDeviceSize size,
194 VirtualBlockCreateFlags flags,
195 VmaVirtualBlock *pVirtualBlock)
196 {
197 VmaVirtualBlockCreateInfo virtualBlockCreateInfo = {};
198 virtualBlockCreateInfo.size = size;
199 virtualBlockCreateInfo.flags = (VmaVirtualBlockCreateFlagBits)flags;
200 return vmaCreateVirtualBlock(&virtualBlockCreateInfo, pVirtualBlock);
201 }
202
DestroyVirtualBlock(VmaVirtualBlock virtualBlock)203 void DestroyVirtualBlock(VmaVirtualBlock virtualBlock)
204 {
205 vmaDestroyVirtualBlock(virtualBlock);
206 }
207
VirtualAllocate(VmaVirtualBlock virtualBlock,VkDeviceSize size,VkDeviceSize alignment,VkDeviceSize * pOffset)208 VkResult VirtualAllocate(VmaVirtualBlock virtualBlock,
209 VkDeviceSize size,
210 VkDeviceSize alignment,
211 VkDeviceSize *pOffset)
212 {
213 VmaVirtualAllocationCreateInfo createInfo = {};
214 createInfo.size = size;
215 createInfo.alignment = alignment;
216 createInfo.flags = 0;
217 return vmaVirtualAllocate(virtualBlock, &createInfo, pOffset);
218 }
219
VirtualFree(VmaVirtualBlock virtualBlock,VkDeviceSize offset)220 void VirtualFree(VmaVirtualBlock virtualBlock, VkDeviceSize offset)
221 {
222 vmaVirtualFree(virtualBlock, offset);
223 }
224
IsVirtualBlockEmpty(VmaVirtualBlock virtualBlock)225 VkBool32 IsVirtualBlockEmpty(VmaVirtualBlock virtualBlock)
226 {
227 return vmaIsVirtualBlockEmpty(virtualBlock);
228 }
229
GetVirtualAllocationInfo(VmaVirtualBlock virtualBlock,VkDeviceSize offset,VkDeviceSize * sizeOut,void ** pUserDataOut)230 void GetVirtualAllocationInfo(VmaVirtualBlock virtualBlock,
231 VkDeviceSize offset,
232 VkDeviceSize *sizeOut,
233 void **pUserDataOut)
234 {
235 VmaVirtualAllocationInfo virtualAllocInfo = {};
236 vmaGetVirtualAllocationInfo(virtualBlock, offset, &virtualAllocInfo);
237 *sizeOut = virtualAllocInfo.size;
238 *pUserDataOut = virtualAllocInfo.pUserData;
239 }
240
ClearVirtualBlock(VmaVirtualBlock virtualBlock)241 void ClearVirtualBlock(VmaVirtualBlock virtualBlock)
242 {
243 vmaClearVirtualBlock(virtualBlock);
244 }
245
SetVirtualAllocationUserData(VmaVirtualBlock virtualBlock,VkDeviceSize offset,void * pUserData)246 void SetVirtualAllocationUserData(VmaVirtualBlock virtualBlock,
247 VkDeviceSize offset,
248 void *pUserData)
249 {
250 vmaSetVirtualAllocationUserData(virtualBlock, offset, pUserData);
251 }
252
CalculateVirtualBlockStats(VmaVirtualBlock virtualBlock,StatInfo * pStatInfo)253 void CalculateVirtualBlockStats(VmaVirtualBlock virtualBlock, StatInfo *pStatInfo)
254 {
255 vmaCalculateVirtualBlockStats(virtualBlock, reinterpret_cast<VmaStatInfo *>(pStatInfo));
256 }
257
BuildVirtualBlockStatsString(VmaVirtualBlock virtualBlock,char ** ppStatsString,VkBool32 detailedMap)258 void BuildVirtualBlockStatsString(VmaVirtualBlock virtualBlock,
259 char **ppStatsString,
260 VkBool32 detailedMap)
261 {
262 vmaBuildVirtualBlockStatsString(virtualBlock, ppStatsString, detailedMap);
263 }
264
FreeVirtualBlockStatsString(VmaVirtualBlock virtualBlock,char * pStatsString)265 void FreeVirtualBlockStatsString(VmaVirtualBlock virtualBlock, char *pStatsString)
266 {
267 vmaFreeVirtualBlockStatsString(virtualBlock, pStatsString);
268 }
269 } // namespace vma
270