| #![deny(clippy::use_self)] |
| #![warn(trivial_casts, trivial_numeric_casts)] |
| #![allow( |
| clippy::too_many_arguments, |
| clippy::missing_safety_doc, |
| clippy::upper_case_acronyms |
| )] |
| #![cfg_attr(docsrs, feature(doc_cfg))] |
| //! # Vulkan API |
| //! |
| //! <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/html/index.html> |
| //! |
| //! ## Examples |
| //! |
| //! ```no_run |
| //! use ash::{vk, Entry}; |
| //! # fn main() -> Result<(), Box<dyn std::error::Error>> { |
| //! let entry = Entry::linked(); |
| //! let app_info = vk::ApplicationInfo { |
| //! api_version: vk::make_api_version(0, 1, 0, 0), |
| //! ..Default::default() |
| //! }; |
| //! let create_info = vk::InstanceCreateInfo { |
| //! p_application_info: &app_info, |
| //! ..Default::default() |
| //! }; |
| //! let instance = unsafe { entry.create_instance(&create_info, None)? }; |
| //! # Ok(()) } |
| //! ``` |
| //! |
| //! ## Getting started |
| //! |
| //! Load the Vulkan library linked at compile time using [`Entry::linked()`], or load it at runtime |
| //! using [`Entry::load()`], which uses `libloading`. If you want to perform entry point loading |
| //! yourself, call [`Entry::from_static_fn()`]. |
| //! |
| //! ## Crate features |
| //! |
| //! * **debug** (default): Whether Vulkan structs should implement `Debug`. |
| //! * **loaded** (default): Support searching for the Vulkan loader manually at runtime. |
| //! * **linked**: Link the Vulkan loader at compile time. |
| |
| pub use crate::device::Device; |
| pub use crate::entry::Entry; |
| #[cfg(feature = "loaded")] |
| pub use crate::entry::LoadingError; |
| pub use crate::instance::Instance; |
| |
| mod device; |
| mod entry; |
| mod instance; |
| pub mod prelude; |
| pub mod util; |
| /// Raw Vulkan bindings and types, generated from `vk.xml` |
| #[macro_use] |
| pub mod vk; |
| |
| // macros of vk need to be defined beforehand |
| /// Wrappers for Vulkan extensions |
| pub mod extensions; |
| |
| pub trait RawPtr<T> { |
| fn as_raw_ptr(&self) -> *const T; |
| } |
| |
| impl<'r, T> RawPtr<T> for Option<&'r T> { |
| fn as_raw_ptr(&self) -> *const T { |
| match *self { |
| Some(inner) => inner, |
| _ => ::std::ptr::null(), |
| } |
| } |
| } |
| |
| /// Given a mutable raw pointer to a type with an `s_type` member such as [`vk::BaseOutStructure`], |
| /// match on a set of Vulkan structures. The struct will be rebound to the given variable of the |
| /// type of the given Vulkan structure. |
| /// |
| /// Note that all match bodies have to be enclosed by curly braces due to macro parsing limitations. |
| /// It is unfortunately not possible to write `x @ ash::vk::SomeStruct => one_line_expression(),`. |
| /// |
| /// ``` |
| /// let mut info = ash::vk::DeviceCreateInfo::default(); |
| /// let info: *mut ash::vk::BaseOutStructure = <*mut _>::cast(&mut info); |
| /// unsafe { |
| /// ash::match_out_struct!(match info { |
| /// info @ ash::vk::DeviceQueueCreateInfo => { |
| /// dbg!(&info); // Unreachable |
| /// } |
| /// info @ ash::vk::DeviceCreateInfo => { |
| /// dbg!(&info); |
| /// } |
| /// }) |
| /// } |
| /// ``` |
| /// |
| /// In addition this macro propagates implicit return values just like normal `match` blocks, as |
| /// long as a default value or expression is provided in the "any" match arm |
| /// (`_ => { some_value() }`). For the time being said arm must be wrapped in curly braces; an |
| /// expression like `_ => None` is not yet supported. |
| /// |
| /// ``` |
| /// # let mut info = ash::vk::DeviceCreateInfo::default(); |
| /// # let info: *mut ash::vk::BaseOutStructure = <*mut _>::cast(&mut info); |
| /// let device_create_flags: Option<ash::vk::DeviceCreateFlags> = unsafe { |
| /// ash::match_out_struct!(match info { |
| /// info @ ash::vk::DeviceQueueCreateInfo => { |
| /// dbg!(&info); // Unreachable |
| /// Some(ash::vk::DeviceCreateFlags::empty()) |
| /// } |
| /// info @ ash::vk::DeviceCreateInfo => { |
| /// dbg!(&info); |
| /// Some(info.flags) |
| /// } |
| /// _ => { |
| /// None |
| /// } |
| /// }) |
| /// }; |
| /// ``` |
| #[macro_export] |
| macro_rules! match_out_struct { |
| (match $p:ident { $($bind:ident @ $ty:path => $body:block $(,)?)+ $(_ => $any:block $(,)?)? }) => { |
| match std::ptr::addr_of!((*$p).s_type).read() { |
| $(<$ty as $crate::vk::TaggedStructure>::STRUCTURE_TYPE => { |
| let $bind = $p |
| .cast::<$ty>() |
| .as_mut() |
| .unwrap(); |
| $body |
| }),+ |
| _ => { $($any)? } |
| } |
| }; |
| } |
| |
| /// Given an immutable raw pointer to a type with an `s_type` member such as [`vk::BaseInStructure`], |
| /// match on a set of Vulkan structures. The struct will be rebound to the given variable of the |
| /// type of the given Vulkan structure. |
| /// |
| /// Note that all match bodies have to be enclosed by curly braces due to macro parsing limitations. |
| /// It is unfortunately not possible to write `x @ ash::vk::SomeStruct => one_line_expression(),`. |
| /// |
| /// ``` |
| /// let info = ash::vk::DeviceCreateInfo::default(); |
| /// let info: *const ash::vk::BaseInStructure = <*const _>::cast(&info); |
| /// unsafe { |
| /// ash::match_in_struct!(match info { |
| /// info @ ash::vk::DeviceQueueCreateInfo => { |
| /// dbg!(&info); // Unreachable |
| /// } |
| /// info @ ash::vk::DeviceCreateInfo => { |
| /// dbg!(&info); |
| /// } |
| /// }) |
| /// } |
| /// ``` |
| /// |
| /// See the [`match_out_struct!`] documentation for an example with implicit return values. |
| #[macro_export] |
| macro_rules! match_in_struct { |
| (match $p:ident { $($bind:ident @ $ty:path => $body:block $(,)?)+ $(_ => $any:block $(,)?)? }) => { |
| match std::ptr::addr_of!((*$p).s_type).read() { |
| $(<$ty as $crate::vk::TaggedStructure>::STRUCTURE_TYPE => { |
| let $bind = $p |
| .cast::<$ty>() |
| .as_ref() |
| .unwrap(); |
| $body |
| }),+ |
| _ => { $($any)? } |
| } |
| }; |
| } |
| |
| #[cfg(test)] |
| mod tests { |
| use super::vk; |
| #[test] |
| fn test_ptr_chains() { |
| let mut variable_pointers = vk::PhysicalDeviceVariablePointerFeatures::builder(); |
| let mut corner = vk::PhysicalDeviceCornerSampledImageFeaturesNV::builder(); |
| let chain = vec![ |
| <*mut _>::cast(&mut variable_pointers), |
| <*mut _>::cast(&mut corner), |
| ]; |
| let mut device_create_info = vk::DeviceCreateInfo::builder() |
| .push_next(&mut corner) |
| .push_next(&mut variable_pointers); |
| let chain2: Vec<*mut vk::BaseOutStructure> = unsafe { |
| vk::ptr_chain_iter(&mut device_create_info) |
| .skip(1) |
| .collect() |
| }; |
| assert_eq!(chain, chain2); |
| } |
| } |