#内存分配器 #内存块 #内存 #内存池 #内存管理 #vulkan #vulkan-bindings

无需std vk-mem-vulkanalia

Rust对AMD Vulkan内存分配器(VMA)的ffi绑定和惯用包装,使用vulkanalia而不是ash。是vk-mem的分支。

1个不稳定版本

0.1.0+vk-mem-0.4.02024年5月27日

#13 in 渲染引擎

MIT/Apache

1.5MB
2.5K SLoC

vk-mem-vulkanalia

Latest version Documentation MIT APACHE2

此crate是使用vulkanalia(而不是ash)代替vk-mem的分支。它提供了AMD Vulkan内存分配器(VMA) C/C++库的FFI层和惯用的Rust包装。

问题

在Vulkan中,由于多个原因,内存分配和资源(缓冲区和图像)创建相对较难(与较老的图形API,如D3D11或OpenGL相比)

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

功能

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

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

附加功能

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

计划中的功能

  • 广泛的单元测试和示例。
    • 已经有一些单元测试,但尚未全面覆盖
    • 示例尚未编写 - 很可能将VMA示例移植到ashvk_mem
  • 记录和重放分配,以深入了解内存使用、资源转换等
    • 检查正确性、测量性能和收集统计数据。

示例

此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

使用方法

将此添加到您的Cargo.toml

[dependencies]
vk-mem = "0.3.0"

并将其添加到您的crate根目录

extern crate vk_mem;

使用MinGW W64进行编译

Vulkan内存分配器需要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

许可证

根据以下任一许可证授权:

任选其一。

鸣谢与特别感谢

贡献

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

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

行为准则

vk-mem crate的贡献按照贡献者公约进行组织,vk-mem的维护者@Neo-Zhixing承诺将介入以维护该行为准则。

依赖关系

~6–11MB
~163K SLoC