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 次下载
3MB
57K SLoC
熔岩
在Rust中操作Vulkan API的包装器,比使用绑定更方便
- 在向Vulkan发送结构时,无需指定结构类型
- 在必要时进行双倍Vulkan调用(当检索Vulkan对象列表时)
- 返回由Vulkan检索的对象,而不是要求用户提供指针
- 允许操作引用、切片和选项,而不是指针(特别是允许提供切片而不是指针 + 长度)
- 以面向对象的方式公开API(例如
instance.enumerate_physical_devices()
而不是enumerate_physical_devices(&instance)
) - 从函数和数据结构名称中删除扩展后缀(使用模块代替)
- 以结构的形式公开位标志,而不是整数
- 为所有结构提供默认值,允许使用
..Default::default()
完成具有可选字段的结构的自动完成 - 管理对
vkGetInstanceProcAddr
和vkGetDeviceProcAddr
的调用,以操作未静态公开的函数 - 提供创建表面的通用
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::vk
、lava::constants
、lava::ext
和lava::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.h
和vk.xml
文件生成的。
如果您想手动重新生成,可以这样做(需要Node.js)
npm install
node generate.js[ --tag<version> ]
其中 <version>
是 Vulkan-Docs 仓库的分支或标签名(例如 v1.1.80
)。如果省略,则默认为 master
。脚本将在 download/
文件夹中下载相应的文件并生成新的源文件。