#内存分配器 #内存 #内存池 #空闲内存 #内存块 #内存管理 #Vulkan

vk-mem-erupt

Rust ffi 绑定和 erupt 使用的 AMD Vulkan 内存分配器 (VMA) 习惯用法包装

2 个版本

0.2.4 2021 年 10 月 25 日
0.2.3 2021 年 7 月 23 日

#266 in 图形 API

MIT/Apache

305KB
4.5K SLoC

vk-mem-erupt

vk-mem on travis-ci.com Latest version Documentation Lines of Code MIT APACHE2

这是 Graham Wihlidal 的 vk-mem-rs 的分支,但使用 erupt 而不是 ash 进行 Vulkan 绑定。 因此,这个 crate 上的所有工作都是由 Graham Wihlidal 和 VMA 库背后的团队完成的。我只是修改了 crate,使其可以与 erupt Vulkan 绑定一起使用。

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

问题

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

  • 它需要大量的模板代码,就像 Vulkan 中的所有其他东西一样,因为它是一个低级和高性能 API。
  • 存在额外的间接层: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.2.3"

并将以下内容添加到您的 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

许可证

许可协议为以下之一:

任选其一。

致谢和特别感谢

贡献

除非您明确说明,否则您根据 Apache-2.0 许可协议提交的任何有意包含在此 crate 中的贡献,将按上述方式双许可,不附加任何其他条款或条件。

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

行为准则

对 vk-mem crate 的贡献是在贡献者协约的条款下组织的,vk-mem 的维护者 @gwihlidal 承诺将介入以维护该行为准则。

依赖项

~6.5MB
~152K SLoC