Vulkan Memory Allocator
Vulkan Memory Allocator

Version 1.0.0 (2017-06-16)

Members grouped: see Modules.

All members: see vk_mem_alloc.h.

Problem Statement

Memory allocation and resource (buffer and image) creation in Vulkan is difficult (comparing to older graphics API-s, like D3D11 or OpenGL) for several reasons:

Features

This library is helps game developers to manage memory allocations and resource creation by offering some higher-level functions. Features of the library could be divided into several layers, low level to high level:

  1. Functions that help to choose correct and optimal memory type based on intended usage of the memory.
    • Required or preferred traits of the memory are expressed using higher-level description comparing to Vulkan flags.
  2. Functions that allocate memory blocks, reserve and return parts of them (VkDeviceMemory + offset + size) to the user.
    • Library keeps track of allocated memory blocks, used and unused ranges inside them, finds best matching unused ranges for new allocations, takes all the rules of alignment into consideration.
  3. Functions that can create an image/buffer, allocate memory for it and bind them together - all in one call.

Prequisites

Quick Start

In your project code:

  1. Include "vk_mem_alloc.h" file wherever you want to use the library.
  2. In exacly one C++ file define following macro before include to build library implementation.
#define VMA_IMPLEMENTATION
#include "vk_mem_alloc.h"

At program startup:

  1. Initialize Vulkan to have VkPhysicalDevice and VkDevice object.
  2. Fill VmaAllocatorCreateInfo structure and create VmaAllocator object by calling vmaCreateAllocator().
VmaAllocatorCreateInfo allocatorInfo = {};
allocatorInfo.physicalDevice = physicalDevice;
allocatorInfo.device = device;

VmaAllocator allocator;
vmaCreateAllocator(&allocatorInfo, &allocator);

When you want to create a buffer or image:

  1. Fill VkBufferCreateInfo / VkImageCreateInfo structure.
  2. Fill VmaMemoryRequirements structure.
  3. Call vmaCreateBuffer() / vmaCreateImage() to get VkBuffer/VkImage with memory already allocated and bound to it.
VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
bufferInfo.size = myBufferSize;
bufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;

VmaMemoryRequirements memReq = {};
memReq.usage = VMA_MEMORY_USAGE_GPU_ONLY;

VkBuffer buffer;
vmaCreateBuffer(allocator, &bufferInfo, &memReq, &buffer, nullptr, nullptr);

When no longer needed, destroy your buffer or image using vmaDestroyBuffer() / vmaDestroyImage(). This function would also free memory bound to it.

vmaDestroyBuffer(allocator, buffer);

Configuration

Set VMA_STATS_STRING_ENABLED macro in vk_mem_alloc.h to 0 or 1 to disable/enable compilation of code for dumping internal allocator state to string in JSON format.

Please check "CONFIGURATION" section in vk_mem_alloc.cpp file to find macros and other definitions that you can change to connect the library to your own implementation of basic facilities like assert, min and max functions, mutex etc. C++ STL is used by default, but changing these allows you to get rid of any STL usage if you want, as many game developers tend to do.

Custom memory allocator

You can use custom memory allocator by filling optional member VmaAllocatorCreateInfo::pAllocationCallbacks. These functions will be passed to Vulkan, as well as used by the library itself to make any CPU-side allocations.

Thread safety

All calls to functions that take VmaAllocator as first parameter are safe to call from multiple threads simultaneously, synchronized internally when needed.