vkgen
Generates Rust source code from the Vulkan registry.
General Information
Licence
This software is MIT licenced.
Dependencies
Rust Version
The latest Rust version the generated code was tested with is 1.40 and 1.42-nightly.
Cargo Crates
libloading
is the default way of loading the Vulkan shared library, but the generated
code can easily be modified to use something different. (see usage step 3a)
Environment (Shared Libraries etc.)
No C/C++ headers/source code or any binaries are required to compile and run the generated
code, only the Vulkan shared library. (libvulkan.so
on Linux and vulkan-1.dll
on Win32)
Sometimes on Linux the library is named libvulkan.so.1.1
or similar, causing the program
to crash. One way to fix this is to create a link or copy the library with the correct name.
Other
No other dependencies are required to use the generated code, if the code fails to compile or crashes at runtime nonetheless and an API misuse can be ruled out, please submit an issue on github.
Details
Function Loading
When a static function is called (functions that do not require a dispatchable handle) the
vulkan shared library is automatically loaded. To use non static functions, a dispatchable
handle needs to be wrapped with VkXxxImpl::new(handle)
.
Wrapper Structs
Wrapper structs are generated for all disptachable handles, which contain a function table or
point to the function table of the parent handle. When a wrapper method is called, the equivalent
function in the function table is dispatched. The wrapper methods' signatures only differ from the
ones in the table in slice parameters that can not be null
, where the functions in the table
take a pointer and a length, but the wrapper methods take a slice, to provide some safety. No
other safety guards are provided.
The special wrappers VkInstanceImpl
and VkDeviceImpl
will populate a table with function
pointers obtained via vkGetInstanceProcAddr
and vkGetDeviceProcAddr
on creation.
All wrapper structs implements Debug
for debugging purposes obviously and Deref
/DerefMut
,
to access the wrapped handles. The table entries are not pub
and thus cannot be accessed but with
the wrapper methods.
Structs and Enums
All structs and enums implement Copy
, Clone
and Debug
.
Common Mistakes
Initializing a struct with a member that is a pointer to an array might cause undefined behaviour:
Never do this:
VkSomeStruct ;
Always do this:
let array = ;
VkSomeStruct
VkResult
The enum VkResult
implements Error
and ops::Try
, which means it can be used with the
?
operator. To utilize this, a nightly compiler is required and the try_trait
feature
must be enabled.
#![feature("try_trait")]
...
VkInstanceImpl::create(&info, allocator, &mut instance)?; // <-- returns early if the result was an error
Versions and Extensions
Almost every method/struct/enum has a #[cfg(feature = "VK_SERSION_X_X")]
or
#[cfg(feature = "VK_SOME_FEATURE_KHR"")]
attribute, which means in order to use
any method/struct/enum a feature must be enabled. The versions of the Vulkan API,
VK_VERSION_1_0
and VK_VERSION_1_1
, are enabled by default.
Some extensions are marked as unsupported in the registry, which will be skipped.
Constants and Type Aliases
The type of constants will be inferred by looking at their values. If the generator
fails to infer the type, u32
will be used instead. This might result in constants
with a wrong type, which prevents them from being passed to functions or used in
structs. In this case, please submit an issue on github.
Usage
Step 1
Download vk.xml from the official Vulkan-Headers repository
Step 2
Generate Rust source code from vk.xml
$ vkgen <input file> <flags>
Parameters
input file
is the Vulkan registry file to be parsedflags
see Flags
Flags
--verbose
,-v
print all warnings
Output
<input file>.rs
contains the generated source code<input file>.toml
contains a list of all versions and extensions
Example
$ vkgen ./vk.xml
Parses a file named vk.xml
containing the Vulkan registry and outputs the generated
code to vk.rs
and a list of all versions and extensions to vk.toml
.
Step 3
Copy the Rust file into your project folder and add the versions and extensions located in the toml file to your project's Cargo.toml:
...
[]
= ["VK_VERSION_1_0", "VK_VERSION_1_1"]
...
= []
= []
...
[]
= "*"
...
Step 3a (optional)
If you do not want to use libloading, remove the dependency and edit vkInit
to load the
function pointers with your preferred method.
Examples
This simple example demonstrates how to output the instance version (1.1.0) and create an
instance. vk.rs is the file containing the generated Rust source code. The shared library
will be loaded on the first method call (VkInstanceImpl::enumerateVersion
in this case).
Cargo.toml:
[]
= "vkgen_test"
= "0.1.0"
= ["tobias"]
= "2018"
[]
= ["VK_VERSION_1_0", "VK_VERSION_1_1"]
= []
= []
[]
= "0.5.0"
main.rs:
use *;
use null;