diff options
Diffstat (limited to 'third_party/rust/ash/src/lib.rs')
-rw-r--r-- | third_party/rust/ash/src/lib.rs | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/third_party/rust/ash/src/lib.rs b/third_party/rust/ash/src/lib.rs new file mode 100644 index 0000000000..c900fc6c4d --- /dev/null +++ b/third_party/rust/ash/src/lib.rs @@ -0,0 +1,197 @@ +#![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); + } +} |