• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..--

src/25-Apr-2025-141,451139,271

tests/25-Apr-2025-5239

.cargo-checksum.jsonD25-Apr-202510.2 KiB11

Android.bpD25-Apr-20252.4 KiB110103

Cargo.tomlD25-Apr-20251.2 KiB5549

LICENSED25-Apr-20259.5 KiB6839

LICENSE-APACHED25-Apr-20259.5 KiB6839

LICENSE-MITD25-Apr-20251 KiB2622

METADATAD25-Apr-2025370 1817

MODULE_LICENSE_APACHE2D25-Apr-20250

README.mdD25-Apr-202512.4 KiB291232

TEST_MAPPINGD25-Apr-2025155 98

build.rsD25-Apr-2025799 2522

cargo_embargo.jsonD25-Apr-2025125 98

README.md

1# Ash
2
3A very lightweight wrapper around Vulkan
4
5[![Crates.io Version](https://img.shields.io/crates/v/ash.svg)](https://crates.io/crates/ash)
6[![Documentation](https://docs.rs/ash/badge.svg)](https://docs.rs/ash)
7[![Build Status](https://github.com/MaikKlein/ash/workflows/CI/badge.svg)](https://github.com/MaikKlein/ash/actions?workflow=CI)
8[![LICENSE](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE-MIT)
9[![LICENSE](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE-APACHE)
10[![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)
11[![MSRV](https://img.shields.io/badge/rustc-1.60.0+-ab6000.svg)](https://blog.rust-lang.org/2022/04/07/Rust-1.60.0.html)
12
13## Overview
14- [x] A true Vulkan API without compromises
15- [x] Convenience features without limiting functionality
16- [x] Additional type safety
17- [x] Device local function pointer loading
18- [x] No validation, everything is **unsafe**
19- [x] Generated from `vk.xml`
20- [x] Support for Vulkan `1.1`, `1.2`, `1.3`
21
22## ⚠️ Semver compatibility warning
23The Vulkan Video bindings are experimental and still seeing breaking changes in their upstream specification, and are only provided by Ash for early adopters. All related functions and types are semver-exempt [^1] (we allow breaking API changes while releasing Ash with non-breaking semver bumps).
24
25[^1]: `generator` complexity makes it so that we cannot easily hide these bindings behind a non-`default` feature flag, and they are widespread across the generated codebase.
26
27## Features
28### Explicit returns with `Result`
29```rust
30// function signature
31pub fn create_instance(&self,
32                       create_info: &vk::InstanceCreateInfo,
33                       allocation_callbacks: Option<&vk::AllocationCallbacks>)
34                       -> Result<Instance, InstanceError> { .. }
35let instance = entry.create_instance(&create_info, None)
36    .expect("Instance creation error");
37```
38
39
40### `Vec<T>` instead of mutable slices
41
42```rust
43pub fn get_swapchain_images(&self,
44                            swapchain: vk::SwapchainKHR)
45                            -> VkResult<Vec<vk::Image>>;
46let present_images = swapchain_loader.get_swapchain_images_khr(swapchain).unwrap();
47```
48*Note*: Functions don't return `Vec<T>` if this would limit the functionality. See `p_next`.
49
50### Slices
51```rust
52pub fn cmd_pipeline_barrier(&self,
53                            command_buffer: vk::CommandBuffer,
54                            src_stage_mask: vk::PipelineStageFlags,
55                            dst_stage_mask: vk::PipelineStageFlags,
56                            dependency_flags: vk::DependencyFlags,
57                            memory_barriers: &[vk::MemoryBarrier],
58                            buffer_memory_barriers: &[vk::BufferMemoryBarrier],
59                            image_memory_barriers: &[vk::ImageMemoryBarrier]);
60```
61
62### Strongly typed handles
63
64Each Vulkan handle type is exposed as a newtyped struct for improved type safety. Null handles can be constructed with
65`T::null()`, and handles may be freely converted to and from `u64` with `Handle::from_raw` and `Handle::as_raw` for
66interop with non-Ash Vulkan code.
67
68### Default implementation for all types
69```rust
70// No need to manually set the structure type
71let desc_alloc_info = vk::DescriptorSetAllocateInfo {
72    descriptor_pool: self.pool,
73    descriptor_set_count: self.layouts.len() as u32,
74    p_set_layouts: self.layouts.as_ptr(),
75    ..Default::default()
76};
77```
78### Builder pattern
79
80```rust
81// We lose all lifetime information when we call `.build()`. Be careful!
82let queue_info = [vk::DeviceQueueCreateInfo::builder()
83    .queue_family_index(queue_family_index)
84    .queue_priorities(&priorities)
85    .build()];
86
87// We don't need to call `.build()` here because builders implement `Deref`.
88let device_create_info = vk::DeviceCreateInfo::builder()
89    .queue_create_infos(&queue_info)
90    .enabled_extension_names(&device_extension_names_raw)
91    .enabled_features(&features);
92
93let device: Device = instance
94    .create_device(pdevice, &device_create_info, None)
95    .unwrap();
96```
97
98To 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`:
99
100```rust
101let queue_info = vk::DeviceQueueCreateInfo::builder()
102    .queue_family_index(queue_family_index)
103    .queue_priorities(&priorities);
104
105let device_create_info = vk::DeviceCreateInfo::builder()
106    .queue_create_infos(std::slice::from_ref(&queue_info))
107    ...;
108```
109
110Builders have an explicit lifetime, and are marked as `#[repr(transparent)]`.
111```rust
112#[repr(transparent)]
113pub struct DeviceCreateInfoBuilder<'a> {
114    inner: DeviceCreateInfo,
115    marker: ::std::marker::PhantomData<&'a ()>,
116}
117impl<'a> DeviceCreateInfoBuilder<'a> {
118    //...
119    pub fn queue_create_infos(
120        mut self,
121        queue_create_infos: &'a [DeviceQueueCreateInfo],
122    ) -> DeviceCreateInfoBuilder<'a> {...}
123    //...
124```
125
126Every 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
127to Vulkan functions.
128
129Calling `.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.
130
131
132### Pointer chains
133
134```rust
135let mut variable_pointers = vk::PhysicalDeviceVariablePointerFeatures::builder();
136let mut corner =
137    vk::PhysicalDeviceCornerSampledImageFeaturesNV::builder();
138;
139let mut device_create_info = vk::DeviceCreateInfo::builder()
140    .push_next(&mut corner)
141    .push_next(&mut variable_pointers);
142```
143
144Pointer 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.
145
146`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`.
147
148
149### Flags and constants as associated constants
150
151```rust
152// Bitflag
153vk::AccessFlags::COLOR_ATTACHMENT_READ | vk::AccessFlags::COLOR_ATTACHMENT_WRITE
154```
155
156```rust
157// Constant
158vk::PipelineBindPoint::GRAPHICS,
159```
160### Debug/Display for Flags
161
162```rust
163let flag = vk::AccessFlags::COLOR_ATTACHMENT_READ
164        | vk::AccessFlags::COLOR_ATTACHMENT_WRITE;
165println!("Debug: {:?}", flag);
166println!("Display: {}", flag);
167// Prints:
168// Debug: AccessFlags(110000000)
169// Display: COLOR_ATTACHMENT_READ | COLOR_ATTACHMENT_WRITE
170```
171
172### Function pointer loading
173Ash also takes care of loading the function pointers. Function pointers are split into 3 categories.
174
175* Entry: Loads the Vulkan library. Needs to outlive `Instance` and `Device`.
176* Instance: Loads instance level functions. Needs to outlive the `Device`s it has created.
177* Device: Loads device **local** functions.
178
179The loader is just one possible implementation:
180
181* Device level functions are retrieved on a per device basis.
182* Everything is loaded by default, functions that failed to load are initialized to a function that always panics.
183* Do not call Vulkan 1.1 functions if you have created a 1.0 instance. Doing so will result in a panic.
184
185Custom loaders can be implemented.
186
187### Extension loading
188Additionally, 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).
189```rust
190use ash::extensions::khr::Swapchain;
191let swapchain_loader = Swapchain::new(&instance, &device);
192let swapchain = swapchain_loader.create_swapchain(&swapchain_create_info).unwrap();
193```
194
195### Raw function pointers
196
197Raw function pointers are available, if something hasn't been exposed yet in the higher level API. Please open an issue if anything is missing.
198
199```rust
200device.fp_v1_0().destroy_device(...);
201```
202
203### Support for extension names
204```rust
205use ash::extensions::{Swapchain, XlibSurface, Surface, DebugReport};
206#[cfg(all(unix, not(target_os = "android")))]
207fn extension_names() -> Vec<*const i8> {
208    vec![
209        Surface::name().as_ptr(),
210        XlibSurface::name().as_ptr(),
211        DebugReport::name().as_ptr()
212    ]
213}
214```
215
216### Implicit handles
217Handles from Instance or Device are passed implicitly.
218```rust
219pub fn create_command_pool(&self,
220                           create_info: &vk::CommandPoolCreateInfo)
221                           -> VkResult<vk::CommandPool>;
222
223let pool = device.create_command_pool(&pool_create_info).unwrap();
224```
225
226### Optional linking
227
228The default `loaded` cargo feature will dynamically load the default Vulkan library for the current platform with `Entry::load`, meaning that the build environment does not have to have Vulkan development packages installed.
229
230If, on the other hand, your application cannot handle Vulkan being missing at runtime, you can instead enable the `linked` feature, which will link your binary with the Vulkan loader directly and expose the infallible `Entry::linked`.
231
232## Example
233You can find the examples [here](https://github.com/MaikKlein/ash/tree/master/examples).
234All 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/)
235#### Windows
236Make sure that you have a Vulkan ready driver and install the [LunarG Vulkan SDK](https://lunarg.com/vulkan-sdk/).
237#### Linux
238Make 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.
239#### macOS
240Install the [LunarG Vulkan SDK](https://lunarg.com/vulkan-sdk/). The installer puts the SDK in `$HOME/VulkanSDK/<version>` by default. You will need to set the following environment variables when running cargo:
241```sh
242VULKAN_SDK=$HOME/VulkanSDK/<version>/macOS \
243DYLD_FALLBACK_LIBRARY_PATH=$VULKAN_SDK/lib \
244VK_ICD_FILENAMES=$VULKAN_SDK/share/vulkan/icd.d/MoltenVK_icd.json \
245VK_LAYER_PATH=$VULKAN_SDK/share/vulkan/explicit_layer.d \
246cargo run ...
247```
248
249### [Triangle](https://github.com/MaikKlein/ash/blob/master/examples/src/bin/triangle.rs)
250Displays a triangle with vertex colors.
251```
252cd examples
253cargo run --bin triangle
254```
255
256![screenshot](http://i.imgur.com/PQZcL6w.jpg)
257
258### [Texture](https://github.com/MaikKlein/ash/blob/master/examples/src/bin/texture.rs)
259Displays a texture on a quad.
260```
261cd examples
262cargo run --bin texture
263```
264![texture](http://i.imgur.com/trow00H.png)
265
266## Useful resources
267
268### Examples
269
270* [vulkan-tutorial-rust](https://github.com/Usami-Renko/vulkan-tutorial-rust) - A port of [vulkan-tutorial.com](https://vulkan-tutorial.com).
271* [ash-sample-progression](https://github.com/bzm3r/ash-sample-progression) - A port of the LunarG examples.
272* [ash-nv-rt](https://github.com/gwihlidal/ash-nv-rt) A raytracing example for ash.
273
274### Utility libraries
275* [vk-sync](https://github.com/gwihlidal/vk-sync-rs) - Simplified Vulkan synchronization logic, written in rust.
276* [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.
277* [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
278* [lahar](https://github.com/Ralith/lahar) - Tools for asynchronously uploading data to a Vulkan device.
279
280### Libraries that use ash
281* [gfx-rs](https://github.com/gfx-rs/gfx) - gfx-rs is a low-level, cross-platform graphics abstraction library in Rust.
282
283## A thanks to
284
285* [Api with no secrets](https://software.intel.com/en-us/articles/api-without-secrets-introduction-to-vulkan-part-1)
286* [Vulkan tutorial](http://jhenriques.net/development.html)
287* [Vulkan examples](https://github.com/SaschaWillems/Vulkan)
288* [Vulkan tutorial](https://vulkan-tutorial.com/)
289* [Vulkano](https://github.com/vulkano-rs/vulkano)
290* [vk-rs](https://github.com/Osspial/vk-rs)
291