2021-07-30 20:32:52 +10:00
Ash
=
2016-12-10 06:33:25 +11:00
2016-12-10 09:13:58 +11:00
A very lightweight wrapper around Vulkan
2021-07-30 20:32:52 +10:00
-
2016-12-10 06:38:22 +11:00
2021-07-30 20:32:52 +10:00
[![Crates.io Version ](https://img.shields.io/crates/v/ash.svg )](https://crates.io/crates/ash)
2016-12-10 06:49:49 +11:00
[![Documentation ](https://docs.rs/ash/badge.svg )](https://docs.rs/ash)
2019-10-21 02:47:38 +11:00
[![Build Status ](https://github.com/MaikKlein/ash/workflows/CI/badge.svg )](https://github.com/MaikKlein/ash/actions?workflow=CI)
2021-07-30 20:32:52 +10:00
[![LICENSE ](https://img.shields.io/badge/license-MIT-blue.svg )](LICENSE-MIT)
[![LICENSE ](https://img.shields.io/badge/license-apache-blue.svg )](LICENSE-APACHE)
2016-12-10 06:33:25 +11:00
[![Join the chat at https://gitter.im/MaikKlein/ash ](https://badges.gitter.im/MaikKlein/ash.svg )](https://gitter.im/MaikKlein/ash?utm_source=badge& utm_medium=badge& utm_campaign=pr-badge& utm_content=badge)
2016-08-14 09:13:39 +10:00
2018-11-12 04:05:03 +11:00
## Overview
2018-11-12 04:06:48 +11:00
- [x] A true Vulkan API without compromises
2018-11-13 02:25:31 +11:00
- [x] Convenience features without limiting functionality
2018-11-13 00:53:06 +11:00
- [x] Additional type safety
- [x] Device local function pointer loading
2018-11-12 04:06:48 +11:00
- [x] No validation, everything is **unsafe**
- [x] Generated from `vk.xml`
2020-01-26 19:38:58 +11:00
- [x] Support for Vulkan `1.1` , `1.2`
2018-11-12 04:05:03 +11:00
## Features
2016-12-28 14:31:48 +11:00
### Explicit returns with `Result`
2020-08-15 06:40:06 +10:00
```rust
2017-04-30 23:46:38 +10:00
// function signature
2016-12-29 18:06:17 +11:00
pub fn create_instance(& self,
create_info: & vk::InstanceCreateInfo,
allocation_callbacks: Option< & vk::AllocationCallbacks>)
2017-04-30 23:46:38 +10:00
-> Result< Instance , InstanceError > { .. }
2017-01-05 18:35:37 +11:00
let instance = entry.create_instance(& create_info, None)
2016-12-29 18:06:17 +11:00
.expect("Instance creation error");
2016-12-10 05:25:48 +11:00
```
2018-11-13 00:53:06 +11:00
### `Vec<T>` instead of mutable slices
2018-11-12 04:05:03 +11:00
2020-08-15 06:40:06 +10:00
```rust
2019-01-19 20:00:44 +11:00
pub fn get_swapchain_images(& self,
swapchain: vk::SwapchainKHR)
-> VkResult< Vec < vk::Image > >;
2016-12-29 18:06:17 +11:00
let present_images = swapchain_loader.get_swapchain_images_khr(swapchain).unwrap();
2016-12-10 05:25:48 +11:00
```
2018-11-13 00:53:06 +11:00
*Note*: Functions don't return `Vec<T>` if this would limit the functionality. See `p_next` .
2016-12-28 14:31:48 +11:00
2018-11-13 00:53:06 +11:00
### Slices
2020-08-15 06:40:06 +10:00
```rust
2016-12-24 07:41:16 +11:00
pub fn cmd_pipeline_barrier(& self,
command_buffer: vk::CommandBuffer,
src_stage_mask: vk::PipelineStageFlags,
dst_stage_mask: vk::PipelineStageFlags,
dependency_flags: vk::DependencyFlags,
memory_barriers: & [vk::MemoryBarrier],
buffer_memory_barriers: & [vk::BufferMemoryBarrier],
image_memory_barriers: &[vk::ImageMemoryBarrier]);
2016-12-10 05:25:48 +11:00
```
2016-12-28 14:31:48 +11:00
2018-11-20 15:19:50 +11:00
### Strongly typed handles
Each Vulkan handle type is exposed as a newtyped struct for improved type safety. Null handles can be constructed with
`T::null()` , and handles may be freely converted to and from `u64` with `Handle::from_raw` and `Handle::as_raw` for
interop with non-Ash Vulkan code.
2018-11-12 04:05:03 +11:00
### Default implementation for all types
2020-08-15 06:40:06 +10:00
```rust
2018-11-12 04:05:03 +11:00
// No need to manually set the structure type
let desc_alloc_info = vk::DescriptorSetAllocateInfo {
descriptor_pool: self.pool,
descriptor_set_count: self.layouts.len() as u32,
p_set_layouts: self.layouts.as_ptr(),
..Default::default()
2016-12-24 07:41:16 +11:00
};
2016-12-10 05:25:48 +11:00
```
2018-11-12 04:05:03 +11:00
### Builder pattern
2019-03-20 20:37:55 +11:00
2020-08-15 06:40:06 +10:00
```rust
2021-07-30 20:32:52 +10:00
// We lose all lifetime information when we call `.build()` . Be careful!
2019-03-20 20:37:55 +11:00
let queue_info = [vk::DeviceQueueCreateInfo::builder()
.queue_family_index(queue_family_index)
.queue_priorities(& priorities)
.build()];
2021-03-03 04:22:04 +11:00
// We don't need to call `.build()` here because builders implement `Deref` .
2019-03-20 20:37:55 +11:00
let device_create_info = vk::DeviceCreateInfo::builder()
.queue_create_infos(& queue_info)
.enabled_extension_names(& device_extension_names_raw)
.enabled_features(&features);
let device: Device = instance
.create_device(pdevice, & device_create_info, None)
.unwrap();
```
2021-03-03 04:22:04 +11:00
To not lose this lifetime single items can be "cast" to a slice of length _one_ with `std::slice::from_ref` while still taking advantage of `Deref` :
```rust
let queue_info = vk::DeviceQueueCreateInfo::builder()
.queue_family_index(queue_family_index)
.queue_priorities(&priorities);
let device_create_info = vk::DeviceCreateInfo::builder()
.queue_create_infos(std::slice::from_ref(& queue_info))
...;
```
2019-03-20 20:37:55 +11:00
Builders have an explicit lifetime, and are marked as `#[repr(transparent)]` .
2020-08-15 06:40:06 +10:00
```rust
2019-03-20 20:37:55 +11:00
#[repr(transparent)]
pub struct DeviceCreateInfoBuilder< 'a> {
inner: DeviceCreateInfo,
marker: ::std::marker::PhantomData< & 'a ()>,
}
impl< 'a> DeviceCreateInfoBuilder< 'a> {
//...
pub fn queue_create_infos(
mut self,
queue_create_infos: & 'a [DeviceQueueCreateInfo],
2019-03-20 20:48:32 +11:00
) -> DeviceCreateInfoBuilder< 'a> {...}
2019-03-20 20:37:55 +11:00
//...
2017-01-01 18:31:13 +11:00
```
2018-11-20 15:19:50 +11:00
2019-03-20 20:37:55 +11:00
Every reference has to live as long as the builder itself. Builders implement `Deref` targeting their corresponding Vulkan struct, so references to builders can be passed directly
to Vulkan functions.
2019-03-22 21:00:56 +11:00
Calling `.build()` will **discard** that lifetime because Vulkan structs use raw pointers internally. This should be avoided as much as possible because this can easily lead to dangling pointers. If `.build()` has to be called, it should be called as late as possible. [Lifetimes of temporaries ](https://doc.rust-lang.org/reference/expressions.html#temporary-lifetimes ) are extended to the enclosing statement, ensuring they are valid for the duration of a Vulkan call occurring in the same statement.
2019-03-20 20:37:55 +11:00
2018-11-20 15:19:50 +11:00
2019-03-10 03:33:42 +11:00
### Pointer chains
2020-08-15 06:40:06 +10:00
```rust
2019-03-10 03:33:42 +11:00
let mut variable_pointers = vk::PhysicalDeviceVariablePointerFeatures::builder();
let mut corner =
vk::PhysicalDeviceCornerSampledImageFeaturesNV::builder();
;
let mut device_create_info = vk::DeviceCreateInfo::builder()
.push_next(& mut corner)
.push_next(& mut variable_pointers);
```
2019-05-10 08:43:55 +10:00
Pointer chains in builders differ from raw Vulkan. Instead of chaining every struct manually, you instead use `.push_next` on the struct that you are going to pass into the function. Those structs then get *prepended* into the chain.
2019-03-10 03:33:42 +11:00
`push_next` is also type checked, you can only add valid structs to the chain. Both the structs and the builders can be passed into `push_next` . Only builders for structs that can be passed into functions will implement a `push_next` .
2018-11-12 04:05:03 +11:00
### Flags and constants as associated constants
2017-01-01 18:31:13 +11:00
2020-08-15 06:40:06 +10:00
```rust
2018-11-13 00:53:06 +11:00
// Bitflag
vk::AccessFlags::COLOR_ATTACHMENT_READ | vk::AccessFlags::COLOR_ATTACHMENT_WRITE
2017-01-01 18:31:13 +11:00
```
2020-08-15 06:40:06 +10:00
```rust
2018-11-13 00:53:06 +11:00
// Constant
vk::PipelineBindPoint::GRAPHICS,
2017-01-01 18:31:13 +11:00
```
2018-11-12 04:05:03 +11:00
### Debug/Display for Flags
2017-01-01 18:31:13 +11:00
2020-08-15 06:40:06 +10:00
```rust
2018-11-12 04:05:03 +11:00
let flag = vk::AccessFlags::COLOR_ATTACHMENT_READ
| vk::AccessFlags::COLOR_ATTACHMENT_WRITE;
println!("Debug: {:?}", flag);
println!("Display: {}", flag);
// Prints:
// Debug: AccessFlags(110000000)
// Display: COLOR_ATTACHMENT_READ | COLOR_ATTACHMENT_WRITE
2017-01-01 18:31:13 +11:00
```
2018-11-12 04:05:03 +11:00
### Function pointer loading
2018-11-13 20:07:37 +11:00
Ash also takes care of loading the function pointers. Function pointers are split into 3 categories.
* Entry: Loads the Vulkan library. Needs to outlive `Instance` and `Device` .
* Instance: Loads instance level functions. Needs to outlive the `Device` s it has created.
* Device: Loads device **local** functions.
The loader is just one possible implementation:
* Device level functions are retrieved on a per device basis.
* Everything is loaded by default, functions that failed to load are initialized to a function that always panics.
* Do not call Vulkan 1.1 functions if you have created a 1.0 instance. Doing so will result in a panic.
Custom loaders can be implemented.
2018-11-12 04:05:03 +11:00
2016-12-28 14:31:48 +11:00
### Extension loading
2018-11-12 04:05:03 +11:00
Additionally, every Vulkan extension has to be loaded explicitly. You can find all extensions under [ash::extensions ](https://github.com/MaikKlein/ash/tree/master/ash/src/extensions ).
2020-08-15 06:40:06 +10:00
```rust
2019-01-19 20:00:44 +11:00
use ash::extensions::khr::Swapchain;
2018-11-12 04:05:03 +11:00
let swapchain_loader = Swapchain::new(& instance, &device);
2019-01-19 20:00:44 +11:00
let swapchain = swapchain_loader.create_swapchain(&swapchain_create_info).unwrap();
2016-12-10 05:25:48 +11:00
```
2016-12-28 14:31:48 +11:00
2018-11-13 00:53:06 +11:00
### Raw function pointers
Raw function pointers are available, if something hasn't been exposed yet in the higher level API. Please open an issue if anything is missing.
2020-08-15 06:40:06 +10:00
```rust
2018-11-13 00:53:06 +11:00
device.fp_v1_0().destroy_device(...);
```
2017-01-01 18:31:13 +11:00
### Support for extension names
2020-08-15 06:40:06 +10:00
```rust
2017-01-01 18:31:13 +11:00
use ash::extensions::{Swapchain, XlibSurface, Surface, DebugReport};
#[cfg(all(unix, not(target_os = "android")))]
fn extension_names() -> Vec< *const i8> {
vec![
Surface::name().as_ptr(),
XlibSurface::name().as_ptr(),
DebugReport::name().as_ptr()
]
}
```
2016-12-28 14:31:48 +11:00
### Implicit handles
2018-11-12 04:05:03 +11:00
Handles from Instance or Device are passed implicitly.
2020-08-15 06:40:06 +10:00
```rust
2016-12-24 07:41:16 +11:00
pub fn create_command_pool(& self,
create_info: & vk::CommandPoolCreateInfo)
-> VkResult< vk::CommandPool > ;
2016-12-10 05:25:48 +11:00
2016-12-24 07:41:16 +11:00
let pool = device.create_command_pool(&pool_create_info).unwrap();
2016-12-10 05:25:48 +11:00
```
2016-12-28 14:22:13 +11:00
2021-09-10 06:50:34 +10:00
### Optional linking
The default `linked` cargo feature will link your binary with the Vulkan loader directly and expose the infallible `Entry::new` .
If your application can handle Vulkan being missing at runtime, you can instead enable the `loaded` feature to dynamically load Vulkan with `Entry::load` .
2016-12-10 05:39:16 +11:00
## Example
You can find the examples [here ](https://github.com/MaikKlein/ash/tree/master/examples ).
2017-01-01 18:37:12 +11:00
All examples currently require: the LunarG Validation layers and a Vulkan library that is visible in your `PATH` . An easy way to get started is to use the [LunarG Vulkan SDK ](https://lunarg.com/vulkan-sdk/ )
2017-01-01 18:43:36 +11:00
#### Windows
Make sure that you have a Vulkan ready driver and install the [LunarG Vulkan SDK ](https://lunarg.com/vulkan-sdk/ ).
#### Linux
Make sure that you have a Vulkan ready driver and install the [LunarG Vulkan SDK ](https://lunarg.com/vulkan-sdk/ ). You also have to add the library and layers to your path. Have a look at my [post ](http://askubuntu.com/a/803110/77183 ) if you are unsure how to do that.
2018-07-07 14:55:59 +10:00
#### macOS
Install the [LunarG Vulkan SDK ](https://lunarg.com/vulkan-sdk/ ). This basically entails extracting the downloaded tarball to any location you choose and then setting a few environment variables. Specifically, if `SDK_PATH` is set to the root extracted SDK directory,
* `DYLD_LIBRARY_PATH = $SDK_PATH/macOS/lib`
* `VK_ICD_FILENAMES = $SDK_PATH/macOS/etc/vulkan/icd.d/MoltenVK_icd.json`
* `VK_LAYER_PATH = $SDK_PATH/macOS/etc/vulkan/explicit_layer.d`
2016-12-10 05:39:16 +11:00
2019-11-17 10:45:05 +11:00
### [Triangle](https://github.com/MaikKlein/ash/blob/master/examples/src/bin/triangle.rs)
Displays a triangle with vertex colors.
```
cd examples
cargo run --bin triangle
```
2016-12-10 05:47:29 +11:00
![screenshot ](http://i.imgur.com/PQZcL6w.jpg )
2016-12-10 05:39:16 +11:00
2016-12-26 00:49:20 +11:00
### [Texture](https://github.com/MaikKlein/ash/blob/master/examples/src/bin/texture.rs)
2016-12-26 11:23:19 +11:00
Displays a texture on a quad.
2016-12-12 14:43:46 +11:00
```
2016-12-26 00:49:20 +11:00
cd examples
cargo run --bin texture
2016-12-12 14:43:46 +11:00
```
2016-12-12 14:30:01 +11:00
![texture ](http://i.imgur.com/trow00H.png )
2016-12-12 14:19:21 +11:00
2019-02-15 20:08:38 +11:00
## Useful resources
### Examples
* [vulkan-tutorial-rust ](https://github.com/Usami-Renko/vulkan-tutorial-rust ) - A port of [vulkan-tutorial.com ](vulkan-tutorial.com ).
* [ash-sample-progression ](https://github.com/bzm3r/ash-sample-progression ) - A port of the LunarG examples.
* [ash-nv-rt ](https://github.com/gwihlidal/ash-nv-rt ) A raytracing example for ash.
### Utility libraries
* [vk-sync ](https://github.com/gwihlidal/vk-sync-rs ) - Simplified Vulkan synchronization logic, written in rust.
* [vk-mem-rs ](https://github.com/gwihlidal/vk-mem-rs ) - This crate provides an FFI layer and idiomatic rust wrappers for the excellent AMD Vulkan Memory Allocator (VMA) C/C++ library.
2021-07-30 20:32:52 +10:00
* [gpu-allocator ](https://github.com/Traverse-Research/gpu-allocator ) - Memory allocator written in pure Rust for GPU memory in Vulkan and in the future DirectX 12
2019-02-15 20:08:38 +11:00
* [lahar ](https://github.com/Ralith/lahar ) - Tools for asynchronously uploading data to a Vulkan device.
### Libraries that use ash
2019-02-15 20:10:02 +11:00
* [gfx-rs ](https://github.com/gfx-rs/gfx ) - gfx-rs is a low-level, cross-platform graphics abstraction library in Rust.
2019-02-15 20:08:38 +11:00
2016-12-10 07:04:31 +11:00
## A thanks to
* [Api with no secrets ](https://software.intel.com/en-us/articles/api-without-secrets-introduction-to-vulkan-part-1 )
2019-05-10 05:49:51 +10:00
* [Vulkan tutorial ](http://jhenriques.net/development.html )
2016-12-10 07:04:31 +11:00
* [Vulkan examples ](https://github.com/SaschaWillems/Vulkan )
2016-12-10 07:05:19 +11:00
* [Vulkan tutorial ](https://vulkan-tutorial.com/ )
2019-05-11 21:29:40 +10:00
* [Vulkano ](https://github.com/vulkano-rs/vulkano )
2016-12-10 07:04:31 +11:00
* [vk-rs ](https://github.com/Osspial/vk-rs )