5 releases
0.3.4 | Nov 7, 2023 |
---|---|
0.3.3 | Nov 7, 2023 |
0.3.2 | Nov 7, 2023 |
0.3.1 | Aug 13, 2023 |
0.3.0 | Aug 13, 2023 |
#164 in Graphics APIs
Used in bort-vk
310KB
3K
SLoC
bort-vma
This crate provides an FFI layer and idiomatic rust wrappers for the excellent AMD Vulkan Memory Allocator (VMA) C/C++ library.
This is a fork of vk-mem-rs, originally created by @gwihlidal.
Problem
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:
- It requires a lot of boilerplate code, just like everything else in Vulkan, because it is a low-level and high-performance API.
- There is additional level of indirection: VkDeviceMemory is allocated separately from creating VkBuffer/VkImage and they must be bound together. The binding cannot be changed later - resource must be recreated.
- Driver must be queried for supported memory heaps and memory types. Different IHVs provide different types of it.
- It is recommended practice to allocate bigger chunks of memory and assign parts of them to particular resources.
Features
This crate can help game developers to manage memory allocations and resource creation by offering some higher-level functions:
- 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.
- 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, respects all the rules of alignment and buffer/image granularity.
- Functions that can create an image/buffer, allocate memory for it and bind them together - all in one call.
Additional features:
- Cross-platform
- Windows
- Linux
- macOS (MoltenVK)
- Well tested and documented API
- Underlying library ships in a number of commerical game titles.
- Extensive documentation (including full algorithm descriptions in the VMA repository)
- Support for custom memory pools:
- Create a pool with desired parameters (e.g. fixed or limited maximum size)
- Allocate memory out of it.
- Support for a linear or buddy allocation strategy
- Create a pool with linear algorithm and use it for much faster allocations and deallocations in free-at-once, stack, double stack, or ring buffer fashion.
- Detailed statistics:
- Globally, per memory heap, and per memory type.
- Amount of memory used
- Amount of memory unused
- Number of allocated blocks
- Number of allocations
- etc.
- Debug annotations:
- Associate string with name or opaque pointer to your own data with every allocation.
- JSON dump:
- Obtain a string in JSON format with detailed map of internal state, including list of allocations and gaps between them.
- Convert this JSON dump into a picture to visualize your memory. See tools/VmaDumpVis.
- Support for memory mapping:
- Reference-counted internally.
- Support for persistently mapped memory; just allocate with appropriate flag and you get access to mapped pointer.
- Support for defragmenting allocations:
- Call one function and let the library move data around to free some memory blocks and make your allocations better compacted.
- Support for lost allocations:
- Allocate memory with appropriate flags and let the library remove allocations that are not used for many frames to make room for new ones.
- Support for non-coherent memory and flushing allocations:
nonCoherentAtomSize
is respected automatically.
- Supporting for attempting to detect incorrect mapped memory usage:
- Enable initialization of all allocated memory with a bit pattern to detect usage of uninitialized or freed memory.
- Enable validation of a magic number before and after every allocation to detect out-of-bounds memory corruption.
Example
Basic usage of this crate is very simple; advanced features are optional.
After you create a vk_mem::Allocator
instance, very little code is needed to create a buffer:
// Create the buffer (GPU only, 16KiB in this example)
let create_info = vk_mem::AllocationCreateInfo {
usage: vk_mem::MemoryUsage::GpuOnly,
..Default::default()
};
let (buffer, allocation, allocation_info) = allocator
.create_buffer(
&ash::vk::BufferCreateInfo::builder()
.size(16 * 1024)
.usage(ash::vk::BufferUsageFlags::VERTEX_BUFFER | ash::vk::BufferUsageFlags::TRANSFER_DST)
.build(),
&create_info,
)
.unwrap();
// Do stuff with buffer! (type is ash::vk::Buffer)
// Destroy the buffer
allocator.destroy_buffer(buffer, &allocation).unwrap();
With this one function call (vk_mem::Allocator::create_buffer
):
ash::vk::Buffer
(VkBuffer
) is created.ash::vk::DeviceMemory
(VkDeviceMemory
) block is allocated if needed.- An unused region of the memory block is bound to this buffer.
vk_mem::Allocation
is created that represents memory assigned to this buffer. It can be queried for parameters like Vulkan memory handle and offset.
MoltenVK
For MoltenVK on macOS, you need to have the proper environment variables set. Something like:
export SDK_PATH=/path/to/vulkansdk-macos-1.1.106.0
export DYLD_LIBRARY_PATH=$SDK_PATH/macOS/lib
export VK_ICD_FILENAMES=$SDK_PATH/macOS/etc/vulkan/icd.d/MoltenVK_icd.json
export VK_LAYER_PATH=$SDK_PATH/macOS/etc/vulkan/explicit_layer.d
cargo test
Compiling using MinGW W64
Vulkan Memory Allocator requires C++11 threads. MinGW W64 does not support these by default, so you need to switch to the posix build. For example, on debian you need to run the following:
update-alternatives --set x86_64-w64-mingw32-gcc /usr/bin/x86_64-w64-mingw32-gcc-posix
update-alternatives --set x86_64-w64-mingw32-g++ /usr/bin/x86_64-w64-mingw32-g++-posix
update-alternatives --set i686-w64-mingw32-gcc /usr/bin/i686-w64-mingw32-gcc-posix
update-alternatives --set i686-w64-mingw32-g++ /usr/bin/i686-w64-mingw32-g++-posix
License
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Credits and Special Thanks
- gwihlidal (original author of this crate)
- Adam Sawicki - AMD (Author of C/C++ library)
- Maik Klein (Author of ash - Vulkan rust bindings)
- Johan Andersson (Contributions)
- Patrick Minogue (Contributions)
- Layl Conway (Contributions)
- aloucks (Contributions)
- Henrik Rydgård (Contributions)
- msiglreith (Contributions)
- Maksym Pavlenko (Contributions)
- Brandon Pollack (Contributions)
Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
Contributions are always welcome; please look at the issue tracker to see what known improvements are documented.
Dependencies
~5.5MB
~136K SLoC