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}