Skip to main content

covk_sys/
lib.rs

1#![no_std]
2#![macro_use]
3#![cfg_attr(docsrs, feature(doc_cfg))]
4#![allow(unpredictable_function_pointer_comparisons)]
5#![allow(non_upper_case_globals)]
6#![allow(non_camel_case_types)]
7#![allow(nonstandard_style)]
8#![allow(unused_imports)]
9#![allow(unused_parens)]
10#![allow(unused)]
11#![allow(rustdoc::broken_intra_doc_links)]
12
13extern crate alloc;
14
15#[macro_export]
16/// `(($variant as u32) << 29u32) | (($major as u32) << 22u32) | (($minor as u32) << 12u32) | ($patch as u32)`
17macro_rules! VK_MAKE_API_VERSION {
18    ( $variant:expr, $major:expr, $minor:expr, $patch:expr ) => {
19        (($variant as u32) << 29u32)
20            | (($major as u32) << 22u32)
21            | (($minor as u32) << 12u32)
22            | ($patch as u32)
23    };
24}
25
26#[macro_export]
27/// `($version as u32) >> 29u32`
28macro_rules! VK_API_VERSION_VARIANT {
29    ( $version:expr ) => {
30        ($version as u32) >> 29u32
31    };
32}
33
34#[macro_export]
35/// `(($version as u32) >> 22u32) & 0x7Fu32`
36macro_rules! VK_API_VERSION_MAJOR {
37    ( $version:expr ) => {
38        (($version as u32) >> 22u32) & 0x7Fu32
39    };
40}
41
42#[macro_export]
43/// `(($version as u32) >> 12u32) & 0x3FFu32`
44macro_rules! VK_API_VERSION_MINOR {
45    ( $version:expr ) => {
46        (($version as u32) >> 12u32) & 0x3FFu32
47    };
48}
49
50#[macro_export]
51/// `($version as u32) & 0xFFFu32`
52macro_rules! VK_API_VERSION_PATCH {
53    ( $version:expr ) => {
54        ($version as u32) & 0xFFFu32
55    };
56}
57
58/// `VK_MAKE_API_VERSION!(0, 1, 0, 0)`
59pub const VK_API_VERSION_1_0: u32 = VK_MAKE_API_VERSION!(0, 1, 0, 0);
60/// `VK_MAKE_API_VERSION!(0, 1, 1, 0)`
61pub const VK_API_VERSION_1_1: u32 = VK_MAKE_API_VERSION!(0, 1, 1, 0);
62/// `VK_MAKE_API_VERSION!(0, 1, 2, 0)`
63pub const VK_API_VERSION_1_2: u32 = VK_MAKE_API_VERSION!(0, 1, 2, 0);
64/// `VK_MAKE_API_VERSION!(0, 1, 3, 0)`
65pub const VK_API_VERSION_1_3: u32 = VK_MAKE_API_VERSION!(0, 1, 3, 0);
66/// `VK_MAKE_API_VERSION!(0, 1, 4, 0)`
67pub const VK_API_VERSION_1_4: u32 = VK_MAKE_API_VERSION!(0, 1, 4, 0);
68
69/// VkSampleMask
70pub type VkSampleMask = u32;
71/// VkBool32
72pub type VkBool32 = u32;
73/// VkFlags
74pub type VkFlags = u32;
75/// VkFlags64
76pub type VkFlags64 = u64;
77/// VkDeviceSize
78pub type VkDeviceSize = u64;
79/// VkDeviceAddress
80pub type VkDeviceAddress = u64;
81
82impl VkBaseInStructure {
83    /// Downcast the structure to the specified type if `sType` matches, otherwise return `None`.
84    pub unsafe fn downcast<T: Chainable>(&self) -> Option<&T> {
85        if self.sType == T::TYPE {
86            Some(unsafe { core::mem::transmute(self) })
87        } else {
88            None
89        }
90    }
91    /// Downcast the structure to the specified type if `sType` matches, otherwise return `None`.
92    pub unsafe fn downcast_mut<T: Chainable>(&mut self) -> Option<&mut T> {
93        if self.sType == T::TYPE {
94            Some(unsafe { core::mem::transmute(self) })
95        } else {
96            None
97        }
98    }
99}
100
101impl VkBaseOutStructure {
102    /// Downcast the structure to the specified type if `sType` matches, otherwise return `None`.
103    pub unsafe fn downcast<T: Chainable>(&self) -> Option<&T> {
104        if self.sType == T::TYPE {
105            Some(unsafe { core::mem::transmute(self) })
106        } else {
107            None
108        }
109    }
110    /// Downcast the structure to the specified type if `sType` matches, otherwise return `None`.
111    pub unsafe fn downcast_mut<T: Chainable>(&mut self) -> Option<&mut T> {
112        if self.sType == T::TYPE {
113            Some(unsafe { core::mem::transmute(self) })
114        } else {
115            None
116        }
117    }
118}
119
120/// Marker trait for struct with `sType` and `pNext` field
121pub trait Chainable: Sized {
122    /// The value of `sType` field
123    const TYPE: crate::VkStructureType;
124    /// The const reference of `pNext` field
125    fn p_next(&self) -> &*const core::ffi::c_void;
126    /// The mutable reference of `pNext` field
127    fn p_next_mut(&mut self) -> &mut *mut core::ffi::c_void;
128
129    /// Push the next struct to the chain
130    unsafe fn push_next<E: Extend<Self>>(&mut self, ex: &mut E) -> &mut Self {
131        core::mem::replace(ex.p_next_mut(), *self.p_next_mut());
132        *self.p_next_mut() = (ex as *mut E).cast();
133        self
134    }
135
136    /// Get the next struct in the chain
137    unsafe fn next(&self) -> Option<&VkBaseInStructure> {
138        let p_next = *self.p_next();
139        if p_next.is_null() {
140            None
141        } else {
142            Some(unsafe { &*(p_next.cast::<VkBaseInStructure>()) })
143        }
144    }
145
146    /// Get the next struct in the chain
147    unsafe fn next_mut(&mut self) -> Option<&mut VkBaseOutStructure> {
148        let p_next = *self.p_next_mut();
149        if p_next.is_null() {
150            None
151        } else {
152            Some(unsafe { &mut *(p_next.cast::<VkBaseOutStructure>()) })
153        }
154    }
155
156    /// Upcast the struct to `VkBaseInStructure`
157    unsafe fn upcast(&self) -> &VkBaseInStructure {
158        unsafe { core::mem::transmute(self) }
159    }
160
161    /// Upcast the struct to `VkBaseOutStructure`
162    unsafe fn upcast_mut(&mut self) -> &mut VkBaseOutStructure {
163        unsafe { core::mem::transmute(self) }
164    }
165}
166
167/// Type safe extend chain
168pub trait Extend<T: Chainable>: Chainable {}
169
170/// Marker trait for vulkan handles
171pub trait Handle {
172    /// Handle type
173    const TYPE: crate::VkObjectType;
174
175    fn null() -> Self;
176    fn is_null(&self) -> bool;
177}
178
179/// Marker trait for non parent handles
180pub trait RootHandle: Handle {}
181
182/// Marker trait for sub handles
183pub trait SubHandle: Handle {
184    /// Parent handle type
185    type Parent: Handle;
186}
187
188macro_rules! from_into_transparent {
189    ( $t:ty : $u:ty ) => {
190        impl From<$t> for $u {
191            fn from(value: $t) -> Self {
192                value.0 as _
193            }
194        }
195        impl From<$u> for $t {
196            fn from(value: $u) -> Self {
197                Self(value as _)
198            }
199        }
200    };
201}
202
203macro_rules! flags {
204    ( $t:ty ) => {
205        impl $t {
206            /// `0`
207            pub const fn empty() -> Self {
208                Self(0)
209            }
210            /// return is `0`
211            pub const fn is_empty(self) -> bool {
212                self.0 == 0
213            }
214            /// return is all bits in `flags` are set
215            pub const fn has_flags(self, flags: Self) -> bool {
216                (self.0 & flags.0) == flags.0
217            }
218            /// return is any bits in `flags` are set
219            pub const fn has_any_flags(self, flags: Self) -> bool {
220                (self.0 & flags.0) != 0
221            }
222            /// return is only bits in `flags` are set
223            pub const fn has_flags_only(self, flags: Self) -> bool {
224                (self.0 & !flags.0) == 0
225            }
226        }
227        impl core::ops::Not for $t {
228            type Output = Self;
229
230            fn not(self) -> Self::Output {
231                Self(!self.0)
232            }
233        }
234        impl core::ops::BitOr for $t {
235            type Output = Self;
236
237            fn bitor(self, rhs: Self) -> Self::Output {
238                Self(self.0 | rhs.0)
239            }
240        }
241        impl core::ops::BitAnd for $t {
242            type Output = Self;
243
244            fn bitand(self, rhs: Self) -> Self::Output {
245                Self(self.0 & rhs.0)
246            }
247        }
248        impl core::ops::BitXor for $t {
249            type Output = Self;
250
251            fn bitxor(self, rhs: Self) -> Self::Output {
252                Self(self.0 ^ rhs.0)
253            }
254        }
255        impl core::ops::BitAndAssign for $t {
256            fn bitand_assign(&mut self, rhs: Self) {
257                self.0 &= rhs.0;
258            }
259        }
260        impl core::ops::BitOrAssign for $t {
261            fn bitor_assign(&mut self, rhs: Self) {
262                self.0 |= rhs.0;
263            }
264        }
265        impl core::ops::BitXorAssign for $t {
266            fn bitxor_assign(&mut self, rhs: Self) {
267                self.0 ^= rhs.0;
268            }
269        }
270    };
271}
272
273macro_rules! impl_extends {
274    { $this:ty : $($ex:ty),+ } => {
275        $(
276            impl Extend<$ex> for $this {}
277        )+
278    };
279}
280
281macro_rules! impl_handle {
282    ( $t:ty : $objtyp:expr; $det:ty $(= $parent:ty)? ) => {
283        impl $t {
284            pub const fn null() -> Self {
285                Self(0 as _)
286            }
287            pub fn is_null(&self) -> bool {
288                self == &Self::null()
289            }
290        }
291        unsafe impl Send for $t {}
292        unsafe impl Sync for $t {}
293        impl Handle for $t {
294            const TYPE: crate::VkObjectType = $objtyp;
295            fn null() -> Self {
296                Self::null()
297            }
298            fn is_null(&self) -> bool {
299                self.is_null()
300            }
301        }
302        impl $det for $t {
303            $(type Parent = $parent;)?
304        }
305        impl core::fmt::Pointer for $t
306        {
307            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
308                write!(f, "{:x}", self.0 as u64)
309            }
310        }
311    };
312}
313
314macro_rules! impl_zeroed {
315    ( $t:ty ) => {
316        impl $t {
317            pub const ZEROED: Self = unsafe { MaybeUninit::<Self>::zeroed().assume_init() };
318        }
319    };
320}
321
322macro_rules! impl_default_zeroed {
323    ( $t:ty ) => {
324        impl_zeroed!($t);
325        impl Default for $t {
326            fn default() -> Self {
327                Self::ZEROED
328            }
329        }
330    };
331}
332
333macro_rules! impl_default_zeroed_with_s_type {
334    ( $t:ty : $s_type:expr ) => {
335        impl_zeroed!($t);
336        impl Chainable for $t {
337            const TYPE: crate::VkStructureType = $s_type;
338            fn p_next(&self) -> &*const core::ffi::c_void {
339                unsafe { core::mem::transmute(&self.pNext) }
340            }
341            fn p_next_mut(&mut self) -> &mut *mut core::ffi::c_void {
342                unsafe { core::mem::transmute(&mut self.pNext) }
343            }
344        }
345        impl Default for $t {
346            fn default() -> Self {
347                Self {
348                    sType: $s_type,
349                    ..Self::ZEROED
350                }
351            }
352        }
353    };
354}
355
356macro_rules! impl_debug_for_union {
357    ( $t:ty ) => {
358        impl core::fmt::Debug for $t {
359            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
360                f.debug_struct(stringify!($t)).finish_non_exhaustive()
361            }
362        }
363    };
364}
365
366macro_rules! impl_enum_display {
367    ( $t:ty { $($item:ident),* } ) => {
368        impl core::fmt::Debug for $t {
369            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
370                write!(f, "{}", self)
371            }
372        }
373        impl core::fmt::Display for $t {
374            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
375                match *self {
376                    $(
377                        $item => write!(f, "{}", stringify!($item)),
378                    )*
379                    _ => write!(f, "{}", self.0),
380                }
381            }
382        }
383    };
384}
385
386macro_rules! impl_flags_display {
387    ( $t:ident { $($item:ident),* } ) => {
388        impl core::fmt::Debug for $t {
389            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
390                if self.is_empty() {
391                    return write!(f, "{}(0)", stringify!($t));
392                }
393                let mut first = true;
394                $(
395                    if self.has_flags($item)
396                    {
397                        if first { first = false; } else { write!(f, " | ")?; }
398                        write!(f, "{}", stringify!($item))?;
399                    }
400                )*
401                const ALL_FLAGS: $t = const { $t ( 0 $(| $item.0)* ) };
402                if ALL_FLAGS.is_empty() {
403                    return write!(f, "0");
404                }
405                let remaining = *self & !ALL_FLAGS;
406                if !remaining.is_empty() {
407                    if !first {
408                        write!(f, " | ")?;
409                    }
410                    write!(f, "{}(0x{:#x})", stringify!($t), remaining.0)?;
411                }
412                Ok(())
413            }
414        }
415        impl core::fmt::Display for $t {
416            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
417                if self.is_empty() {
418                    return write!(f, "0");
419                }
420                let mut first = true;
421                $(
422                    if self.has_flags($item)
423                    {
424                        if first { first = false; } else { write!(f, " | ")?; }
425                        write!(f, "{}", stringify!($item))?;
426                    }
427                )*
428                const ALL_FLAGS: $t = const { $t ( 0 $(| $item.0)* ) };
429                if ALL_FLAGS.is_empty() {
430                    return write!(f, "0");
431                }
432                let remaining = *self & !ALL_FLAGS;
433                if !remaining.is_empty() {
434                    if !first {
435                        write!(f, " | ")?;
436                    }
437                    write!(f, "0x{:#x}", remaining.0)?;
438                }
439                Ok(())
440            }
441        }
442    };
443}
444
445#[macro_export]
446/// Create Cstr from literal UTF-8 string with a trailing null terminator.
447///
448/// ```
449/// # use core::ffi::CStr;
450/// # use covk_sys::c;
451/// let s = c!("Hello, world!");
452/// assert_eq!(s, CStr::from_bytes_with_nul(b"Hello, world!\0").unwrap());
453/// ```
454macro_rules! c {
455    ( $s:literal ) => {
456        unsafe { ::core::ffi::CStr::from_bytes_with_nul_unchecked(concat!($s, "\0").as_bytes()) }
457    };
458}
459
460/// ffi types
461pub mod ffi;
462/// Vulkan loader
463pub mod loader;
464
465mod generated;
466use core::{mem::MaybeUninit, ptr::NonNull};
467
468pub use generated::*;
469
470/// Vulkan command vtables
471pub mod vtbl {
472    use crate::{loader::*, *};
473    use core::ffi::{CStr, c_char};
474    pub use vtbl_gen::*;
475
476    /// Command vtable
477    pub trait CommandVTable {
478        /// Command function pointers
479        type Commands;
480        // unsafe fn load(entry: &Entry) -> Result<Self::Commands, LoadingError>;
481    }
482
483    /// Global commands
484    #[derive(Debug)]
485    pub struct GlobalCommands {
486        pub vkEnumerateInstanceVersion: FN_vkEnumerateInstanceVersion,
487        pub vkEnumerateInstanceExtensionProperties: FN_vkEnumerateInstanceExtensionProperties,
488        pub vkEnumerateInstanceLayerProperties: FN_vkEnumerateInstanceLayerProperties,
489        pub vkCreateInstance: FN_vkCreateInstance,
490    }
491
492    impl GlobalCommands {
493        /// Load global commands from the entry point
494        pub unsafe fn new(entry: &Entry) -> Result<Self, LoadingError> {
495            unsafe {
496                Self::load(|name| entry.GetInstanceProcAddr(VkInstance::null(), name.as_ptr()))
497            }
498        }
499        pub unsafe fn load(
500            mut get: impl FnMut(&CStr) -> Option<ProcAddr>,
501        ) -> Result<Self, LoadingError> {
502            unsafe {
503                Ok(Self {
504                    vkEnumerateInstanceVersion: get(c!("vkEnumerateInstanceVersion"))
505                        .ok_or_else(|| {
506                            LoadingError::MissingGlobalCommand("vkEnumerateInstanceVersion")
507                        })?
508                        .cast(),
509                    vkEnumerateInstanceExtensionProperties: get(c!(
510                        "vkEnumerateInstanceExtensionProperties"
511                    ))
512                    .ok_or_else(|| {
513                        LoadingError::MissingGlobalCommand("vkEnumerateInstanceExtensionProperties")
514                    })?
515                    .cast(),
516                    vkEnumerateInstanceLayerProperties: get(c!(
517                        "vkEnumerateInstanceLayerProperties"
518                    ))
519                    .ok_or_else(|| {
520                        LoadingError::MissingGlobalCommand("vkEnumerateInstanceLayerProperties")
521                    })?
522                    .cast(),
523                    vkCreateInstance: get(c!("vkCreateInstance"))
524                        .ok_or_else(|| LoadingError::MissingGlobalCommand("vkCreateInstance"))?
525                        .cast(),
526                })
527            }
528        }
529    }
530
531    impl GlobalCommands {
532        /// Query instance-level version before instance creation
533        ///
534        /// `vkEnumerateInstanceVersion`
535        pub unsafe fn EnumerateInstanceVersion(&self, pApiVersion: *mut u32) -> VkResult {
536            unsafe { (self.vkEnumerateInstanceVersion)(pApiVersion) }
537        }
538        /// Returns up to requested number of global extension properties
539        ///
540        /// `vkEnumerateInstanceExtensionProperties`
541        pub unsafe fn EnumerateInstanceExtensionProperties(
542            &self,
543            pLayerName: *const c_char,
544            pPropertyCount: *mut u32,
545            pProperties: *mut VkExtensionProperties,
546        ) -> VkResult {
547            unsafe {
548                (self.vkEnumerateInstanceExtensionProperties)(
549                    pLayerName,
550                    pPropertyCount,
551                    pProperties,
552                )
553            }
554        }
555        /// Returns up to requested number of global layer properties
556        ///
557        /// `vkEnumerateInstanceLayerProperties`
558        pub unsafe fn EnumerateInstanceLayerProperties(
559            &self,
560            pPropertyCount: *mut u32,
561            pProperties: *mut VkLayerProperties,
562        ) -> VkResult {
563            unsafe { (self.vkEnumerateInstanceLayerProperties)(pPropertyCount, pProperties) }
564        }
565        /// Create a new Vulkan instance
566        ///
567        /// `vkCreateInstance`
568        pub unsafe fn CreateInstance(
569            &self,
570            pCreateInfo: *const VkInstanceCreateInfo,
571            pAllocator: *const VkAllocationCallbacks,
572            pInstance: *mut VkInstance,
573        ) -> VkResult {
574            unsafe { (self.vkCreateInstance)(pCreateInfo, pAllocator, pInstance) }
575        }
576    }
577
578    impl crate::vtbl::InstanceCommands_1_0 {
579        /// `vkGetInstanceProcAddr`
580        pub unsafe fn GetInstanceProcAddr(&self, instance: VkInstance, pName: &CStr) -> Option<ProcAddr> {
581            unsafe {
582                (self
583                    .vkGetInstanceProcAddr
584                    .expect("Unable to load GetInstanceProcAddr"))(
585                    instance, pName.as_ptr()
586                )
587                    .map(ProcAddr)
588            }
589        }
590        /// `vkGetDeviceProcAddr`
591        pub unsafe fn GetDeviceProcAddr(&self, device: VkDevice, pName: &CStr) -> Option<ProcAddr> {
592            unsafe {
593                (self
594                    .vkGetDeviceProcAddr
595                    .expect("Unable to load GetDeviceProcAddr"))(
596                    device, pName.as_ptr()
597                )
598                .map(ProcAddr)
599            }
600        }
601    }
602}
603
604pub type StdVideoAV1Level = u32;
605pub type StdVideoAV1Profile = u32;
606pub type StdVideoH264LevelIdc = u32;
607pub type StdVideoH265LevelIdc = u32;
608pub type StdVideoH264ProfileIdc = u32;
609pub type StdVideoH265ProfileIdc = u32;
610pub type StdVideoVP9Level = u32;
611pub type StdVideoVP9Profile = u32;
612pub type StdVideoDecodeAV1ReferenceInfo = core::ffi::c_void;
613pub type StdVideoAV1SequenceHeader = core::ffi::c_void;
614pub type StdVideoDecodeAV1PictureInfo = core::ffi::c_void;
615pub type StdVideoDecodeH264ReferenceInfo = core::ffi::c_void;
616pub type StdVideoH264SequenceParameterSet = core::ffi::c_void;
617pub type StdVideoH264PictureParameterSet = core::ffi::c_void;
618pub type StdVideoDecodeH264PictureInfo = core::ffi::c_void;
619pub type StdVideoDecodeH265ReferenceInfo = core::ffi::c_void;
620pub type StdVideoH265VideoParameterSet = core::ffi::c_void;
621pub type StdVideoH265SequenceParameterSet = core::ffi::c_void;
622pub type StdVideoH265PictureParameterSet = core::ffi::c_void;
623pub type StdVideoDecodeH265PictureInfo = core::ffi::c_void;
624pub type StdVideoDecodeVP9PictureInfo = core::ffi::c_void;
625pub type StdVideoEncodeAV1ReferenceInfo = core::ffi::c_void;
626pub type StdVideoEncodeAV1PictureInfo = core::ffi::c_void;
627pub type StdVideoEncodeAV1DecoderModelInfo = core::ffi::c_void;
628pub type StdVideoEncodeAV1OperatingPointInfo = core::ffi::c_void;
629pub type StdVideoEncodeH264ReferenceInfo = core::ffi::c_void;
630pub type StdVideoEncodeH264SliceHeader = core::ffi::c_void;
631pub type StdVideoEncodeH264PictureInfo = core::ffi::c_void;
632pub type StdVideoEncodeH265ReferenceInfo = core::ffi::c_void;
633pub type StdVideoEncodeH265SliceSegmentHeader = core::ffi::c_void;
634pub type StdVideoEncodeH265PictureInfo = core::ffi::c_void;
635
636#[cfg(test)]
637mod tests {
638    use core::ffi::CStr;
639
640    #[test]
641    fn test_c_macro() {
642        let s = c!("Hello, world!");
643        assert_eq!(s, CStr::from_bytes_with_nul(b"Hello, world!\0").unwrap());
644    }
645}