6个版本

使用旧Rust 2015

0.1.6 2016年7月11日
0.1.5 2016年7月8日
0.1.2 2016年6月30日

图形API中排名第697


dvk_ext_debug_report中使用

MIT许可

265KB
4.5K SLoC

Dvk是一个提供Vulkan API绑定的库。与其他许多替代方案不同,Dvk在运行时动态加载所有Vulkan命令,使编译变得更加简单,以至于即使不需要安装Vulkan也可以编译。

该库的设计遵循最小惊讶原则,它与官方头文件几乎不偏离,不会无谓地污染官方Vulkan命名空间。只有少数地方由于语言差异或需要动态加载而迫使设计偏离标准,所有这些特殊性都在本页上进行了详细说明。标准的Khronos文档应该足以了解该库提供所有类型和函数。

注意:在当前版本中,只有khr_win32_surface完成了所有平台特定WSI扩展。

文档

https://www.khronos.org/registry/vulkan/specs/1.0-wsi_extensions/xhtml/vkspec.html

组织

所有定义都组织到模块中,主要的是core,其余的khr_surfaceext_debug_reportkhr_displaykhr_display_swapchainkhr_swapchainkhr_win32_surface都是扩展。该库不导出任何可用的命令原型。所有定义的顺序与vulkan.h头文件中的顺序相同。

官方API的更改

类型

  • VkClearValueUnion
  • VkClearColorValueUnion
  • VkCoreCommands
  • VkKhrSurfaceCommands
  • VkKhrSwapchainCommands
  • VkKhrDisplayCommands
  • VkKhrDisplaySwapchainCommands
  • VkKhrWin32SurfaceCommands
  • VkExtDebugReportCommands
  • 没有单独的*FlagBits*Flags类型,只有*Flags
  • VkDescriptorPoolSize.type更名为dType,因为与Rust关键字type命名冲突。
  • 平台类型作为库的一部分重新定义
  • 没有通用的VK_NULL_HANDLE常量,它与类型安全句柄不兼容

函数

  • Vulkan*::new()Vulkan*::load(&mut self, VkInstance)
  • ::null() 构造函数和所有句柄的 ::is_null(&self) 方法
  • *Union 类型的特质实现

加载

动态加载相对于静态链接的优势在于无需静态库即可编译。Vulkan 标准在这方面相当保守,只保证从动态库中导出单个命令。该命令是 vkGetInstanceProcAddr。一旦获取了该命令,就可以使用它来加载下一级 API,该 API 由三个 全局命令 组成

  1. vkCreateInstance
  2. vkEnumerateInstanceExtensionProperties
  3. vkEnumerateInstanceLayerProperties

API 的其余部分,由 134 个核心命令 组成,可以类似地通过 vkGetInstanceProcAddr 加载,但需要 VkInstance 对象来加载它们。不出所料,可以通过全局命令 vkCreateInstance 创建 VkInstance 对象。扩展命令以完全相同的方式加载。

该库不导出任何现成的命令原型,而是以结构体返回所有动态加载的命令。

Vulkan 功能的核心位于 VkCoreCommands 结构体中。它提供了所有核心 Vulkan 命令作为方法。当通过调用 VkCoreCommands::new() 初始创建 VkCoreCommands 时,它将已经加载了 3 个全局命令 并准备好使用。如果在此时尝试调用任何未加载的命令,将导致 panic。下一步应该是创建一个 VkInstance 对象并调用 VkCoreCommands::load(&mut self, VkInstance instance) 方法,并将其作为参数传递。Vulkan 准备就绪。

扩展通过 VkKhrSurfaceCommandsVkKhrSwapchainCommandsVkKhrDisplayCommandsVkKhrDisplaySwapchainCommandsVkKhrWin32SurfaceCommands 等类似方式加载。

该库不支持使用 vkGetDeviceProcAddr 加载设备优化的命令指针。这种省略的原因是,以这种方式加载函数引入了大量的意外复杂性,并使库难以使用。

平台类型

平台类型被重新定义以避免操作系统特定的依赖,使用 std::mem::transmute 在它们之间进行转换。当前的平台类型有

  • dvk::khr_win32_surface::platform::HINSTANCE
  • dvk::khr_win32_surface::platform::HWND

联合

由于Rust没有与C联合体相对应的结构,因此它们通过标签联合类型From trait的组合来模拟。每当Vulkan需要名为VkSomeTypeName的联合体时,构造一个类型为VkSomeTypeNameUnion的值,并调用其上的into(self)方法来获取VkSomeTypeName。例如

let foo: VkClearColorValue = VkClearColorValueUnion::Float32([1,2,3]).into();

句柄

所有句柄都是类型安全的,这不幸地使得生成“NULL”句柄变得很尴尬。因此,所有句柄类型都实现了null函数来构建空句柄,以及相应的is_null方法来检查句柄是否为空。

用法

以下是一个简短的示例,用于说明基本用法

#[macro_use]
extern crate dvk;

use dvk::core::*;
use dvk::khr_surface::*;
use dvk::khr_win32_surface::*;

...
// This will load vulkan shared library and 3 global commands
let mut core = VkCoreCommands::new().unwrap(); 

// The null method is used to get type-safe "NULL" handles
let mut instance = VkInstance::null();

// vkCreateInstance is one of the 3 global commands
// that can be loaded without an instance object
core.vkCreateInstance(&instance_create_info, null(), &mut context.instance);

// Calling unloaded command will cause a panic
core.vkEnumeratePhysicalDevices(...); // ERROR!

// After you've acquired an instance object the remaining commands can be loaded
core.load(instance).unwrap(); 

// The rest of commands are loaded and ready to use now
core.vkEnumeratePhysicalDevices(...); 
core.vkCreateDevice(...); 
core.vkQueueSubmit(...);

// Using intermediate VkClearValueUnion Rust-style enum to 
// construct VkClearValue corresponding to C-style union
let clear_depth_stencil_value = VkClearDepthStencilValue{depth:0.0f32, stencil: 0u32};
let clear_value: VkClearValue = VkClearValueUnion::DepthStencil(clear_depth_stencil_value).into();

示例代码

更完整的示例可以在examples/triangle.rs中找到。要编译(或运行)它,请

> cargo build(or run) --examples triangle

依赖项

~215KB