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