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 #if ANGLE_VMA_VERSION < 3000000
22 VALIDATE_BLOCK_CREATE_FLAG_BITS(BUDDY);
23 #endif // ANGLE_VMA_VERSION < 3000000
24
InitAllocator(VkPhysicalDevice physicalDevice,VkDevice device,VkInstance instance,uint32_t apiVersion,VkDeviceSize preferredLargeHeapBlockSize,VmaAllocator * pAllocator)25 VkResult InitAllocator(VkPhysicalDevice physicalDevice,
26 VkDevice device,
27 VkInstance instance,
28 uint32_t apiVersion,
29 VkDeviceSize preferredLargeHeapBlockSize,
30 VmaAllocator *pAllocator)
31 {
32 VmaVulkanFunctions funcs = {};
33 funcs.vkGetPhysicalDeviceProperties = vkGetPhysicalDeviceProperties;
34 funcs.vkGetPhysicalDeviceMemoryProperties = vkGetPhysicalDeviceMemoryProperties;
35 funcs.vkAllocateMemory = vkAllocateMemory;
36 funcs.vkFreeMemory = vkFreeMemory;
37 funcs.vkMapMemory = vkMapMemory;
38 funcs.vkUnmapMemory = vkUnmapMemory;
39 funcs.vkFlushMappedMemoryRanges = vkFlushMappedMemoryRanges;
40 funcs.vkInvalidateMappedMemoryRanges = vkInvalidateMappedMemoryRanges;
41 funcs.vkBindBufferMemory = vkBindBufferMemory;
42 funcs.vkBindImageMemory = vkBindImageMemory;
43 funcs.vkGetBufferMemoryRequirements = vkGetBufferMemoryRequirements;
44 funcs.vkGetImageMemoryRequirements = vkGetImageMemoryRequirements;
45 funcs.vkCreateBuffer = vkCreateBuffer;
46 funcs.vkDestroyBuffer = vkDestroyBuffer;
47 funcs.vkCreateImage = vkCreateImage;
48 funcs.vkDestroyImage = vkDestroyImage;
49 funcs.vkCmdCopyBuffer = vkCmdCopyBuffer;
50 {
51 #if !defined(ANGLE_SHARED_LIBVULKAN)
52 // When the vulkan-loader is statically linked, we need to use the extension
53 // functions defined in ANGLE's rx namespace. When it's dynamically linked
54 // with volk, this will default to the function definitions with no namespace
55 using rx::vkBindBufferMemory2KHR;
56 using rx::vkBindImageMemory2KHR;
57 using rx::vkGetBufferMemoryRequirements2KHR;
58 using rx::vkGetImageMemoryRequirements2KHR;
59 using rx::vkGetPhysicalDeviceMemoryProperties2KHR;
60 #endif // !defined(ANGLE_SHARED_LIBVULKAN)
61 funcs.vkGetBufferMemoryRequirements2KHR = vkGetBufferMemoryRequirements2KHR;
62 funcs.vkGetImageMemoryRequirements2KHR = vkGetImageMemoryRequirements2KHR;
63 funcs.vkBindBufferMemory2KHR = vkBindBufferMemory2KHR;
64 funcs.vkBindImageMemory2KHR = vkBindImageMemory2KHR;
65 funcs.vkGetPhysicalDeviceMemoryProperties2KHR = vkGetPhysicalDeviceMemoryProperties2KHR;
66 }
67
68 VmaAllocatorCreateInfo allocatorInfo = {};
69 allocatorInfo.physicalDevice = physicalDevice;
70 allocatorInfo.device = device;
71 allocatorInfo.instance = instance;
72 allocatorInfo.pVulkanFunctions = &funcs;
73 allocatorInfo.vulkanApiVersion = apiVersion;
74 allocatorInfo.preferredLargeHeapBlockSize = preferredLargeHeapBlockSize;
75
76 return vmaCreateAllocator(&allocatorInfo, pAllocator);
77 }
78
DestroyAllocator(VmaAllocator allocator)79 void DestroyAllocator(VmaAllocator allocator)
80 {
81 vmaDestroyAllocator(allocator);
82 }
83
CreatePool(VmaAllocator allocator,uint32_t memoryTypeIndex,bool buddyAlgorithm,VkDeviceSize blockSize,VmaPool * pPool)84 VkResult CreatePool(VmaAllocator allocator,
85 uint32_t memoryTypeIndex,
86 #if ANGLE_VMA_VERSION < 3000000
87 bool buddyAlgorithm,
88 #endif // ANGLE_VMA_VERSION < 3000000
89 VkDeviceSize blockSize,
90 VmaPool *pPool)
91 {
92 VmaPoolCreateInfo poolCreateInfo = {};
93 poolCreateInfo.memoryTypeIndex = memoryTypeIndex;
94 poolCreateInfo.flags = VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT;
95 #if ANGLE_VMA_VERSION < 3000000
96 if (buddyAlgorithm)
97 {
98 poolCreateInfo.flags |= VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT;
99 }
100 #endif
101 poolCreateInfo.blockSize = blockSize;
102 poolCreateInfo.maxBlockCount = -1; // unlimited
103 return vmaCreatePool(allocator, &poolCreateInfo, pPool);
104 }
105
DestroyPool(VmaAllocator allocator,VmaPool pool)106 void DestroyPool(VmaAllocator allocator, VmaPool pool)
107 {
108 vmaDestroyPool(allocator, pool);
109 }
110
FreeMemory(VmaAllocator allocator,VmaAllocation allocation)111 void FreeMemory(VmaAllocator allocator, VmaAllocation allocation)
112 {
113 vmaFreeMemory(allocator, allocation);
114 }
115
CreateBuffer(VmaAllocator allocator,const VkBufferCreateInfo * pBufferCreateInfo,VkMemoryPropertyFlags requiredFlags,VkMemoryPropertyFlags preferredFlags,bool persistentlyMapped,uint32_t * pMemoryTypeIndexOut,VkBuffer * pBuffer,VmaAllocation * pAllocation)116 VkResult CreateBuffer(VmaAllocator allocator,
117 const VkBufferCreateInfo *pBufferCreateInfo,
118 VkMemoryPropertyFlags requiredFlags,
119 VkMemoryPropertyFlags preferredFlags,
120 bool persistentlyMapped,
121 uint32_t *pMemoryTypeIndexOut,
122 VkBuffer *pBuffer,
123 VmaAllocation *pAllocation)
124 {
125 VkResult result;
126 VmaAllocationCreateInfo allocationCreateInfo = {};
127 allocationCreateInfo.requiredFlags = requiredFlags;
128 allocationCreateInfo.preferredFlags = preferredFlags;
129 allocationCreateInfo.flags = (persistentlyMapped) ? VMA_ALLOCATION_CREATE_MAPPED_BIT : 0;
130 VmaAllocationInfo allocationInfo = {};
131
132 result = vmaCreateBuffer(allocator, pBufferCreateInfo, &allocationCreateInfo, pBuffer,
133 pAllocation, &allocationInfo);
134 *pMemoryTypeIndexOut = allocationInfo.memoryType;
135
136 return result;
137 }
138
AllocateAndBindMemoryForImage(VmaAllocator allocator,VkImage * pImage,VkMemoryPropertyFlags requiredFlags,VkMemoryPropertyFlags preferredFlags,bool allocateDedicatedMemory,VmaAllocation * pAllocationOut,uint32_t * pMemoryTypeIndexOut,VkDeviceSize * sizeOut)139 VkResult AllocateAndBindMemoryForImage(VmaAllocator allocator,
140 VkImage *pImage,
141 VkMemoryPropertyFlags requiredFlags,
142 VkMemoryPropertyFlags preferredFlags,
143 bool allocateDedicatedMemory,
144 VmaAllocation *pAllocationOut,
145 uint32_t *pMemoryTypeIndexOut,
146 VkDeviceSize *sizeOut)
147 {
148 VkResult result;
149 VmaAllocationCreateInfo allocationCreateInfo = {};
150 allocationCreateInfo.requiredFlags = requiredFlags;
151 allocationCreateInfo.preferredFlags = preferredFlags;
152 allocationCreateInfo.flags =
153 allocateDedicatedMemory ? VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT : 0;
154 VmaAllocationInfo allocationInfo = {};
155
156 result = vmaAllocateMemoryForImage(allocator, *pImage, &allocationCreateInfo, pAllocationOut,
157 &allocationInfo);
158 if (result == VK_SUCCESS)
159 {
160 // If binding was unsuccessful, we should free the allocation.
161 result = vmaBindImageMemory(allocator, *pAllocationOut, *pImage);
162 if (result != VK_SUCCESS)
163 {
164 vmaFreeMemory(allocator, *pAllocationOut);
165 *pAllocationOut = VK_NULL_HANDLE;
166 return result;
167 }
168
169 *pMemoryTypeIndexOut = allocationInfo.memoryType;
170 *sizeOut = allocationInfo.size;
171 }
172
173 return result;
174 }
175
FindMemoryTypeIndexForBufferInfo(VmaAllocator allocator,const VkBufferCreateInfo * pBufferCreateInfo,VkMemoryPropertyFlags requiredFlags,VkMemoryPropertyFlags preferredFlags,bool persistentlyMappedBuffers,uint32_t * pMemoryTypeIndexOut)176 VkResult FindMemoryTypeIndexForBufferInfo(VmaAllocator allocator,
177 const VkBufferCreateInfo *pBufferCreateInfo,
178 VkMemoryPropertyFlags requiredFlags,
179 VkMemoryPropertyFlags preferredFlags,
180 bool persistentlyMappedBuffers,
181 uint32_t *pMemoryTypeIndexOut)
182 {
183 VmaAllocationCreateInfo allocationCreateInfo = {};
184 allocationCreateInfo.requiredFlags = requiredFlags;
185 allocationCreateInfo.preferredFlags = preferredFlags;
186 allocationCreateInfo.flags = (persistentlyMappedBuffers) ? VMA_ALLOCATION_CREATE_MAPPED_BIT : 0;
187
188 return vmaFindMemoryTypeIndexForBufferInfo(allocator, pBufferCreateInfo, &allocationCreateInfo,
189 pMemoryTypeIndexOut);
190 }
191
FindMemoryTypeIndexForImageInfo(VmaAllocator allocator,const VkImageCreateInfo * pImageCreateInfo,VkMemoryPropertyFlags requiredFlags,VkMemoryPropertyFlags preferredFlags,bool allocateDedicatedMemory,uint32_t * pMemoryTypeIndexOut)192 VkResult FindMemoryTypeIndexForImageInfo(VmaAllocator allocator,
193 const VkImageCreateInfo *pImageCreateInfo,
194 VkMemoryPropertyFlags requiredFlags,
195 VkMemoryPropertyFlags preferredFlags,
196 bool allocateDedicatedMemory,
197 uint32_t *pMemoryTypeIndexOut)
198 {
199 VmaAllocationCreateInfo allocationCreateInfo = {};
200 allocationCreateInfo.requiredFlags = requiredFlags;
201 allocationCreateInfo.preferredFlags = preferredFlags;
202 allocationCreateInfo.flags =
203 allocateDedicatedMemory ? VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT : 0;
204
205 return vmaFindMemoryTypeIndexForImageInfo(allocator, pImageCreateInfo, &allocationCreateInfo,
206 pMemoryTypeIndexOut);
207 }
208
GetMemoryTypeProperties(VmaAllocator allocator,uint32_t memoryTypeIndex,VkMemoryPropertyFlags * pFlags)209 void GetMemoryTypeProperties(VmaAllocator allocator,
210 uint32_t memoryTypeIndex,
211 VkMemoryPropertyFlags *pFlags)
212 {
213 vmaGetMemoryTypeProperties(allocator, memoryTypeIndex, pFlags);
214 }
215
MapMemory(VmaAllocator allocator,VmaAllocation allocation,void ** ppData)216 VkResult MapMemory(VmaAllocator allocator, VmaAllocation allocation, void **ppData)
217 {
218 return vmaMapMemory(allocator, allocation, ppData);
219 }
220
UnmapMemory(VmaAllocator allocator,VmaAllocation allocation)221 void UnmapMemory(VmaAllocator allocator, VmaAllocation allocation)
222 {
223 return vmaUnmapMemory(allocator, allocation);
224 }
225
FlushAllocation(VmaAllocator allocator,VmaAllocation allocation,VkDeviceSize offset,VkDeviceSize size)226 void FlushAllocation(VmaAllocator allocator,
227 VmaAllocation allocation,
228 VkDeviceSize offset,
229 VkDeviceSize size)
230 {
231 vmaFlushAllocation(allocator, allocation, offset, size);
232 }
233
InvalidateAllocation(VmaAllocator allocator,VmaAllocation allocation,VkDeviceSize offset,VkDeviceSize size)234 void InvalidateAllocation(VmaAllocator allocator,
235 VmaAllocation allocation,
236 VkDeviceSize offset,
237 VkDeviceSize size)
238 {
239 vmaInvalidateAllocation(allocator, allocation, offset, size);
240 }
241
BuildStatsString(VmaAllocator allocator,char ** statsString,VkBool32 detailedMap)242 void BuildStatsString(VmaAllocator allocator, char **statsString, VkBool32 detailedMap)
243 {
244 vmaBuildStatsString(allocator, statsString, detailedMap);
245 }
246
FreeStatsString(VmaAllocator allocator,char * statsString)247 void FreeStatsString(VmaAllocator allocator, char *statsString)
248 {
249 vmaFreeStatsString(allocator, statsString);
250 }
251
252 // VmaVirtualBlock implementation
CreateVirtualBlock(VkDeviceSize size,VirtualBlockCreateFlags flags,VmaVirtualBlock * pVirtualBlock)253 VkResult CreateVirtualBlock(VkDeviceSize size,
254 VirtualBlockCreateFlags flags,
255 VmaVirtualBlock *pVirtualBlock)
256 {
257 VmaVirtualBlockCreateInfo virtualBlockCreateInfo = {};
258 virtualBlockCreateInfo.size = size;
259 virtualBlockCreateInfo.flags = (VmaVirtualBlockCreateFlagBits)flags;
260 return vmaCreateVirtualBlock(&virtualBlockCreateInfo, pVirtualBlock);
261 }
262
DestroyVirtualBlock(VmaVirtualBlock virtualBlock)263 void DestroyVirtualBlock(VmaVirtualBlock virtualBlock)
264 {
265 vmaDestroyVirtualBlock(virtualBlock);
266 }
267
VirtualAllocate(VmaVirtualBlock virtualBlock,VkDeviceSize size,VkDeviceSize alignment,VmaVirtualAllocation * pAllocation,VkDeviceSize * pOffset)268 VkResult VirtualAllocate(VmaVirtualBlock virtualBlock,
269 VkDeviceSize size,
270 VkDeviceSize alignment,
271 VmaVirtualAllocation *pAllocation,
272 VkDeviceSize *pOffset)
273 {
274 VmaVirtualAllocationCreateInfo createInfo = {};
275 createInfo.size = size;
276 createInfo.alignment = alignment;
277 createInfo.flags = 0;
278 #if ANGLE_VMA_VERSION < 3000000
279 return vmaVirtualAllocate(virtualBlock, &createInfo, pOffset);
280 #else
281 return vmaVirtualAllocate(virtualBlock, &createInfo, pAllocation, pOffset);
282 #endif // ANGLE_VMA_VERSION < 3000000
283 }
284
VirtualFree(VmaVirtualBlock virtualBlock,VmaVirtualAllocation allocation,VkDeviceSize offset)285 void VirtualFree(VmaVirtualBlock virtualBlock, VmaVirtualAllocation allocation, VkDeviceSize offset)
286 {
287 #if ANGLE_VMA_VERSION < 3000000
288 vmaVirtualFree(virtualBlock, offset);
289 #else
290 vmaVirtualFree(virtualBlock, allocation);
291 #endif // ANGLE_VMA_VERSION < 3000000
292 }
293
IsVirtualBlockEmpty(VmaVirtualBlock virtualBlock)294 VkBool32 IsVirtualBlockEmpty(VmaVirtualBlock virtualBlock)
295 {
296 return vmaIsVirtualBlockEmpty(virtualBlock);
297 }
298
GetVirtualAllocationInfo(VmaVirtualBlock virtualBlock,VmaVirtualAllocation allocation,VkDeviceSize offset,VkDeviceSize * sizeOut,void ** pUserDataOut)299 void GetVirtualAllocationInfo(VmaVirtualBlock virtualBlock,
300 VmaVirtualAllocation allocation,
301 VkDeviceSize offset,
302 VkDeviceSize *sizeOut,
303 void **pUserDataOut)
304 {
305 VmaVirtualAllocationInfo virtualAllocInfo = {};
306 #if ANGLE_VMA_VERSION < 3000000
307 vmaGetVirtualAllocationInfo(virtualBlock, offset, &virtualAllocInfo);
308 #else
309 vmaGetVirtualAllocationInfo(virtualBlock, allocation, &virtualAllocInfo);
310 #endif // ANGLE_VMA_VERSION < 3000000
311 *sizeOut = virtualAllocInfo.size;
312 *pUserDataOut = virtualAllocInfo.pUserData;
313 }
314
ClearVirtualBlock(VmaVirtualBlock virtualBlock)315 void ClearVirtualBlock(VmaVirtualBlock virtualBlock)
316 {
317 vmaClearVirtualBlock(virtualBlock);
318 }
319
SetVirtualAllocationUserData(VmaVirtualBlock virtualBlock,VmaVirtualAllocation allocation,VkDeviceSize offset,void * pUserData)320 void SetVirtualAllocationUserData(VmaVirtualBlock virtualBlock,
321 VmaVirtualAllocation allocation,
322 VkDeviceSize offset,
323 void *pUserData)
324 {
325 #if ANGLE_VMA_VERSION < 3000000
326 vmaSetVirtualAllocationUserData(virtualBlock, offset, pUserData);
327 #else
328 vmaSetVirtualAllocationUserData(virtualBlock, allocation, pUserData);
329 #endif // ANGLE_VMA_VERSION < 3000000
330 }
331
CalculateVirtualBlockStats(VmaVirtualBlock virtualBlock,StatInfo * pStatInfo)332 void CalculateVirtualBlockStats(VmaVirtualBlock virtualBlock, StatInfo *pStatInfo)
333 {
334 #if ANGLE_VMA_VERSION < 3000000
335 vmaCalculateVirtualBlockStats(virtualBlock, reinterpret_cast<VmaStatInfo *>(pStatInfo));
336 #else
337 vmaCalculateVirtualBlockStatistics(virtualBlock,
338 reinterpret_cast<VmaDetailedStatistics *>(pStatInfo));
339 #endif // ANGLE_VMA_VERSION < 3000000
340 }
341
BuildVirtualBlockStatsString(VmaVirtualBlock virtualBlock,char ** ppStatsString,VkBool32 detailedMap)342 void BuildVirtualBlockStatsString(VmaVirtualBlock virtualBlock,
343 char **ppStatsString,
344 VkBool32 detailedMap)
345 {
346 vmaBuildVirtualBlockStatsString(virtualBlock, ppStatsString, detailedMap);
347 }
348
FreeVirtualBlockStatsString(VmaVirtualBlock virtualBlock,char * pStatsString)349 void FreeVirtualBlockStatsString(VmaVirtualBlock virtualBlock, char *pStatsString)
350 {
351 vmaFreeVirtualBlockStatsString(virtualBlock, pStatsString);
352 }
353 } // namespace vma
354