#![deny(clippy::use_self)] #![warn(trivial_casts, trivial_numeric_casts)] #![allow( clippy::too_many_arguments, clippy::missing_safety_doc, clippy::upper_case_acronyms )] #![cfg_attr(docsrs, feature(doc_cfg))] //! # Vulkan API //! //! //! //! ## Examples //! //! ```no_run //! use ash::{vk, Entry}; //! # fn main() -> Result<(), Box> { //! let entry = Entry::linked(); //! let app_info = vk::ApplicationInfo { //! api_version: vk::make_api_version(0, 1, 0, 0), //! ..Default::default() //! }; //! let create_info = vk::InstanceCreateInfo { //! p_application_info: &app_info, //! ..Default::default() //! }; //! let instance = unsafe { entry.create_instance(&create_info, None)? }; //! # Ok(()) } //! ``` //! //! ## Getting started //! //! Load the Vulkan library linked at compile time using [`Entry::linked()`], or load it at runtime //! using [`Entry::load()`], which uses `libloading`. If you want to perform entry point loading //! yourself, call [`Entry::from_static_fn()`]. //! //! ## Crate features //! //! * **debug** (default): Whether Vulkan structs should implement `Debug`. //! * **loaded** (default): Support searching for the Vulkan loader manually at runtime. //! * **linked**: Link the Vulkan loader at compile time. pub use crate::device::Device; pub use crate::entry::Entry; #[cfg(feature = "loaded")] pub use crate::entry::LoadingError; pub use crate::instance::Instance; mod device; mod entry; mod instance; pub mod prelude; pub mod util; /// Raw Vulkan bindings and types, generated from `vk.xml` #[macro_use] pub mod vk; // macros of vk need to be defined beforehand /// Wrappers for Vulkan extensions pub mod extensions; pub trait RawPtr { fn as_raw_ptr(&self) -> *const T; } impl<'r, T> RawPtr for Option<&'r T> { fn as_raw_ptr(&self) -> *const T { match *self { Some(inner) => inner, _ => ::std::ptr::null(), } } } /// Given a mutable raw pointer to a type with an `s_type` member such as [`vk::BaseOutStructure`], /// match on a set of Vulkan structures. The struct will be rebound to the given variable of the /// type of the given Vulkan structure. /// /// Note that all match bodies have to be enclosed by curly braces due to macro parsing limitations. /// It is unfortunately not possible to write `x @ ash::vk::SomeStruct => one_line_expression(),`. /// /// ``` /// let mut info = ash::vk::DeviceCreateInfo::default(); /// let info: *mut ash::vk::BaseOutStructure = <*mut _>::cast(&mut info); /// unsafe { /// ash::match_out_struct!(match info { /// info @ ash::vk::DeviceQueueCreateInfo => { /// dbg!(&info); // Unreachable /// } /// info @ ash::vk::DeviceCreateInfo => { /// dbg!(&info); /// } /// }) /// } /// ``` /// /// In addition this macro propagates implicit return values just like normal `match` blocks, as /// long as a default value or expression is provided in the "any" match arm /// (`_ => { some_value() }`). For the time being said arm must be wrapped in curly braces; an /// expression like `_ => None` is not yet supported. /// /// ``` /// # let mut info = ash::vk::DeviceCreateInfo::default(); /// # let info: *mut ash::vk::BaseOutStructure = <*mut _>::cast(&mut info); /// let device_create_flags: Option = unsafe { /// ash::match_out_struct!(match info { /// info @ ash::vk::DeviceQueueCreateInfo => { /// dbg!(&info); // Unreachable /// Some(ash::vk::DeviceCreateFlags::empty()) /// } /// info @ ash::vk::DeviceCreateInfo => { /// dbg!(&info); /// Some(info.flags) /// } /// _ => { /// None /// } /// }) /// }; /// ``` #[macro_export] macro_rules! match_out_struct { (match $p:ident { $($bind:ident @ $ty:path => $body:block $(,)?)+ $(_ => $any:block $(,)?)? }) => { match std::ptr::addr_of!((*$p).s_type).read() { $(<$ty as $crate::vk::TaggedStructure>::STRUCTURE_TYPE => { let $bind = $p .cast::<$ty>() .as_mut() .unwrap(); $body }),+ _ => { $($any)? } } }; } /// Given an immutable raw pointer to a type with an `s_type` member such as [`vk::BaseInStructure`], /// match on a set of Vulkan structures. The struct will be rebound to the given variable of the /// type of the given Vulkan structure. /// /// Note that all match bodies have to be enclosed by curly braces due to macro parsing limitations. /// It is unfortunately not possible to write `x @ ash::vk::SomeStruct => one_line_expression(),`. /// /// ``` /// let info = ash::vk::DeviceCreateInfo::default(); /// let info: *const ash::vk::BaseInStructure = <*const _>::cast(&info); /// unsafe { /// ash::match_in_struct!(match info { /// info @ ash::vk::DeviceQueueCreateInfo => { /// dbg!(&info); // Unreachable /// } /// info @ ash::vk::DeviceCreateInfo => { /// dbg!(&info); /// } /// }) /// } /// ``` /// /// See the [`match_out_struct!`] documentation for an example with implicit return values. #[macro_export] macro_rules! match_in_struct { (match $p:ident { $($bind:ident @ $ty:path => $body:block $(,)?)+ $(_ => $any:block $(,)?)? }) => { match std::ptr::addr_of!((*$p).s_type).read() { $(<$ty as $crate::vk::TaggedStructure>::STRUCTURE_TYPE => { let $bind = $p .cast::<$ty>() .as_ref() .unwrap(); $body }),+ _ => { $($any)? } } }; } #[cfg(test)] mod tests { use super::vk; #[test] fn test_ptr_chains() { let mut variable_pointers = vk::PhysicalDeviceVariablePointerFeatures::builder(); let mut corner = vk::PhysicalDeviceCornerSampledImageFeaturesNV::builder(); let chain = vec![ <*mut _>::cast(&mut variable_pointers), <*mut _>::cast(&mut corner), ]; let mut device_create_info = vk::DeviceCreateInfo::builder() .push_next(&mut corner) .push_next(&mut variable_pointers); let chain2: Vec<*mut vk::BaseOutStructure> = unsafe { vk::ptr_chain_iter(&mut device_create_info) .skip(1) .collect() }; assert_eq!(chain, chain2); } }