ash/lib.rs
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
43pub use crate::device::Device;
44pub use crate::entry::Entry;
45#[cfg(feature = "loaded")]
46pub use crate::entry::LoadingError;
47pub use crate::instance::Instance;
48
49mod device;
50mod entry;
51mod instance;
52pub mod prelude;
53pub mod util;
54/// Raw Vulkan bindings and types, generated from `vk.xml`
55#[macro_use]
56pub mod vk;
57
58// macros of vk need to be defined beforehand
59/// Wrappers for Vulkan extensions
60pub mod extensions;
61
62pub trait RawPtr<T> {
63 fn as_raw_ptr(&self) -> *const T;
64}
65
66impl<'r, T> RawPtr<T> for Option<&'r T> {
67 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]
122macro_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]
161macro_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)]
177mod tests {
178 use super::vk;
179 #[test]
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}