Module vulkano::memory

source ·
Expand description

Device memory allocation and memory pools.

By default, memory allocation is automatically handled by the vulkano library when you create a buffer or an image. But if you want more control, you have the possibility to customise the memory allocation strategy.

Memory types and heaps

A physical device is composed of one or more memory heaps. A memory heap is a pool of memory that can be allocated.

// Enumerating memory heaps.
for (index, heap) in physical_device.memory_properties().memory_heaps.iter().enumerate() {
    println!("Heap #{:?} has a capacity of {:?} bytes", index, heap.size);

However you can’t allocate directly from a memory heap. A memory heap is shared amongst one or multiple memory types, which you can allocate memory from. Each memory type has different characteristics.

A memory type may or may not be visible to the host. In other words, it may or may not be directly writable by the CPU. A memory type may or may not be device-local. A device-local memory type has a much quicker access time from the GPU than a non-device-local type. Note that non-device-local memory types are still accessible by the device, they are just slower.

// Enumerating memory types.
for ty in physical_device.memory_properties().memory_types.iter() {
    println!("Memory type belongs to heap #{:?}", ty.heap_index);
    println!("Host-accessible: {:?}", ty.property_flags.host_visible);
    println!("Device-local: {:?}", ty.property_flags.device_local);

Memory types are order from “best” to “worse”. In other words, the implementation prefers that you use the memory types that are earlier in the list. This means that selecting a memory type should always be done by enumerating them and taking the first one that matches our criteria.

In practice

In practice, desktop machines usually have two memory heaps: one that represents the RAM of the CPU, and one that represents the RAM of the GPU. The CPU’s RAM is host-accessible but not device-local, while the GPU’s RAM is not host-accessible but is device-local.

Mobile machines usually have a single memory heap that is “equally local” to both the CPU and the GPU. It is both host-accessible and device-local.

Allocating memory and memory pools

Allocating memory can be done by calling DeviceMemory::allocate().

Here is an example:

use vulkano::memory::{DeviceMemory, MemoryAllocateInfo};

// Taking the first memory type for the sake of this example.
let memory_type_index = 0;

let memory = DeviceMemory::allocate(
    MemoryAllocateInfo {
        allocation_size: 1024,
).expect("Failed to allocate memory");

// The memory is automatically freed when `memory` is destroyed.

However allocating and freeing memory is very slow (up to several hundred milliseconds sometimes). Instead you are strongly encouraged to use a memory pool. A memory pool is not a Vulkan concept but a vulkano concept.

A memory pool is any object that implements the MemoryPool trait. You can implement that trait on your own structure and then use it when you create buffers and images so that they get memory from that pool. By default if you don’t specify any pool when creating a buffer or an image, an instance of StandardMemoryPool that is shared by the Device object is used.


In Vulkan, suballocation of DeviceMemory is left to the application, because every application has slightly different needs and one can not incorporate an allocator into the driver that would perform well in all cases. Vulkano stays true to this sentiment, but aims to reduce the burden on the user as much as possible. You have a toolbox of configurable suballocators to choose from that cover all allocation algorithms, which you can compose into any kind of hierarchy you wish. This way you have maximum flexibility while still only using a few DeviceMemory blocks and not writing any of the very error-prone code.


Parameters to execute sparse bind operations on a queue.
Represents memory that has been allocated from the device.
A mask of multiple handle types.
The properties for exporting or importing external memory, when a buffer or image is created with a specific configuration.
Represents device memory that has been mapped in a CPU-accessible space.
A mask specifying flags for device memory allocation.
Parameters to allocate a new DeviceMemory.
A memory heap in a physical device.
Attributes of a memory heap.
Properties of the memory in a physical device.
Properties of a memory type.
Represents requirements expressed by the Vulkan implementation when it comes to binding memory to a resource.
A memory type in a physical device.
Parameters for a single sparse bind operation on a buffer.
Parameters for a single sparse bind operation on parts of an image with a known memory layout.
Parameters for a single sparse bind operation on parts of an image with an opaque memory layout.


Indicates a specific resource to allocate memory for.
Error type returned by functions related to DeviceMemory.
Describes a handle type used for Vulkan external memory apis. This is not just a suggestion. Check out vkExternalMemoryHandleTypeFlagBits in the Vulkan spec.
Parameters to import memory from an external source.
Error type returned by functions related to DeviceMemory.