5个版本

0.3.4 2023年11月7日
0.3.3 2023年11月7日
0.3.2 2023年11月7日
0.3.1 2023年8月13日
0.3.0 2023年8月13日

#10 in 渲染引擎

Download history 6/week @ 2024-03-28 5/week @ 2024-04-04 1/week @ 2024-04-25

60 每月下载量
用于 bort-vk

MIT/Apache

310KB
3K SLoC

bort-vma

MIT APACHE2

此crate提供对优秀的AMD Vulkan内存分配器(VMA)C/C++库的FFI层和惯用Rust包装。

这是对vk-mem-rs的分支,最初由@gwihlidal创建。

问题

Vulkan中的内存分配和资源(缓冲区和图像)创建很困难(与较旧的图形API相比,如D3D11或OpenGL),原因有几个

  • 它需要大量的样板代码,就像Vulkan中的其他一切一样,因为它是一个低级和高性能的API。
  • 存在额外的间接层:VkDeviceMemory是独立于创建VkBuffer/VkImage分配的,并且它们必须绑定在一起。绑定不能更改——资源必须重新创建。
  • 必须查询驱动程序以获取支持的内存堆和内存类型。不同的IHVs提供不同类型的内存。
  • 建议分配较大的内存块,并将它们的部分分配给特定资源。

功能

此crate可以通过提供一些高级函数来帮助游戏开发者管理内存分配和资源创建

  • 帮助根据内存的预期使用选择正确和最优内存类型的函数。
    • 使用比Vulkan标志更高层次描述来表示内存所需或首选的特性。
  • 分配内存块、预留并返回它们的部分(VkDeviceMemory + 偏移量 + 大小)给用户的函数。
    • 库跟踪分配的内存块、它们内部已用和未用范围,为新分配找到最佳匹配的未用范围,并尊重所有对齐和缓冲区/图像粒度的规则。
  • 可以创建图像/缓冲区、为其分配内存并将它们一起绑定的函数——所有这些都在一个调用中完成。

附加功能

  • 跨平台
    • Windows
    • Linux
    • macOS (MoltenVK)
  • 经过良好测试和文档化的API
    • 底层库已在多个商业游戏标题中发货。
    • 详细的文档(包括VMA存储库中的完整算法描述)
  • 支持自定义内存池
    • 创建具有所需参数的池(例如,固定或有限的最大大小)
    • 从其中分配内存。
    • 支持线性或伙伴分配策略
    • 创建具有线性算法的池,并用于一次性、堆栈、双堆栈或环形缓冲区的快速分配和释放。
  • 详细统计信息
    • 全局、每个内存堆和每个内存类型。
    • 使用的内存量
    • 未使用的内存量
    • 已分配块的数量
    • 分配的数量
    • 等。
  • 调试注释
    • 将字符串与名称或与您的自定义数据关联的不可见指针与每次分配相关联。
  • JSON转储
    • 获取包含内部状态的详细映射的JSON格式的字符串,包括分配列表及其之间的间隔。
    • 将此JSON转储转换为图片以可视化您的内存。请参阅工具/VmaDumpVis
  • 支持内存映射
    • 内部使用引用计数。
    • 支持持久映射内存;只需使用适当的标志分配,即可获取映射指针的访问权限。
  • 支持分配碎片化
    • 调用一个函数,让库移动数据以释放一些内存块,并使您的分配更紧凑。
  • 支持丢失的分配
    • 使用适当的标志分配内存,并让库删除长时间未使用的分配,为新分配腾出空间。
  • 支持非一致内存和刷新分配
    • nonCoherentAtomSize将被自动尊重。
  • 支持尝试检测错误的映射内存使用
    • 启用使用位模式初始化所有分配的内存,以检测未初始化或已释放的内存的使用。
    • 在每次分配前后启用验证魔数,以检测越界内存损坏。

示例

此crate的基本用法非常简单;高级功能是可选的。

创建vk_mem::Allocator实例后,创建缓冲区所需的代码很少。

// 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();

使用此一个函数调用(vk_mem::Allocator::create_buffer

  • ash::vk::Buffer(《VkBuffer》)被创建。
  • 如果需要,将分配ash::vk::DeviceMemory(《VkDeviceMemory》)块。
  • 内存块未使用区域绑定到该缓冲区。
  • 创建vk_mem::Allocation,它表示分配给该缓冲区的内存。它可以查询如Vulkan内存句柄和偏移量等参数。

MoltenVK

对于macOS上的MoltenVK,您需要设置正确的环境变量。例如

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

使用MinGW W64编译

Vulkan Memory Allocator需要C++11线程。MinGW W64默认不支持这些,因此您需要切换到posix构建。例如,在debian上,您需要运行以下命令

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

许可证

根据以下任一项许可

任你选择。

致谢与特别感谢

贡献

除非你明确表示,否则根据Apache-2.0许可证定义的,任何有意提交以包含在此crate中的贡献,都应按上述方式双许可,不附加任何额外条款或条件。

欢迎贡献;请查看问题跟踪器以了解已记录的已知改进。

依赖关系

~5.5MB
~133K SLoC