#vulkan #structure #create #pointers #manipulate #gpu #bindings

lava

Rust包装器,用于比使用绑定更方便地操作Vulkan

15个版本

使用旧Rust 2015

0.4.9 2020年4月20日
0.4.7 2020年1月27日
0.4.6 2019年12月7日
0.4.5 2019年9月22日
0.2.0 2018年9月25日

#97 in 图形API

每月 30 次下载

MIT 许可证

3MB
57K SLoC

熔岩

在Rust中操作Vulkan API的包装器,比使用绑定更方便

  • 在向Vulkan发送结构时,无需指定结构类型
  • 在必要时进行双倍Vulkan调用(当检索Vulkan对象列表时)
  • 返回由Vulkan检索的对象,而不是要求用户提供指针
  • 允许操作引用、切片和选项,而不是指针(特别是允许提供切片而不是指针 + 长度)
  • 以面向对象的方式公开API(例如 instance.enumerate_physical_devices() 而不是 enumerate_physical_devices(&instance)
  • 从函数和数据结构名称中删除扩展后缀(使用模块代替)
  • 以结构的形式公开位标志,而不是整数
  • 为所有结构提供默认值,允许使用 ..Default::default() 完成具有可选字段的结构的自动完成
  • 管理对 vkGetInstanceProcAddrvkGetDeviceProcAddr 的调用,以操作未静态公开的函数
  • 提供创建表面的通用 create_surface 方法

熔岩完全由Vulkan的C头文件生成。

当前限制

  • 无法提供分配器回调
  • 无法设置结构的 pNext 字段

使用方法

[dependencies]
lava = "0.4"

示例

此代码创建一个Vulkan实例,添加一个调试报告回调并显示机器上每个GPU的名称

#[macro_use] extern crate lava;
use lava::*;

fn main() {
    let instance = vk_create_instance(VkInstanceCreateInfo {
        flags: VkInstanceCreateFlags!(),
        application_info: Some(VkApplicationInfo {
            application_name: Some("lava-example"),
            application_version: 1,
            engine_name: None,
            engine_version: 1,
            api_version: VkVersion(1, 0, 0),
        }),
        enabled_layer_names: vec![VK_LAYER_KHRONOS_VALIDATION_NAME],
        enabled_extension_names: vec![VK_EXT_DEBUG_REPORT_EXTENSION_NAME]
    }).expect("Failed to create instance");

    let debug_report_callback = instance.create_debug_report_callback(VkDebugReportCallbackCreateInfo {
        flags: VkDebugReportFlags!(error, warning),
        callback: |data: VkDebugReportCallbackData| {
            println!("{}", data.message);
        }
    }).expect("Failed to create debug callback");

    let physical_devices = instance.enumerate_physical_devices()
        .expect("Failed to retrieve physical devices");

    for physical_device in &physical_devices {
        let properties = physical_device.get_properties();

        println!("{}", properties.device_name);
    }

    debug_report_callback.destroy();
    instance.destroy();
}

本片段展示了如何从GLFW窗口创建一个表面

// We assume that `window` is a pointer to a GLFWwindow, as described here:
// http://www.glfw.org/docs/latest/group__vulkan.html#ga1a24536bec3f80b08ead18e28e6ae965

let surface = instance.create_surface(
    |handle, allocator, surface| unsafe { glfwCreateWindowSurface(handle, window, allocator, surface) }
).expect("Failed to create surface from glfw window");

附加使用信息

模块划分

根据它们的扩展(KHR,EXT等),数据结构被划分到多个模块中。没有扩展的数据结构位于lava::vk模块中。

一些常量(例如验证层名称)位于lava::constants模块中。

Lava导出lava::vklava::constantslava::extlava::khr模块的所有成员(使用use lava::*使得这些模块中包含的所有数据结构都可用,无需前缀)。

位标志

位标志以结构体而不是整数的格式表示。此外,所有位标志结构体都有静态的none()all()函数。创建位标志结构的典型方式如下

// Creates a structure with the `vertex` and `fragment` flag enabled, and all the others disabled
VkShaderStageFlags {
    vertex: true,
    fragment: true,
    ..VkShaderStageFlags::none()
}

由于编写起来很麻烦,所有位标志结构体都有一个宏快捷方式

// Same effect as previous snippet
VkShaderStageFlags!(vertex, fragment)

此外,所有位标志结构体都有以下方法

let no_shader_stage = VkShaderStageFlags::none();
let all_shader_stages = VkShaderStageFlags::all();
let shader_stages = VkShaderStageFlags::from_u32(17);
let shader_stages_int = shader_stages.to_u32();

结果

当相关时,函数返回一个Result<T, (VkResult, T)>。如果Vulkan函数返回的VkResult是0,则返回值是Ok(T)。否则它是Err((VkResult, T))。元组的第一个元素是Vulkan函数返回的错误代码。第二个元素是,在特定情况下,当VkResult不为0但也不是错误(例如调用swapchain.acquire_next_image())时,函数产生的值。否则它是一个零值,在使用时很可能会崩溃。

对象销毁和释放

用户需要手动销毁他们的对象,而不是Rust在对象释放时自动执行。原因有两个

  • 在C API中,某些对象不能由用户销毁。例如,当交换链被销毁时,交换链的VkImage对象会自动销毁,手动尝试销毁它们将产生错误。但用户仍然需要销毁他们手动创建的VkImage对象。自动销毁机制需要一些关于对象来源的上下文,而这超出了范围。
  • 对象释放的顺序有很大可能性不会与它们必须销毁的顺序匹配,尤其是在结构体释放时。

手动构建

src/vulkan/文件夹的内容是从Vulkan文档存储库中的vulkan_core.hvk.xml文件生成的。

如果您想手动重新生成,可以这样做(需要Node.js)

  • npm install
  • node generate.js[ --tag<version> ]

其中 <version> 是 Vulkan-Docs 仓库的分支或标签名(例如 v1.1.80)。如果省略,则默认为 master。脚本将在 download/ 文件夹中下载相应的文件并生成新的源文件。

许可证

MIT

无运行时依赖