ash | ||
examples | ||
generator | ||
.gitignore | ||
.gitmodules | ||
.travis.yml | ||
appveyor.yml | ||
Cargo.toml | ||
Changelog.md | ||
LICENSE-APACHE | ||
LICENSE-MIT | ||
README.md | ||
rustfmt.toml |
Ash
A very lightweight wrapper around Vulkan
Overview
- A true Vulkan API without compromises
- Convenience features that don't limit the functionality
- Additional type safety
- Device local function pointer loading
- No validation, everything is unsafe
- Generated from
vk.xml
Features
Explicit returns with Result
// function signature
pub fn create_instance(&self,
create_info: &vk::InstanceCreateInfo,
allocation_callbacks: Option<&vk::AllocationCallbacks>)
-> Result<Instance, InstanceError> { .. }
let instance = entry.create_instance(&create_info, None)
.expect("Instance creation error");
Vec<T>
instead of mutable slices
pub fn get_swapchain_images_khr(&self,
swapchain: vk::SwapchainKHR)
-> VkResult<Vec<vk::Image>>;
let present_images = swapchain_loader.get_swapchain_images_khr(swapchain).unwrap();
Note: Functions don't return Vec<T>
if this would limit the functionality. See p_next
.
Slices
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]);
Default implementation for all types
// 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()
};
Builder pattern
let pipeline_vertex_input_state_create_info = vk::PipelineVertexInputStateCreateInfo::builder()
.vertex_binding_descriptions(&Vertex::binding_descriptions())
.vertex_attribute_descriptions(&Vertex::attribute_descriptions()).build();
Note: No validation is done, the lifetimes only have to live as long as the builder object. It is the responsibility of the user to make sure that the pointers are valid.
Flags and constants as associated constants
// Bitflag
vk::AccessFlags::COLOR_ATTACHMENT_READ | vk::AccessFlags::COLOR_ATTACHMENT_WRITE
// Constant
vk::PipelineBindPoint::GRAPHICS,
Debug/Display for Flags
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
Interop
Vulkan objects inside Ash can be constructed from raw values with Object::from:raw
. Useful if you need to interact with a C library.
PipelineBindPoint::from_raw(bindpoint);
Function pointer loading
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 for more information.
Extension loading
Additionally, every Vulkan extension has to be loaded explicitly. You can find all extensions under ash::extensions.
use ash::extensions::Swapchain;
let swapchain_loader = Swapchain::new(&instance, &device);
let swapchain = swapchain_loader.create_swapchain_khr(&swapchain_create_info).unwrap();
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.
device.fp_v1_0().destroy_device(...);
Support for extension names
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()
]
}
Implicit handles
Handles from Instance or Device are passed implicitly.
pub fn create_command_pool(&self,
create_info: &vk::CommandPoolCreateInfo)
-> VkResult<vk::CommandPool>;
let pool = device.create_command_pool(&pool_create_info).unwrap();
Example
You can find the examples here.
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
Windows
Make sure that you have a Vulkan ready driver and install the LunarG Vulkan SDK.
Linux
Make sure that you have a Vulkan ready driver and install the LunarG Vulkan SDK. You also have to add the library and layers to your path. Have a look at my post if you are unsure how to do that.
Triangle
Displays a triangle with vertex colors.
cd examples
cargo run --bin triangle
macOS
Install the LunarG 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
Texture
Displays a texture on a quad.
cd examples
cargo run --bin texture