1 #![deny(clippy::use_self)] 2 #![warn(trivial_casts, trivial_numeric_casts)] 3 #![allow( 4 clippy::too_many_arguments, 5 clippy::missing_safety_doc, 6 clippy::upper_case_acronyms 7 )] 8 #![cfg_attr(docsrs, feature(doc_cfg))] 9 //! # Vulkan API 10 //! 11 //! <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/html/index.html> 12 //! 13 //! ## Examples 14 //! 15 //! ```no_run 16 //! use ash::{vk, Entry}; 17 //! # fn main() -> Result<(), Box<dyn std::error::Error>> { 18 //! let entry = Entry::linked(); 19 //! let app_info = vk::ApplicationInfo { 20 //! api_version: vk::make_api_version(0, 1, 0, 0), 21 //! ..Default::default() 22 //! }; 23 //! let create_info = vk::InstanceCreateInfo { 24 //! p_application_info: &app_info, 25 //! ..Default::default() 26 //! }; 27 //! let instance = unsafe { entry.create_instance(&create_info, None)? }; 28 //! # Ok(()) } 29 //! ``` 30 //! 31 //! ## Getting started 32 //! 33 //! Load the Vulkan library linked at compile time using [`Entry::linked()`], or load it at runtime 34 //! using [`Entry::load()`], which uses `libloading`. If you want to perform entry point loading 35 //! yourself, call [`Entry::from_static_fn()`]. 36 //! 37 //! ## Crate features 38 //! 39 //! * **debug** (default): Whether Vulkan structs should implement `Debug`. 40 //! * **loaded** (default): Support searching for the Vulkan loader manually at runtime. 41 //! * **linked**: Link the Vulkan loader at compile time. 42 43 pub use crate::device::Device; 44 pub use crate::entry::Entry; 45 #[cfg(feature = "loaded")] 46 pub use crate::entry::LoadingError; 47 pub use crate::instance::Instance; 48 49 mod device; 50 mod entry; 51 mod instance; 52 pub mod prelude; 53 pub mod util; 54 /// Raw Vulkan bindings and types, generated from `vk.xml` 55 #[macro_use] 56 pub mod vk; 57 58 // macros of vk need to be defined beforehand 59 /// Wrappers for Vulkan extensions 60 pub mod extensions; 61 62 pub trait RawPtr<T> { as_raw_ptr(&self) -> *const T63 fn as_raw_ptr(&self) -> *const T; 64 } 65 66 impl<'r, T> RawPtr<T> for Option<&'r T> { as_raw_ptr(&self) -> *const T67 fn as_raw_ptr(&self) -> *const T { 68 match *self { 69 Some(inner) => inner, 70 _ => ::std::ptr::null(), 71 } 72 } 73 } 74 75 /// Given a mutable raw pointer to a type with an `s_type` member such as [`vk::BaseOutStructure`], 76 /// match on a set of Vulkan structures. The struct will be rebound to the given variable of the 77 /// type of the given Vulkan structure. 78 /// 79 /// Note that all match bodies have to be enclosed by curly braces due to macro parsing limitations. 80 /// It is unfortunately not possible to write `x @ ash::vk::SomeStruct => one_line_expression(),`. 81 /// 82 /// ``` 83 /// let mut info = ash::vk::DeviceCreateInfo::default(); 84 /// let info: *mut ash::vk::BaseOutStructure = <*mut _>::cast(&mut info); 85 /// unsafe { 86 /// ash::match_out_struct!(match info { 87 /// info @ ash::vk::DeviceQueueCreateInfo => { 88 /// dbg!(&info); // Unreachable 89 /// } 90 /// info @ ash::vk::DeviceCreateInfo => { 91 /// dbg!(&info); 92 /// } 93 /// }) 94 /// } 95 /// ``` 96 /// 97 /// In addition this macro propagates implicit return values just like normal `match` blocks, as 98 /// long as a default value or expression is provided in the "any" match arm 99 /// (`_ => { some_value() }`). For the time being said arm must be wrapped in curly braces; an 100 /// expression like `_ => None` is not yet supported. 101 /// 102 /// ``` 103 /// # let mut info = ash::vk::DeviceCreateInfo::default(); 104 /// # let info: *mut ash::vk::BaseOutStructure = <*mut _>::cast(&mut info); 105 /// let device_create_flags: Option<ash::vk::DeviceCreateFlags> = unsafe { 106 /// ash::match_out_struct!(match info { 107 /// info @ ash::vk::DeviceQueueCreateInfo => { 108 /// dbg!(&info); // Unreachable 109 /// Some(ash::vk::DeviceCreateFlags::empty()) 110 /// } 111 /// info @ ash::vk::DeviceCreateInfo => { 112 /// dbg!(&info); 113 /// Some(info.flags) 114 /// } 115 /// _ => { 116 /// None 117 /// } 118 /// }) 119 /// }; 120 /// ``` 121 #[macro_export] 122 macro_rules! match_out_struct { 123 (match $p:ident { $($bind:ident @ $ty:path => $body:block $(,)?)+ $(_ => $any:block $(,)?)? }) => { 124 match std::ptr::addr_of!((*$p).s_type).read() { 125 $(<$ty as $crate::vk::TaggedStructure>::STRUCTURE_TYPE => { 126 let $bind = $p 127 .cast::<$ty>() 128 .as_mut() 129 .unwrap(); 130 $body 131 }),+ 132 _ => { $($any)? } 133 } 134 }; 135 } 136 137 /// Given an immutable raw pointer to a type with an `s_type` member such as [`vk::BaseInStructure`], 138 /// match on a set of Vulkan structures. The struct will be rebound to the given variable of the 139 /// type of the given Vulkan structure. 140 /// 141 /// Note that all match bodies have to be enclosed by curly braces due to macro parsing limitations. 142 /// It is unfortunately not possible to write `x @ ash::vk::SomeStruct => one_line_expression(),`. 143 /// 144 /// ``` 145 /// let info = ash::vk::DeviceCreateInfo::default(); 146 /// let info: *const ash::vk::BaseInStructure = <*const _>::cast(&info); 147 /// unsafe { 148 /// ash::match_in_struct!(match info { 149 /// info @ ash::vk::DeviceQueueCreateInfo => { 150 /// dbg!(&info); // Unreachable 151 /// } 152 /// info @ ash::vk::DeviceCreateInfo => { 153 /// dbg!(&info); 154 /// } 155 /// }) 156 /// } 157 /// ``` 158 /// 159 /// See the [`match_out_struct!`] documentation for an example with implicit return values. 160 #[macro_export] 161 macro_rules! match_in_struct { 162 (match $p:ident { $($bind:ident @ $ty:path => $body:block $(,)?)+ $(_ => $any:block $(,)?)? }) => { 163 match std::ptr::addr_of!((*$p).s_type).read() { 164 $(<$ty as $crate::vk::TaggedStructure>::STRUCTURE_TYPE => { 165 let $bind = $p 166 .cast::<$ty>() 167 .as_ref() 168 .unwrap(); 169 $body 170 }),+ 171 _ => { $($any)? } 172 } 173 }; 174 } 175 176 #[cfg(test)] 177 mod tests { 178 use super::vk; 179 #[test] test_ptr_chains()180 fn test_ptr_chains() { 181 let mut variable_pointers = vk::PhysicalDeviceVariablePointerFeatures::builder(); 182 let mut corner = vk::PhysicalDeviceCornerSampledImageFeaturesNV::builder(); 183 let chain = vec![ 184 <*mut _>::cast(&mut variable_pointers), 185 <*mut _>::cast(&mut corner), 186 ]; 187 let mut device_create_info = vk::DeviceCreateInfo::builder() 188 .push_next(&mut corner) 189 .push_next(&mut variable_pointers); 190 let chain2: Vec<*mut vk::BaseOutStructure> = unsafe { 191 vk::ptr_chain_iter(&mut device_create_info) 192 .skip(1) 193 .collect() 194 }; 195 assert_eq!(chain, chain2); 196 } 197 } 198