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]
16macro_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]
27macro_rules! VK_API_VERSION_VARIANT {
29 ( $version:expr ) => {
30 ($version as u32) >> 29u32
31 };
32}
33
34#[macro_export]
35macro_rules! VK_API_VERSION_MAJOR {
37 ( $version:expr ) => {
38 (($version as u32) >> 22u32) & 0x7Fu32
39 };
40}
41
42#[macro_export]
43macro_rules! VK_API_VERSION_MINOR {
45 ( $version:expr ) => {
46 (($version as u32) >> 12u32) & 0x3FFu32
47 };
48}
49
50#[macro_export]
51macro_rules! VK_API_VERSION_PATCH {
53 ( $version:expr ) => {
54 ($version as u32) & 0xFFFu32
55 };
56}
57
58pub const VK_API_VERSION_1_0: u32 = VK_MAKE_API_VERSION!(0, 1, 0, 0);
60pub const VK_API_VERSION_1_1: u32 = VK_MAKE_API_VERSION!(0, 1, 1, 0);
62pub const VK_API_VERSION_1_2: u32 = VK_MAKE_API_VERSION!(0, 1, 2, 0);
64pub const VK_API_VERSION_1_3: u32 = VK_MAKE_API_VERSION!(0, 1, 3, 0);
66pub const VK_API_VERSION_1_4: u32 = VK_MAKE_API_VERSION!(0, 1, 4, 0);
68
69pub type VkSampleMask = u32;
71pub type VkBool32 = u32;
73pub type VkFlags = u32;
75pub type VkFlags64 = u64;
77pub type VkDeviceSize = u64;
79pub type VkDeviceAddress = u64;
81
82impl VkBaseInStructure {
83 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 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 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 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
120pub trait Chainable: Sized {
122 const TYPE: crate::VkStructureType;
124 fn p_next(&self) -> &*const core::ffi::c_void;
126 fn p_next_mut(&mut self) -> &mut *mut core::ffi::c_void;
128
129 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 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 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 unsafe fn upcast(&self) -> &VkBaseInStructure {
158 unsafe { core::mem::transmute(self) }
159 }
160
161 unsafe fn upcast_mut(&mut self) -> &mut VkBaseOutStructure {
163 unsafe { core::mem::transmute(self) }
164 }
165}
166
167pub trait Extend<T: Chainable>: Chainable {}
169
170pub trait Handle {
172 const TYPE: crate::VkObjectType;
174
175 fn null() -> Self;
176 fn is_null(&self) -> bool;
177}
178
179pub trait RootHandle: Handle {}
181
182pub trait SubHandle: Handle {
184 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 pub const fn empty() -> Self {
208 Self(0)
209 }
210 pub const fn is_empty(self) -> bool {
212 self.0 == 0
213 }
214 pub const fn has_flags(self, flags: Self) -> bool {
216 (self.0 & flags.0) == flags.0
217 }
218 pub const fn has_any_flags(self, flags: Self) -> bool {
220 (self.0 & flags.0) != 0
221 }
222 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]
446macro_rules! c {
455 ( $s:literal ) => {
456 unsafe { ::core::ffi::CStr::from_bytes_with_nul_unchecked(concat!($s, "\0").as_bytes()) }
457 };
458}
459
460pub mod ffi;
462pub mod loader;
464
465mod generated;
466use core::{mem::MaybeUninit, ptr::NonNull};
467
468pub use generated::*;
469
470pub mod vtbl {
472 use crate::{loader::*, *};
473 use core::ffi::{CStr, c_char};
474 pub use vtbl_gen::*;
475
476 pub trait CommandVTable {
478 type Commands;
480 }
482
483 #[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 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 pub unsafe fn EnumerateInstanceVersion(&self, pApiVersion: *mut u32) -> VkResult {
536 unsafe { (self.vkEnumerateInstanceVersion)(pApiVersion) }
537 }
538 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 pub unsafe fn EnumerateInstanceLayerProperties(
559 &self,
560 pPropertyCount: *mut u32,
561 pProperties: *mut VkLayerProperties,
562 ) -> VkResult {
563 unsafe { (self.vkEnumerateInstanceLayerProperties)(pPropertyCount, pProperties) }
564 }
565 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 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 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}