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

vk-mem-3-erupt

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

4个版本 (破坏性更新)

0.6.0+708428c2-2023-02-022023年2月10日
0.5.0+3.0.1 2023年2月10日
0.4.0+3.0.1 2022年10月31日
0.3.0+3.0.1 2022年10月30日

#24 in 渲染引擎

MIT/Apache

385KB
5K SLoC

vk-mem-3-erupt

如果这个crate已过时且我尚未更新,请提交一个问题/PR。

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相比)

  • 因为它是一个低级且高性能的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-3-erupt = "0.4.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

许可协议

根据以下任一协议授权:

根据您的选择。

致谢与特别感谢

贡献

除非您明确声明,否则根据Apache-2.0许可证定义的您有意提交以包含在此crate中的任何贡献,都应如上双授权,没有额外的条款或条件。

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

行为准则

vk-mem crate的贡献根据贡献者誓言组织,vk-mem的维护者@gwihlidal承诺将介入以维护该行为准则。

依赖关系

~6.5MB
~152K SLoC