Module 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!("Property flags: {:?}", ty.property_flags);
}

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(
    device.clone(),
    MemoryAllocateInfo {
        allocation_size: 1024,
        memory_type_index,
        ..Default::default()
    },
)
.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.

Modules§

allocator
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 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.
sparse

Structs§

DeviceAlignment
Vulkan analog of std’s Alignment, stored as a DeviceSize that is guaranteed to be a valid Vulkan alignment.
DeviceMemory
Represents memory that has been allocated from the device.
ExternalMemoryHandleTypes
A set of ExternalMemoryHandleType values.
ExternalMemoryProperties
The properties for exporting or importing external memory, when a buffer or image is created with a specific configuration.
MappedDeviceMemoryDeprecated
Represents device memory that has been mapped in a CPU-accessible space.
MappedMemoryRange
Represents a range of host-mapped DeviceMemory to be invalidated or flushed.
MappingState
Represents the currently host-mapped region of a DeviceMemory block.
MemoryAllocateFlags
Flags specifying additional properties of a device memory allocation.
MemoryAllocateInfo
Parameters to allocate a new DeviceMemory.
MemoryFdProperties
The properties of a Unix file descriptor when it is imported.
MemoryHeap
A memory heap in a physical device.
MemoryHeapFlags
Attributes of a memory heap.
MemoryMapFlags
MemoryMapInfo
Parameters of a memory map operation.
MemoryProperties
Properties of the memory in a physical device.
MemoryPropertyFlags
Properties of a memory type.
MemoryRequirements
Represents requirements expressed by the Vulkan implementation when it comes to binding memory to a resource.
MemoryType
A memory type in a physical device.
MemoryUnmapInfo
Parameters of a memory unmap operation.
ResourceMemory
Memory that can be bound to resources.
TryFromIntError
Error that can happen when trying to convert an integer to a DeviceAlignment.

Enums§

DedicatedAllocation
Indicates a specific resource to allocate memory for.
ExternalMemoryHandleType
A handle type used to export or import memory to/from an external source.
MemoryImportInfo
Parameters to import memory from an external source.