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 heap in physical_device.memory_heaps() {
    println!("Heap #{:?} has a capacity of {:?} bytes", heap.id(), 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_types() {
    println!("Memory type belongs to heap #{:?}", ty.heap().id());
    println!("Host-accessible: {:?}", ty.is_host_visible());
    println!("Device-local: {:?}", ty.is_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::alloc().

Here is an example:

use vulkano::memory::DeviceMemory;

// Taking the first memory type for the sake of this example.
let ty = device.physical_device().memory_types().next().unwrap();

let alloc = DeviceMemory::alloc(device.clone(), ty, 1024).expect("Failed to allocate memory");

// The memory is automatically free'd when `alloc` 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 StdMemoryPool that is shared by the Device object is used.

Re-exports

pub use self::pool::MemoryPool;

Modules

Structs

Object that can be used to read or write the content of a MappedDeviceMemory.
Represents memory that has been allocated.
Represents memory that has been allocated and mapped in CPU accessible space.
Represents requirements expressed by the Vulkan implementation when it comes to binding memory to a resource.

Enums

Indicates whether we want to allocate memory for a specific resource, or in a generic way.
Error type returned by functions related to DeviceMemory.

Traits

Trait for types of data that can be mapped.