#![doc = include_str!(concat!("../", std::env!("CARGO_PKG_README")))]
#[cfg(feature = "loaded")]
mod loaded;
pub mod vk;
#[cfg(feature = "raw-window-handle")]
pub mod window;
use std::cell::Cell;
use std::ffi::c_char;
use std::marker::PhantomData;
use std::mem::{self, MaybeUninit};
use std::ptr::{self};
#[cfg(feature = "smallvec")]
use smallvec::SmallVec;
#[cfg(feature = "arrayvec")]
use arrayvec::ArrayVec;
pub type GetInstanceProcAddrSignature = unsafe extern "system" fn(
Option<BorrowedHandle<'_, vk::raw::Instance>>,
*const c_char,
) -> *const ();
pub trait Dispatcher: Clone {
fn get_command_dispatcher(&self) -> &vk::CommandsDispatcher;
unsafe fn new(get_instance_proc_addr: GetInstanceProcAddrSignature) -> Self;
#[cfg(feature = "loaded")]
unsafe fn new_loaded_and_lib(
) -> core::result::Result<(Self, libloading::Library), loaded::LoadingError> {
let (proc_addr, lib) = loaded::load_proc_addr_and_lib()?;
Ok((Self::new(proc_addr), lib))
}
fn clone_with_instance(&self, instance: &vk::raw::Instance) -> Self;
fn clone_with_device(&self, device: &vk::raw::Device) -> Self;
#[cfg(feature = "loaded")]
unsafe fn new_loaded() -> core::result::Result<Self, loaded::LoadingError>;
}
static DYNAMIC_DISPATCHER: vk::CommandsDispatcher = vk::CommandsDispatcher::new();
#[derive(Clone, Copy)]
pub struct DynamicDispatcher(pub(crate) ());
impl Dispatcher for DynamicDispatcher {
#[inline(always)]
fn get_command_dispatcher(&self) -> &vk::CommandsDispatcher {
&DYNAMIC_DISPATCHER
}
unsafe fn new(get_instance_proc_addr: GetInstanceProcAddrSignature) -> Self {
DYNAMIC_DISPATCHER.load_proc_addr(get_instance_proc_addr);
Self(())
}
fn clone_with_instance(&self, instance: &vk::raw::Instance) -> Self {
unsafe { DYNAMIC_DISPATCHER.load_instance(instance) };
Self(())
}
fn clone_with_device(&self, device: &vk::raw::Device) -> Self {
unsafe { DYNAMIC_DISPATCHER.load_device(device) };
Self(())
}
#[cfg(feature = "loaded")]
unsafe fn new_loaded() -> core::result::Result<Self, loaded::LoadingError> {
let (result, lib) = Self::new_loaded_and_lib()?;
loaded::DYNAMIC_VULKAN_LIB.0.set(Some(lib));
Ok(result)
}
}
#[cfg(feature = "loaded")]
impl DynamicDispatcher {
pub unsafe fn unload() {
loaded::DYNAMIC_VULKAN_LIB.0.set(None);
}
}
struct DispatcherWithLib {
dispatcher: vk::CommandsDispatcher,
#[cfg(feature = "loaded")]
library: Option<std::sync::Arc<libloading::Library>>,
}
#[derive(Clone)]
pub struct MultiDispatcher(std::sync::Arc<DispatcherWithLib>);
impl Dispatcher for MultiDispatcher {
#[inline(always)]
fn get_command_dispatcher(&self) -> &vk::CommandsDispatcher {
&self.0.dispatcher
}
unsafe fn new(get_instance_proc_addr: GetInstanceProcAddrSignature) -> Self {
let dispatcher = std::sync::Arc::new(DispatcherWithLib {
dispatcher: vk::CommandsDispatcher::new(),
#[cfg(feature = "loaded")]
library: None,
});
dispatcher.dispatcher.load_proc_addr(get_instance_proc_addr);
Self(dispatcher)
}
fn clone_with_instance(&self, instance: &vk::raw::Instance) -> Self {
let dispatcher = std::sync::Arc::new(DispatcherWithLib {
dispatcher: self.0.dispatcher.clone(),
#[cfg(feature = "loaded")]
library: self.0.library.clone(),
});
unsafe { dispatcher.dispatcher.load_instance(instance) };
Self(dispatcher)
}
fn clone_with_device(&self, device: &vk::raw::Device) -> Self {
let dispatcher = std::sync::Arc::new(DispatcherWithLib {
dispatcher: self.0.dispatcher.clone(),
#[cfg(feature = "loaded")]
library: self.0.library.clone(),
});
unsafe { dispatcher.dispatcher.load_device(device) };
Self(dispatcher)
}
#[cfg(feature = "loaded")]
unsafe fn new_loaded() -> core::result::Result<Self, loaded::LoadingError> {
let (mut result, lib) = Self::new_loaded_and_lib()?;
let library = std::sync::Arc::new(lib);
std::sync::Arc::get_mut(&mut result.0).unwrap().library = Some(library);
Ok(result)
}
}
pub unsafe trait Allocator: Sized + Clone {
fn alloc(
&self,
size: usize,
alignment: usize,
allocation_scope: vk::SystemAllocationScope,
) -> *mut ();
fn realloc(
&self,
original: *mut (),
size: usize,
alignment: usize,
allocation_scope: vk::SystemAllocationScope,
) -> *mut ();
fn free(&self, memory: *mut ());
fn on_internal_alloc(
&self,
size: usize,
allocation_type: vk::InternalAllocationType,
allocation_scope: vk::SystemAllocationScope,
);
fn on_internal_free(
&self,
size: usize,
allocation_type: vk::InternalAllocationType,
allocation_scope: vk::SystemAllocationScope,
);
extern "system" fn pfn_allocation(
user_data: *mut (),
size: usize,
alignment: usize,
allocation_scope: vk::SystemAllocationScope,
) -> *mut () {
let allocator: &Self = unsafe { &*user_data.cast() };
allocator.alloc(size, alignment, allocation_scope)
}
extern "system" fn pfn_reallocation(
user_data: *mut (),
original: *mut (),
size: usize,
alignment: usize,
allocation_scope: vk::SystemAllocationScope,
) -> *mut () {
let allocator: &Self = unsafe { &*user_data.cast() };
allocator.realloc(original, size, alignment, allocation_scope)
}
extern "system" fn pfn_free(user_data: *mut (), memory: *mut ()) {
let allocator: &Self = unsafe { &*user_data.cast() };
allocator.free(memory)
}
extern "system" fn pfn_internal_allocation(
user_data: *mut (),
size: usize,
allocation_type: vk::InternalAllocationType,
allocation_scope: vk::SystemAllocationScope,
) {
let allocator: &Self = unsafe { &*user_data.cast() };
allocator.on_internal_alloc(size, allocation_type, allocation_scope)
}
extern "system" fn pfn_internal_free(
user_data: *mut (),
size: usize,
allocation_type: vk::InternalAllocationType,
allocation_scope: vk::SystemAllocationScope,
) {
let allocator: &Self = unsafe { &*user_data.cast() };
allocator.on_internal_free(size, allocation_type, allocation_scope)
}
fn get_allocation_callbacks(&self) -> Option<vk::AllocationCallbacks> {
Some(vk::AllocationCallbacks {
p_user_data: (self as *const Self).cast(),
pfn_allocation: Self::pfn_allocation as *const (),
pfn_reallocation: Self::pfn_reallocation as *const (),
pfn_free: Self::pfn_free as *const (),
pfn_internal_allocation: Self::pfn_internal_allocation as *const (),
pfn_internal_free: Self::pfn_free as *const (),
})
}
}
#[derive(Clone, Copy)]
pub struct DefaultAllocator;
unsafe impl Allocator for DefaultAllocator {
fn alloc(&self, _: usize, _: usize, _: vk::SystemAllocationScope) -> *mut () {
ptr::null_mut()
}
fn realloc(&self, _: *mut (), _: usize, _: usize, _: vk::SystemAllocationScope) -> *mut () {
ptr::null_mut()
}
fn free(&self, _: *mut ()) {}
fn on_internal_alloc(
&self,
_: usize,
_: vk::InternalAllocationType,
_: vk::SystemAllocationScope,
) {
}
fn on_internal_free(
&self,
_: usize,
_: vk::InternalAllocationType,
_: vk::SystemAllocationScope,
) {
}
#[inline(always)]
fn get_allocation_callbacks(&self) -> Option<vk::AllocationCallbacks> {
None
}
}
#[macro_export]
macro_rules! flagbits {
( $enum:ident ::{ $($variant:ident)|+ } ) => {
$($enum::$variant)|+
};
( vk :: $enum:ident ::{ $($variant:ident)|+ } ) => {
$(vk::$enum::$variant)|+
}
}
mod private {
pub trait Sealed {}
}
pub unsafe trait Alias<T>: Sized {}
unsafe impl<T> Alias<T> for T {}
pub trait Handle: private::Sealed + Sized {
type InnerType: Copy;
const TYPE: vk::ObjectType;
fn as_raw(&self) -> Self::InnerType;
unsafe fn from_raw(x: Self::InnerType) -> Self;
unsafe fn try_from_raw<T>(x: T) -> Option<Self>
where
Self::InnerType: TryFrom<T>,
{
Self::InnerType::try_from(x).ok().map(|t| Self::from_raw(t))
}
#[inline(always)]
fn borrow<'a>(&'a self) -> BorrowedHandle<'a, Self> {
BorrowedHandle {
value: self.as_raw(),
phantom: PhantomData,
}
}
#[inline(always)]
fn borrow_mut<'a>(&'a mut self) -> BorrowedMutHandle<'a, Self> {
BorrowedMutHandle {
value: self.as_raw(),
phantom: PhantomData,
}
}
unsafe fn clone(&self) -> Self;
}
#[repr(transparent)]
#[derive(Debug, Clone, Copy)]
pub struct BorrowedHandle<'a, T: Handle> {
value: T::InnerType,
phantom: PhantomData<&'a T>,
}
unsafe impl<'a, T: Handle> Alias<T> for BorrowedHandle<'a, T> {}
impl<'a, T: Handle> AsRef<T> for BorrowedHandle<'a, T> {
#[inline(always)]
fn as_ref(&self) -> &T {
unsafe { mem::transmute(self) }
}
}
#[repr(transparent)]
#[derive(Debug, Clone, Copy)]
pub struct BorrowedMutHandle<'a, T: Handle> {
value: T::InnerType,
phantom: PhantomData<&'a mut T>,
}
unsafe impl<'a, T: Handle> Alias<T> for BorrowedMutHandle<'a, T> {}
impl<'a, T: Handle> AsMut<T> for BorrowedMutHandle<'a, T> {
#[inline(always)]
fn as_mut(&mut self) -> &mut T {
unsafe { mem::transmute(self) }
}
}
pub unsafe trait ExtendableStructureBase {
fn header(&self) -> *const Header {
ptr::from_ref(self).cast()
}
fn header_mut(&mut self) -> *mut Header {
ptr::from_mut(self).cast()
}
}
pub unsafe trait ExtendableStructure: ExtendableStructureBase + Default {
const STRUCTURE_TYPE: vk::StructureType;
unsafe fn retrieve_next(&self) -> &Cell<*const Header> {
&unsafe { &*self.header() }.p_next
}
unsafe fn push_next_unchecked<T: ExtendableStructure>(&self, ext: &T) {
let my_next = self.retrieve_next();
let other_next = ext.retrieve_next();
other_next.set(my_next.get());
my_next.set(ptr::from_ref(ext).cast());
}
fn new_uninit() -> MaybeUninit<Self> {
let mut result: MaybeUninit<Self> = MaybeUninit::uninit();
let header = Header {
s_type: Self::STRUCTURE_TYPE,
p_next: Cell::new(ptr::null()),
};
unsafe { result.as_mut_ptr().cast::<Header>().write(header) };
result
}
}
pub unsafe trait ExtendingStructure<T: ExtendableStructure>: ExtendableStructure {}
unsafe impl<T: ExtendableStructure> ExtendingStructure<T> for T {}
#[repr(C)]
pub struct Header {
s_type: vk::StructureType,
p_next: Cell<*const Header>,
}
pub unsafe trait StructureChainOut<H>: Sized
where
H: ExtendableStructure,
{
fn setup_uninit(chain: &mut MaybeUninit<Self>);
fn get_uninit_head_ptr(chain: *mut Self) -> *mut H;
fn setup_cleanup(chain: *mut Self) {
let head = Self::get_uninit_head_ptr(chain).cast::<Header>();
unsafe { ptr::addr_of_mut!((*head).p_next).write(Cell::new(ptr::null())) };
}
}
pub unsafe trait StructureChain<H>: AsRef<H> + AsMut<H> + Sized
where
H: ExtendableStructure,
{
fn get_mut<T: ExtendingStructure<H>>(&mut self) -> &mut T;
fn get<T: ExtendingStructure<H>>(&self) -> &T;
fn unlink<T: ExtendingStructure<H>>(&mut self);
fn link<T: ExtendingStructure<H>>(&mut self);
}
unsafe impl<H: ExtendableStructure> StructureChainOut<H> for H {
fn setup_uninit(chain: &mut MaybeUninit<Self>) {
unsafe {
chain.as_mut_ptr().cast::<Header>().write(Header {
s_type: Self::STRUCTURE_TYPE,
p_next: Cell::new(ptr::null()),
})
}
}
fn get_uninit_head_ptr(chain: *mut Self) -> *mut H {
chain
}
fn setup_cleanup(_: *mut Self) {
}
}
macro_rules! make_structure_chain_type {
($name: ident, $($ext_ty:ident => ($ext_nb:tt, $ext_name:ident)),*) => {
#[doc(hidden)]
pub struct $name<H, $($ext_ty),*>
where
H: ExtendableStructure,
$($ext_ty: ExtendingStructure<H>),*
{
head: H,
$($ext_name: ($ext_ty, bool),)*
has_changed: Cell<bool>,
}
impl<H, $($ext_ty),*> $name<H, $($ext_ty),*>
where
H: ExtendableStructure,
$($ext_ty: ExtendingStructure<H>),* {
pub fn new(head: H, $($ext_name: $ext_ty),*) -> Self {
Self {
head,
$($ext_name: ($ext_name, true),)*
has_changed: Cell::new(true),
}
}
fn perform_linking(&self) {
self.has_changed.set(false);
let mut _prev_ptr = ptr::null();
$(
if self.$ext_name.1 {
unsafe { self.$ext_name.0.retrieve_next().set(_prev_ptr) };
_prev_ptr = ptr::from_ref(&self.$ext_name.0).cast();
}
)*
unsafe { self.head.retrieve_next().set(_prev_ptr) };
}
}
impl<H, $($ext_ty),*> AsRef<H> for $name<H, $($ext_ty),*>
where
H: ExtendableStructure,
$($ext_ty: ExtendingStructure<H>),* {
fn as_ref(&self) -> &H {
if self.has_changed.get(){
self.perform_linking();
}
&self.head
}
}
impl<H, $($ext_ty),*> AsMut<H> for $name<H, $($ext_ty),*>
where
H: ExtendableStructure,
$($ext_ty: ExtendingStructure<H>),* {
fn as_mut(&mut self) -> &mut H {
if self.has_changed.get(){
self.perform_linking();
}
&mut self.head
}
}
impl<H, $($ext_ty),*> Default for $name<H, $($ext_ty),*>
where
H: ExtendableStructure,
$($ext_ty: ExtendingStructure<H>),*
{
fn default() -> Self {
Self {
head: Default::default(),
$($ext_name: (Default::default(), true),)*
has_changed: Cell::new(true),
}
}
}
unsafe impl<H, $($ext_ty),*> StructureChain<H> for $name<H, $($ext_ty),*>
where
H: ExtendableStructure,
$($ext_ty: ExtendingStructure<H>),*
{
fn get_mut<T: ExtendingStructure<H>>(&mut self) -> &mut T {
if H::STRUCTURE_TYPE == T::STRUCTURE_TYPE {
self.perform_linking();
unsafe {
mem::transmute(self)
}
} $(else if $ext_ty::STRUCTURE_TYPE == T::STRUCTURE_TYPE {
unsafe {
mem::transmute(self)
}
})* else {
panic!(
"Unexpected type for structure chain {}",
std::any::type_name::<H>()
)
}
}
fn get<T: ExtendingStructure<H>>(&self) -> &T {
if H::STRUCTURE_TYPE == T::STRUCTURE_TYPE {
self.perform_linking();
unsafe {
mem::transmute(self)
}
} $(else if $ext_ty::STRUCTURE_TYPE == T::STRUCTURE_TYPE {
unsafe {
mem::transmute(self)
}
})* else {
panic!(
"Unexpected type for structure chain {}",
std::any::type_name::<H>()
)
}
}
fn unlink<T: ExtendingStructure<H>>(&mut self) {
if H::STRUCTURE_TYPE == T::STRUCTURE_TYPE {
panic!("Cannot unlink head structure!");
}
self.has_changed.set(true);
if false {
} $(else if $ext_ty::STRUCTURE_TYPE == T::STRUCTURE_TYPE {
self.$ext_name.1 = false;
})* else {
panic!(
"Unexpected type for structure chain {}",
std::any::type_name::<H>()
)
}
}
fn link<T: ExtendingStructure<H>>(&mut self) {
if H::STRUCTURE_TYPE == T::STRUCTURE_TYPE {
panic!("Head structure is always linked!");
}
self.has_changed.set(true);
if false {
} $(else if $ext_ty::STRUCTURE_TYPE == T::STRUCTURE_TYPE {
self.$ext_name.1 = true;
})* else {
panic!(
"Unexpected type for structure chain {}",
std::any::type_name::<H>()
)
}
}
}
unsafe impl<H, $($ext_ty),*> StructureChainOut<H> for $name<H, $($ext_ty),*>
where
H: ExtendableStructure,
$($ext_ty: ExtendingStructure<H>),*
{
fn setup_uninit(chain: &mut MaybeUninit<Self>) {
let chain_ptr = chain.as_mut_ptr();
unsafe {
ptr::addr_of_mut!((*chain_ptr).has_changed).write(Cell::new(false));
let mut _prev_header = Header {
s_type: H::STRUCTURE_TYPE,
p_next: Cell::new(ptr::null()),
};
let prev_ptr: *mut Header = ptr::addr_of_mut!((*chain_ptr).head).cast();
$(
let ptr = ptr::addr_of_mut!((*chain_ptr).$ext_name.0).cast();
_prev_header.p_next = Cell::new(ptr);
prev_ptr.write(_prev_header);
let prev_ptr = ptr;
let mut _prev_header = Header {
s_type: $ext_ty::STRUCTURE_TYPE,
p_next: Cell::new(ptr::null()),
};
ptr::addr_of_mut!((*chain_ptr).$ext_name.1).write(true);
)*
prev_ptr.write(_prev_header);
}
}
fn get_uninit_head_ptr(chain: *mut Self) -> *mut H {
unsafe { ptr::addr_of_mut!((*chain).head).cast() }
}
}
unsafe impl<H, $($ext_ty),*> StructureChainOut<H> for (H, $($ext_ty,)*)
where
H: ExtendableStructure,
$($ext_ty: ExtendingStructure<H>),*
{
fn setup_uninit(chain: &mut MaybeUninit<Self>) {
let chain_ptr = chain.as_mut_ptr();
unsafe {
let mut _prev_header = Header {
s_type: H::STRUCTURE_TYPE,
p_next: Cell::new(ptr::null()),
};
let prev_ptr: *mut Header = ptr::addr_of_mut!((*chain_ptr).0).cast();
$(
let ptr = ptr::addr_of_mut!((*chain_ptr).$ext_nb).cast();
_prev_header.p_next = Cell::new(ptr);
prev_ptr.write(_prev_header);
let prev_ptr = ptr;
let mut _prev_header = Header {
s_type: $ext_ty::STRUCTURE_TYPE,
p_next: Cell::new(ptr::null()),
};
)*
prev_ptr.write(_prev_header);
}
}
fn get_uninit_head_ptr(chain: *mut Self) -> *mut H {
unsafe { ptr::addr_of_mut!((*chain).0).cast() }
}
}
};
}
make_structure_chain_type! {StructureChain0,}
make_structure_chain_type! {StructureChain1, V1 => (1,ext1)}
make_structure_chain_type! {StructureChain2, V1 => (1,ext1), V2 => (2,ext2)}
make_structure_chain_type! {StructureChain3, V1 => (1,ext1), V2 => (2,ext2), V3 => (3,ext3)}
make_structure_chain_type! {StructureChain4, V1 => (1,ext1), V2 => (2,ext2), V3 => (3,ext3), V4 => (4,ext4)}
make_structure_chain_type! {StructureChain5, V1 => (1,ext1), V2 => (2,ext2), V3 => (3,ext3), V4 => (4,ext4), V5 => (5,ext5)}
make_structure_chain_type! {StructureChain6, V1 => (1,ext1), V2 => (2,ext2), V3 => (3,ext3), V4 => (4,ext4), V5 => (5,ext5), V6 => (6,ext6) }
pub struct StructureChainVec<H: ExtendableStructure> {
head: H,
content: Vec<(Box<dyn ExtendableStructureBase>, Cell<bool>)>,
has_changed: Cell<bool>,
}
impl<H> StructureChainVec<H>
where
H: ExtendableStructure,
{
pub fn new(head: H) -> Self {
Self::new_with_capacity(head, 0)
}
pub fn new_with_capacity(head: H, capacity: usize) -> Self {
Self {
head,
content: Vec::with_capacity(capacity),
has_changed: Cell::new(true),
}
}
pub fn push<T: ExtendingStructure<H> + 'static>(&mut self, structure: T) {
self.has_changed.set(true);
self.content.push((Box::new(structure), Cell::new(true)));
}
fn perform_linking(&self) {
self.has_changed.set(false);
let mut prev_ptr = ptr::null();
for (structure, is_linked) in &self.content {
if is_linked.get() {
let next_header = structure.header();
unsafe { &*next_header }.p_next.set(prev_ptr);
prev_ptr = next_header;
}
}
unsafe { self.head.retrieve_next().set(prev_ptr) };
}
}
impl<H> AsRef<H> for StructureChainVec<H>
where
H: ExtendableStructure,
{
fn as_ref(&self) -> &H {
if self.has_changed.get() {
self.perform_linking();
}
&self.head
}
}
impl<H> AsMut<H> for StructureChainVec<H>
where
H: ExtendableStructure,
{
fn as_mut(&mut self) -> &mut H {
if self.has_changed.get() {
self.perform_linking();
}
&mut self.head
}
}
unsafe impl<H> StructureChain<H> for StructureChainVec<H>
where
H: ExtendableStructure,
{
fn get_mut<T: ExtendingStructure<H>>(&mut self) -> &mut T {
if H::STRUCTURE_TYPE == T::STRUCTURE_TYPE {
self.perform_linking();
return unsafe { mem::transmute(self) };
}
for (structure, _) in &mut self.content {
let header = structure.header_mut();
if unsafe { (*header).s_type } == T::STRUCTURE_TYPE {
return unsafe { mem::transmute(header) };
}
}
panic!(
"Type {} is not part of the structure chain",
std::any::type_name::<H>()
)
}
fn get<T: ExtendingStructure<H>>(&self) -> &T {
if H::STRUCTURE_TYPE == T::STRUCTURE_TYPE {
self.perform_linking();
return unsafe { mem::transmute(self) };
}
for (structure, _) in &self.content {
let header = structure.header();
if unsafe { (*header).s_type } == T::STRUCTURE_TYPE {
return unsafe { mem::transmute(header) };
}
}
panic!(
"Type {} is not part of the structure chain",
std::any::type_name::<H>()
)
}
fn unlink<T: ExtendingStructure<H>>(&mut self) {
if H::STRUCTURE_TYPE == T::STRUCTURE_TYPE {
panic!("Cannot unlink head structure!");
}
self.has_changed.set(true);
for (structure, is_linked) in &self.content {
let header = structure.header();
if unsafe { (*header).s_type } == T::STRUCTURE_TYPE {
is_linked.set(false);
return;
}
}
panic!(
"Type {} is not part of the structure chain",
std::any::type_name::<H>()
)
}
fn link<T: ExtendingStructure<H>>(&mut self) {
if H::STRUCTURE_TYPE == T::STRUCTURE_TYPE {
panic!("Head structure is always linked!");
}
self.has_changed.set(true);
for (structure, is_linked) in &self.content {
let header = structure.header();
if unsafe { (*header).s_type } == T::STRUCTURE_TYPE {
is_linked.set(true);
return;
}
}
panic!(
"Type {} is not part of the structure chain",
std::any::type_name::<H>()
)
}
}
#[macro_export]
macro_rules! create_structure_chain {
($head:ty $(,)?) => {
$crate::StructureChain0::<$head>::default()
};
($head:ty, $ext1:ty $(,)?) => {
$crate::StructureChain1::<$head, $ext1>::default()
};
($head:ty, $ext1:ty, $ext2:ty $(,)?) => {
$crate::StructureChain2::<$head, $ext1, $ext2>::default()
};
($head:ty, $ext1:ty, $ext2:ty, $ext3:ty $(,)?) => {
$crate::StructureChain3::<$head, $ext1, $ext2, $ext3>::default()
};
($head:ty, $ext1:ty, $ext2:ty, $ext3:ty, $ext4:ty $(,)?) => {
$crate::StructureChain4::<$head, $ext1, $ext2, $ext3, $ext4>::default()
};
($head:ty, $ext1:ty, $ext2:ty, $ext3:ty, $ext4:ty, $ext5:ty $(,)?) => {
$crate::StructureChain5::<$head, $ext1, $ext2, $ext3, $ext4, $ext5>::default()
};
($head:ty, $ext1:ty, $ext2:ty, $ext3:ty, $ext4:ty, $ext5:ty, $ext6:ty $(,)?) => {
$crate::StructureChain6::<$head, $ext1, $ext2, $ext3, $ext4, $ext5, $ext6>::default()
};
}
#[macro_export]
macro_rules! structure_chain {
($head:expr) => {
$crate::StructureChain0::new($head)
};
($head:expr, $ext1:expr $(,)?) => {
$crate::StructureChain1::new($head, $ext1)
};
($head:expr, $ext1:expr, $ext2:expr $(,)?) => {
$crate::StructureChain2::new($head, $ext1, $ext2)
};
($head:expr, $ext1:expr, $ext2:expr, $ext3:expr $(,)?) => {
$crate::StructureChain3::new($head, $ext1, $ext2, $ext3)
};
($head:expr, $ext1:expr, $ext2:expr, $ext3:expr, $ext4:expr $(,)?) => {
$crate::StructureChain4::new($head, $ext1, $ext2, $ext3, $ext4)
};
($head:expr, $ext1:expr, $ext2:expr, $ext3:expr, $ext4:expr, $ext5:expr $(,)?) => {
$crate::StructureChain5::new($head, $ext1, $ext2, $ext3, $ext4, $ext5)
};
($head:expr, $ext1:expr, $ext2:expr, $ext3:expr, $ext4:expr, $ext5:expr, $ext6:expr $(,)?) => {
$crate::StructureChain6::new($head, $ext1, $ext2, $ext3, $ext4, $ext5, $ext6)
};
($head:expr, $($ext:expr),* $(,)?) => {{
let mut chain = $crate::StructureChainVec::new($head);
$(
chain.push($ext);
)*
chain
}}
}
#[macro_export]
macro_rules! include_spirv {
($path:literal) => {{
#[repr(align(4))]
struct AlignedStruct<Bytes: ?Sized> {
bytes: Bytes,
}
static ALIGNED: &'static AlignedStruct<[u8]> = {
let bytes = include_bytes!($path);
assert!(
bytes.len() % 4 == 0,
concat!(
"The file ",
$path,
" must have a size which is a multiple of 4 bytes"
)
);
&AlignedStruct { bytes: *bytes }
};
unsafe {
std::slice::from_raw_parts(
ALIGNED.bytes.as_ptr() as *const u32,
ALIGNED.bytes.len() / 4,
)
}
}};
}
pub unsafe trait DynamicArray<T>: IntoIterator<Item = T> {
#[doc(hidden)]
fn create_with_capacity(capacity: usize) -> Self;
#[doc(hidden)]
fn update_with_capacity(&mut self, new_capacity: usize);
#[doc(hidden)]
fn get_content_mut_ptr(&mut self) -> *mut T;
#[doc(hidden)]
unsafe fn resize_with_len(&mut self, len: usize);
}
pub trait AdvancedDynamicArray<T, S>: DynamicArray<T> + FromIterator<T> {
type InnerArrayType: DynamicArray<S>;
}
unsafe impl<T> DynamicArray<T> for Vec<T> {
fn create_with_capacity(capacity: usize) -> Self {
Self::with_capacity(capacity)
}
fn update_with_capacity(&mut self, new_capacity: usize) {
self.reserve(new_capacity)
}
fn get_content_mut_ptr(&mut self) -> *mut T {
self.as_mut_ptr()
}
unsafe fn resize_with_len(&mut self, len: usize) {
self.set_len(len)
}
}
impl<T, S> AdvancedDynamicArray<T, S> for Vec<T> {
type InnerArrayType = Vec<S>;
}
#[cfg(feature = "smallvec")]
unsafe impl<T, A> DynamicArray<T> for SmallVec<A>
where
A: smallvec::Array<Item = T>,
{
fn create_with_capacity(capacity: usize) -> Self {
Self::with_capacity(capacity)
}
fn update_with_capacity(&mut self, new_capacity: usize) {
self.reserve(new_capacity)
}
fn get_content_mut_ptr(&mut self) -> *mut T {
self.as_mut_ptr()
}
unsafe fn resize_with_len(&mut self, len: usize) {
self.set_len(len)
}
}
#[cfg(feature = "smallvec")]
impl<T, S, const N: usize> AdvancedDynamicArray<T, S> for SmallVec<[T; N]> {
type InnerArrayType = SmallVec<[S; N]>;
}
#[cfg(feature = "arrayvec")]
unsafe impl<T, const N: usize> DynamicArray<T> for ArrayVec<T, N> {
fn create_with_capacity(capacity: usize) -> Self {
if capacity > N {
panic!("Trying to use an ArrayVec of size {N} with capacity {capacity}")
}
Self::new()
}
fn update_with_capacity(&mut self, new_capacity: usize) {
if new_capacity > N {
panic!("Trying to use an ArrayVec of size {N} with capacity {new_capacity}")
}
}
fn get_content_mut_ptr(&mut self) -> *mut T {
self.as_mut_ptr()
}
unsafe fn resize_with_len(&mut self, len: usize) {
self.set_len(len)
}
}
#[cfg(feature = "arrayvec")]
impl<T, S, const N: usize> AdvancedDynamicArray<T, S> for ArrayVec<T, N> {
type InnerArrayType = ArrayVec<S, N>;
}
pub trait AsSlice<'a, T>: Copy {
#[doc(hidden)]
fn as_slice(self) -> &'a [T];
}
impl<'a, T> AsSlice<'a, T> for &'a [T] {
fn as_slice(self) -> &'a [T] {
self
}
}
impl<'a, T, const N: usize> AsSlice<'a, T> for &'a [T; N] {
fn as_slice(self) -> &'a [T] {
self
}
}
impl<'a, T> AsSlice<'a, T> for &'a T {
fn as_slice(self) -> &'a [T] {
std::slice::from_ref(self)
}
}
impl<'a, T> AsSlice<'a, T> for &'a Option<T> {
fn as_slice(self) -> &'a [T] {
self.as_slice()
}
}
impl<'a, T> AsSlice<'a, T> for Option<&'a T> {
fn as_slice(self) -> &'a [T] {
self.map_or(&[], std::slice::from_ref)
}
}
impl<'a, T> AsSlice<'a, T> for &'a Vec<T> {
fn as_slice(self) -> &'a [T] {
self.as_slice()
}
}
impl<'a, T> AsSlice<'a, T> for &'a Box<T> {
fn as_slice(self) -> &'a [T] {
std::slice::from_ref(self)
}
}
impl<'a, T> AsSlice<'a, T> for () {
fn as_slice(self) -> &'a [T] {
&[]
}
}
#[cfg(feature = "smallvec")]
impl<'a, T, const N: usize> AsSlice<'a, T> for &'a SmallVec<[T; N]> {
fn as_slice(self) -> &'a [T] {
self.as_slice()
}
}
#[cfg(feature = "arrayvec")]
impl<'a, T, const N: usize> AsSlice<'a, T> for &'a ArrayVec<T, N> {
fn as_slice(self) -> &'a [T] {
self.as_slice()
}
}