2017-04-07 18:04:14 +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
2016-12-10 06:38:22 +11: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:49:49 +11:00
[![Documentation ](https://docs.rs/ash/badge.svg )](https://docs.rs/ash)
2016-12-10 06:38:22 +11:00
[![Build Status ](https://travis-ci.org/MaikKlein/ash.svg?branch=master )](https://travis-ci.org/MaikKlein/ash)
2016-12-26 12:17:56 +11:00
[![Build status ](https://ci.appveyor.com/api/projects/status/ed7757as3a4ebexn/branch/master?svg=true )](https://ci.appveyor.com/project/MaikKlein/ash/branch/master)
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-12-10 06:45:09 +11:00
[![Crates.io Version ](https://img.shields.io/crates/v/ash.svg )](https://crates.io/crates/ash)
2016-12-23 12:01:36 +11:00
[![ ](https://tokei.rs/b1/github/maikklein/ash )](https://github.com/MaikKlein/ash)
2016-08-14 09:13:39 +10:00
2016-12-10 06:19:54 +11:00
## Stable yet?
2016-12-29 18:06:17 +11:00
I don't expect any big changes anymore. The library will still remain < 1.0 until I had time to use it in a real project . If you encounter any problems , feel free to open an [Issue ](https://github.com/MaikKlein/ash/issues ).
2016-12-10 05:25:48 +11:00
2016-12-10 05:30:05 +11:00
## Why Ash?
2016-12-24 08:02:03 +11:00
- [x] Lightweight Vulkan wrapper
- [x] Low overhead
2017-01-01 18:31:13 +11:00
- [x] Additional type safety
- [x] Trait based, version specific loader
2016-12-10 05:25:48 +11:00
2016-12-24 08:02:03 +11:00
## What does it do?
2016-12-28 14:31:48 +11:00
### Explicit returns with `Result`
2016-12-10 05:25:48 +11:00
Functions return a `type VkResult<T> = Result<T, vk::Result>` instead of an error code. No mutable references for the output are required.
```Rust
2016-12-29 18:06:17 +11:00
pub fn create_instance(& self,
create_info: & vk::InstanceCreateInfo,
allocation_callbacks: Option< & vk::AllocationCallbacks>)
-> 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
```
Always returns a `Vec<T>` for functions that output multiple values.
```Rust
2016-12-24 07:41:16 +11:00
pub fn get_swapchain_images_khr(& 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
```
2016-12-28 14:31:48 +11:00
### Slices
2016-12-10 05:30:05 +11:00
Ash always uses slices in functions.
2016-12-10 05:25:48 +11:00
```Rust
2016-12-24 07:41:16 +11:00
// C
void vkCmdPipelineBarrier(
VkCommandBuffer commandBuffer,
VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask,
VkDependencyFlags dependencyFlags,
uint32_t memoryBarrierCount,
const VkMemoryBarrier* pMemoryBarriers,
uint32_t bufferMemoryBarrierCount,
const VkBufferMemoryBarrier* pBufferMemoryBarriers,
uint32_t imageMemoryBarrierCount,
const VkImageMemoryBarrier* pImageMemoryBarriers);
2016-12-10 05:25:48 +11:00
2016-12-24 07:41:16 +11:00
// Rust
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-24 07:41:16 +11:00
device.cmd_pipeline_barrier(setup_command_buffer,
vk::PIPELINE_STAGE_TOP_OF_PIPE_BIT,
vk::PIPELINE_STAGE_TOP_OF_PIPE_BIT,
vk::DependencyFlags::empty(),
& [],
& [],
&[layout_transition_barrier]);
2016-12-10 05:39:16 +11:00
2016-12-24 07:41:16 +11:00
// or
2016-12-10 05:39:16 +11:00
2016-12-24 07:41:16 +11:00
let slice = device.map_memory::< Vertex > (vertex_input_buffer_memory,
0,
vertex_input_buffer_info.size,
vk::MemoryMapFlags::empty())
.unwrap();
slice.copy_from_slice(&vertices);
2016-12-10 05:25:48 +11:00
```
2016-12-28 14:31:48 +11:00
### Type safety
2016-12-10 05:25:48 +11:00
Ash still uses raw Vulkan structs. The only difference is type safety. Everything that can be an enum is an enum like `vk::StructureType` , flags are implemented similar to the `Bitflags` crate. Ash also follows the Rust style guide. The reason that Ash uses raw Vulkan structs is to be extensible, just like the Vulkan spec.
```Rust
2016-12-24 07:41:16 +11:00
let pool_create_info = vk::CommandPoolCreateInfo {
s_type: vk::StructureType::CommandPoolCreateInfo,
p_next: ptr::null(),
flags: vk::COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
queue_family_index: queue_family_index,
};
2016-12-29 18:06:17 +11:00
let pool = device.create_command_pool(& pool_create_info, None).unwrap();
2016-12-10 05:25:48 +11:00
```
2016-12-28 14:31:48 +11:00
2017-01-05 18:20:57 +11:00
Additionally pointers like `Instance` , `Device` , `Queue` etc are hidden behind a type. Those pointers can only be constructed from within `Ash` which eliminates some invalid API usage and has the benefit of making some functions in Vulkan **safe** .
2016-12-28 14:31:48 +11:00
### Function pointer loading
2017-01-05 18:22:18 +11:00
Ash also takes care of loading the function pointers. Function pointers are split into 3 categories, Entry, Instance and Device. The reason for not loading it into a global is that in Vulkan you can have multiple devices and each device will load its own function pointers to achieve better performance. Click [here ](https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/blob/master/loader/LoaderAndLayerInterface.md ) for more information.
2017-01-01 18:31:13 +11:00
Ash also manages multiple versions of Vulkan without any breakage. You will never run into any runtime error because you tried to access a function pointer that failed to load. Function pointers either load successfully or fail and return an error.
2016-12-10 05:25:48 +11:00
```Rust
2017-01-05 18:06:32 +11:00
use ash::{Device, Instance};
2017-01-01 18:31:13 +11:00
// Specifies the version that you want to load
use ash::version::V1_0;
// Those traits implement the version specific functions
2017-01-05 18:05:54 +11:00
use ash::version::{InstanceV1_0, DeviceV1_0, EntryV1_0};
2017-01-01 18:56:38 +11:00
let entry = Entry::< V1_0 > ::new().unwrap();
2017-01-01 18:31:13 +11:00
let instance = entry.create_instance(...).expect("Instance creation error.");
let device = instance.create_device(...).expect("Device creation error.");
```
2017-01-01 18:37:12 +11:00
A `V1_X` struct is used to indicate the version.
2017-01-01 18:31:13 +11:00
```Rust
// Define your types
type YourDevice = Device< V1_0 > ;
type YourInstance = Instance< V1_0 > ;
```
2017-01-01 18:37:12 +11:00
You can upgrade to a future version without any breakage.
2017-01-01 18:31:13 +11:00
```Rust
// For example, switching from V1_0 to V1_3 will not cause any breakage.
type YourDevice = Device< V1_3 > ;
type YourInstance = Instance< V1_3 > ;
```
A newer version can always be converted to an older version.
```Rust
let newer_device: Device< V1_5 > = ...;
let older_device: Device< V1_0 > = newer_device.into();
```
Or specify the *minimum* version that you require with a trait.
```Rust
fn do_something_with_a_device< Device: DeviceV1_0 > (device: & Device){}
2016-12-24 07:41:16 +11:00
```
2016-12-28 14:31:48 +11:00
### Extension loading
2017-04-16 21:05:45 +10: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 ). You still have to tell Vulkan which instance or device extensions you want to load.
2016-12-24 07:41:16 +11:00
```Rust
use ash::extensions::Swapchain;
let swapchain_loader = Swapchain::new(& instance, & device).expect("Unable to load swapchain");
let swapchain = swapchain_loader.create_swapchain_khr(&swapchain_create_info).unwrap();
2016-12-10 05:25:48 +11:00
```
2016-12-28 14:31:48 +11:00
2017-01-01 18:31:13 +11:00
### Support for extension names
```Rust
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
2016-12-29 18:06:17 +11:00
You don't have to pass an Instance or Device handle anymore, this is done implicitly for you. This makes sure that you will always use the most optimal implementation for your `Device` .
2016-12-10 05:25:48 +11:00
```Rust
2016-12-24 07:41:16 +11:00
// C
VkResult vkCreateCommandPool(
VkDevice device,
const VkCommandPoolCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkCommandPool* pCommandPool);
2016-12-10 05:25:48 +11:00
2016-12-24 07:41:16 +11:00
// Rust
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
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.
2016-12-26 00:49:20 +11:00
### [Triangle](https://github.com/MaikKlein/ash/blob/master/examples/src/bin/triangle.rs)
2016-12-26 11:23:19 +11:00
Displays a triangle with vertex colors.
2016-12-10 07:01:44 +11:00
```
2016-12-26 00:49:20 +11:00
cd examples
cargo run --bin triangle
2016-12-10 07:01:44 +11:00
```
2016-12-10 05:39:16 +11:00
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
2016-12-10 05:47:29 +11:00
## Roadmap
2016-12-10 05:25:48 +11:00
2016-12-23 21:41:43 +11:00
### Extensions
- [x] Swapchain
- [x] Surface
- [x] XlibSurface
- [x] DebugReport
2016-12-29 18:06:17 +11:00
- [x] Win32Surface
- [x] MirSurface
- [x] XcbSurface
- [x] AndroidSurface
- [x] WaylandSurface
2016-12-23 21:43:44 +11:00
- [ ] Display
2016-12-23 21:41:43 +11:00
2016-12-10 05:47:29 +11:00
### In progress
2016-12-10 05:25:48 +11:00
- Wrapping the complete spec
2017-01-01 19:00:55 +11:00
- Version specific loader
2016-12-10 05:25:48 +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 )
* [Vulkan tutorial ](http://av.dfki.de/~jhenriques/development.html )
* [Vulkan examples ](https://github.com/SaschaWillems/Vulkan )
2016-12-10 07:05:19 +11:00
* [Vulkan tutorial ](https://vulkan-tutorial.com/ )
2016-12-10 07:04:31 +11:00
* [Vulkano ](https://github.com/tomaka/vulkano/ )
* [vk-rs ](https://github.com/Osspial/vk-rs )