#内存 #内存管理 #Vulkan #GPU #物理内存 #图形 #渲染

nobs-vkmem

nobs-vk 的 Vulkan 内存管理扩展

2 个不稳定版本

0.2.0 2019 年 2 月 24 日
0.1.0 2019 年 2 月 3 日

#377图形 API


2 个 Crates 中使用(通过 nobs-vulkanism-headless

MIT 许可证

1MB
16K SLoC

nobs-vkmem

作为 nobs-vk 的扩展提供 Vulkan 内存管理。

动机

与例如 OpenGL 相比,vulkan 中的缓冲区和解像创建比较复杂,因为

  1. 我们必须先创建缓冲区/图像,然后稍后将其绑定到必须单独创建的 vkDeviceMemory 上。
  2. 为每个缓冲区/图像创建单个 vkDeviceMemory 分配是不良做法,实际上,鼓励将共同使用的资源绑定到同一分配上。
  3. 由于不同资源(应该)具有不同的内存属性,因此引入了另一层困难——每个驱动程序/供应商都不同。

功能

nobs-vkmem 提供了创建缓冲区和图像以及将它们绑定到物理内存的便捷且易于访问的方法。这大大减少了样板代码,同时仍然使用户能够对资源如何绑定到内存有相当的控制权。

  1. 使用构建器模式轻松创建缓冲区和图像。
  2. 设备内存按较大的页面分配。库跟踪页面中的空闲和已用区域。
  3. 为不同的目的提供不同的分配策略,包括强制将多个资源绑定到连续块,或将资源绑定到私有页面上。
  4. 轻松映射主机可访问的缓冲区

文档

docs.rs 上找到此库的完整文档。

示例用法

  // create an allocator with default page size 
  // (128MiB for device local / 8MB for host visible memory)
  let mut allocator = vkmem::Allocator::new(physical_device_handle, device_handle);

  // declare handles
  let mut buf_ub = vk::NULL_HANDLE;
  let mut img = vk::NULL_HANDLE;
  let mut bb = vk::NULL_HANDLE;

  // configure
  vkmem::Buffer::new(&mut buf_ub)
    .size(std::mem::size_of::<Ub>() as vk::DeviceSize)
    .usage(vk::BUFFER_USAGE_TRANSFER_DST_BIT | vk::BUFFER_USAGE_UNIFORM_BUFFER_BIT)
    .devicelocal(false)
    .next_image(&mut img)
    .image_type(vk::IMAGE_TYPE_2D)
    .size(123, 123, 1)
    .usage(vk::IMAGE_USAGE_SAMPLED_BIT)
    .next_buffer(&mut bb)
    .size(123 * std::mem::size_of::<u32>() as vk::DeviceSize)
    .usage(vk::BUFFER_USAGE_TRANSFER_DST_BIT | vk::BUFFER_USAGE_STORAGE_BUFFER_BIT)
    // binds all configured resources in bulk using as less blocks of memory as possible.
    // But allows to split resources of the same memory type to be scattered to multiple blocks
    // on the same page, if no large enough free block is found
    .bind(&mut allocator, vkmem::BindType::Scatter)
    .unwrap();

  // Mapped gives a convenient view on the memory
  {
    let mapped = allocator.get_mapped(buf_ub).unwrap();
    let ubb = Ub { a: 123, b: 4, c: 5 };
    mapped.host_to_device(&ubb);
    // going out of scope automatically unmapps...
  }
  {
    let mapped = allocator.get_mapped(buf_ub).unwrap();
    let mut ubb = Ub { a: 0, b: 0, c: 0 };
    mapped.device_to_host(&mut ubb);
    println!("{:?}", ubb);
  }

  // we can print stats in a yaml format for the currently allocated pages
  println!("{}", allocator.print_stats());

  // buffers and images can be destroyed
  // destroy_many() should be preferred over destroy(),
  // because this will rearrange and merge allocated blocks into the free list again
  allocator.destroy_many(&[buf_ub, img]);

  // destroying does NOT free memory
  // if we want to free memory we can do this only, if a whole page is not used any more
  // in this case we can free the memory again
  allocator.free_unused();

贡献

请鼓励以任何您能想到的方式做出贡献!

依赖关系