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