2个版本
0.4.0 |
|
---|---|
0.3.1 | 2023年7月4日 |
0.3.0 | 2023年5月27日 |
#26 in 渲染引擎
310KB
3K SLoC
vk-mem
这是一个由@gwihlidal创建的vk-mem-rs的分支,它最初发布在crates.io上,名称为vma
。
此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转储转换为图片以可视化您的内存。请参阅tools/VmaDumpVis。
- 支持内存映射
- 内部引用计数。
- 支持持久映射内存;只需使用适当的标志进行分配,即可获得映射指针的访问权限。
- 支持碎片化分配
- 调用一个函数,让库移动数据,以释放一些内存块并使您的分配更紧凑。
- 支持丢失的分配
- 使用适当的标志分配内存,并让库删除长时间未使用的分配,为新分配腾出空间。
- 支持非一致性内存和刷新分配
nonCoherentAtomSize
自动受到尊重。
- 尝试检测不正确的映射内存使用
- 启用对所有分配的内存进行位模式初始化,以检测未初始化或已释放内存的使用。
- 在每次分配前后启用验证魔数,以检测越界内存损坏。
计划中的功能
- 广泛的单元测试和示例。
- 一些单元测试,但不是全覆盖
- 示例尚未编写 - 很可能将VMA示例迁移到
ash
和vk_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]
vma = "0.4.0"
并将其添加到您的crate根目录下
extern crate vma;
使用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 License,版本2.0(LICENSE-APACHE 或 http://www.apache.org/licenses/LICENSE-2.0)
- MIT许可证(LICENSE-MIT 或 http://opensource.org/licenses/MIT)
任选其一。
致谢及特别感谢
- Adam Sawicki - AMD(C/C++库的作者)
- Maik Klein(ash - Vulkan rust绑定的作者)
- Johan Andersson(贡献)
- Patrick Minogue(贡献)
- Layl Conway(贡献)
- aloucks(贡献)
- Henrik Rydgård(贡献)
- msiglreith(贡献)
- Maksym Pavlenko(贡献)
- Brandon Pollack(贡献)
贡献
除非您明确说明,否则您根据Apache-2.0许可证提交的任何有意包含在此crate中的贡献,应如上所述双许可,无需任何附加条款或条件。
欢迎贡献;请查看问题跟踪器了解已记录的已知改进。
行为准则
根据贡献者公约组织对vma crate的贡献,vk-mem的维护者@Neo-Zhixing承诺将介入以维护该行为准则。
依赖项
~5.5MB
~133K SLoC