1 // Copyright (c) 2022 The Vulkano developers
2 // Licensed under the Apache License, Version 2.0
3 // <LICENSE-APACHE or
4 // https://www.apache.org/licenses/LICENSE-2.0> or the MIT
5 // license <LICENSE-MIT or https://opensource.org/licenses/MIT>,
6 // at your option. All files in the project carrying such
7 // notice may not be copied, modified, or distributed except
8 // according to those terms.
9 
10 macro_rules! vulkan_bitflags {
11     {
12         $(#[doc = $ty_doc:literal])*
13         $ty:ident
14         $( impl { $($impls:item)* } )?
15         = $ty_ffi:ident($repr:ty);
16 
17         $(
18             $(#[doc = $flag_doc:literal])*
19             $flag_name:ident = $flag_name_ffi:ident,
20         )+
21     } => {
22         $(#[doc = $ty_doc])*
23         #[derive(Clone, Copy, PartialEq, Eq, Hash)]
24         pub struct $ty($repr);
25 
26         impl $ty {
27             $(
28                 $(#[doc = $flag_doc])*
29                 pub const $flag_name: Self = Self(ash::vk::$ty_ffi::$flag_name_ffi.as_raw());
30             )*
31 
32             #[doc = concat!("Returns a `", stringify!($ty), "` with none of the flags set.")]
33             #[inline]
34             pub const fn empty() -> Self {
35                 Self(0)
36             }
37 
38             #[deprecated(since = "0.31.0", note = "Use `empty` instead.")]
39             #[doc = concat!("Returns a `", stringify!($ty), "` with none of the flags set.")]
40             #[inline]
41             pub const fn none() -> Self {
42                 Self::empty()
43             }
44 
45             #[doc = concat!("Returns a `", stringify!($ty), "` with all of the flags set.")]
46             #[inline]
47             pub const fn all() -> Self {
48                 Self(Self::all_raw())
49             }
50 
51             const fn all_raw() -> $repr {
52                 0
53                 $(
54                     | ash::vk::$ty_ffi::$flag_name_ffi.as_raw()
55                 )*
56             }
57 
58             /// Returns whether no flags are set in `self`.
59             #[inline]
60             pub const fn is_empty(self) -> bool {
61                 self.0 == 0
62             }
63 
64             /// Returns whether any flags are set in both `self` and `other`.
65             #[inline]
66             pub const fn intersects(self, #[allow(unused_variables)] other: Self) -> bool {
67                 self.0 & other.0 != 0
68             }
69 
70             /// Returns whether all flags in `other` are set in `self`.
71             #[inline]
72             pub const fn contains(self, #[allow(unused_variables)] other: Self) -> bool {
73                 self.0 & other.0 == other.0
74             }
75 
76             /// Returns the union of `self` and `other`.
77             #[inline]
78             pub const fn union(self, #[allow(unused_variables)] other: Self) -> Self {
79                 Self(self.0 | other.0)
80             }
81 
82             /// Returns the intersection of `self` and `other`.
83             #[inline]
84             pub const fn intersection(self, #[allow(unused_variables)] other: Self) -> Self {
85                 Self(self.0 & other.0)
86             }
87 
88             /// Returns `self` without the flags set in `other`.
89             #[inline]
90             pub const fn difference(self, #[allow(unused_variables)] other: Self) -> Self {
91                 Self(self.0 & !other.0)
92             }
93 
94             /// Returns the flags that are set in `self` or `other`, but not in both.
95             #[inline]
96             pub const fn symmetric_difference(self, #[allow(unused_variables)] other: Self) -> Self {
97                 Self(self.0 ^ other.0)
98             }
99 
100             /// Returns the flags not in `self`.
101             #[inline]
102             pub const fn complement(self) -> Self {
103                 Self(!self.0 & Self::all_raw())
104             }
105 
106             $( $($impls)* )?
107         }
108 
109         impl Default for $ty {
110             #[inline]
111             fn default() -> Self {
112                 Self::empty()
113             }
114         }
115 
116         impl std::fmt::Debug for $ty {
117             fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
118                 #[allow(unused_mut)]
119                 let mut written = false;
120 
121                 $(
122                     if self.intersects(Self::$flag_name) {
123                         if written {
124                             write!(f, " | ")?;
125                         }
126 
127                         write!(f, stringify!($flag_name))?;
128                         written = true;
129                     }
130                 )*
131 
132                 if !written {
133                     write!(f, "empty()")?;
134                 }
135 
136                 Ok(())
137             }
138         }
139 
140         impl From<$ty> for ash::vk::$ty_ffi {
141             #[inline]
142             fn from(val: $ty) -> Self {
143                 ash::vk::$ty_ffi::from_raw(val.0)
144             }
145         }
146 
147         impl From<ash::vk::$ty_ffi> for $ty {
148             #[inline]
149             fn from(val: ash::vk::$ty_ffi) -> Self {
150                 Self(val.as_raw() & Self::all_raw())
151             }
152         }
153 
154         impl std::ops::BitAnd for $ty {
155             type Output = Self;
156 
157             #[inline]
158             fn bitand(self, rhs: Self) -> Self {
159                 self.intersection(rhs)
160             }
161         }
162 
163         impl std::ops::BitAndAssign for $ty {
164             #[inline]
165             fn bitand_assign(&mut self, rhs: Self) {
166                 *self = self.intersection(rhs);
167             }
168         }
169 
170         impl std::ops::BitOr for $ty {
171             type Output = Self;
172 
173             #[inline]
174             fn bitor(self, rhs: Self) -> Self {
175                 self.union(rhs)
176             }
177         }
178 
179         impl std::ops::BitOrAssign for $ty {
180             #[inline]
181             fn bitor_assign(&mut self, rhs: Self) {
182                 *self = self.union(rhs);
183             }
184         }
185 
186         impl std::ops::BitXor for $ty {
187             type Output = Self;
188 
189             #[inline]
190             fn bitxor(self, rhs: Self) -> Self {
191                 self.symmetric_difference(rhs)
192             }
193         }
194 
195         impl std::ops::BitXorAssign for $ty {
196             #[inline]
197             fn bitxor_assign(&mut self, rhs: Self) {
198                 *self = self.symmetric_difference(rhs);
199             }
200         }
201 
202         impl std::ops::Sub for $ty {
203             type Output = Self;
204 
205             #[inline]
206             fn sub(self, rhs: Self) -> Self {
207                 self.difference(rhs)
208             }
209         }
210 
211         impl std::ops::SubAssign for $ty {
212             #[inline]
213             fn sub_assign(&mut self, rhs: Self) {
214                 *self = self.difference(rhs);
215             }
216         }
217 
218         impl std::ops::Not for $ty {
219             type Output = Self;
220 
221             #[inline]
222             fn not(self) -> Self {
223                 self.complement()
224             }
225         }
226     };
227 
228     {
229         #[non_exhaustive]
230 
231         $(#[doc = $ty_doc:literal])*
232         $ty:ident
233         $( impl { $($impls:item)* } )?
234         = $ty_ffi:ident($repr:ty);
235 
236         $(
237             $(#[doc = $flag_doc:literal])*
238             $flag_name:ident = $flag_name_ffi:ident
239             $({
240                 $(api_version: $api_version:ident,)?
241                 $(features: [$($feature:ident),+ $(,)?],)?
242                 $(device_extensions: [$($device_extension:ident),+ $(,)?],)?
243                 $(instance_extensions: [$($instance_extension:ident),+ $(,)?],)?
244             })?
245             ,
246         )*
247     } => {
248         $(#[doc = $ty_doc])*
249         #[derive(Clone, Copy, PartialEq, Eq, Hash)]
250         pub struct $ty($repr);
251 
252         impl $ty {
253             $(
254                 $(#[doc = $flag_doc])*
255                 pub const $flag_name: Self = Self(ash::vk::$ty_ffi::$flag_name_ffi.as_raw());
256             )*
257 
258             #[doc = concat!("Returns a `", stringify!($ty), "` with none of the flags set.")]
259             #[inline]
260             pub const fn empty() -> Self {
261                 Self(0)
262             }
263 
264             #[deprecated(since = "0.31.0", note = "Use `empty` instead.")]
265             #[doc = concat!("Returns a `", stringify!($ty), "` with none of the flags set.")]
266             #[inline]
267             pub const fn none() -> Self {
268                 Self::empty()
269             }
270 
271             const fn all_raw() -> $repr {
272                 0
273                 $(
274                     | ash::vk::$ty_ffi::$flag_name_ffi.as_raw()
275                 )*
276             }
277 
278             /// Returns the number of flags set in self.
279             #[inline]
280             pub const fn count(self) -> u32 {
281                 self.0.count_ones()
282             }
283 
284             /// Returns whether no flags are set in `self`.
285             #[inline]
286             pub const fn is_empty(self) -> bool {
287                 self.0 == 0
288             }
289 
290             /// Returns whether any flags are set in both `self` and `other`.
291             #[inline]
292             pub const fn intersects(self, #[allow(unused_variables)] other: Self) -> bool {
293                 self.0 & other.0 != 0
294             }
295 
296             /// Returns whether all flags in `other` are set in `self`.
297             #[inline]
298             pub const fn contains(self, #[allow(unused_variables)] other: Self) -> bool {
299                 self.0 & other.0 == other.0
300             }
301 
302             /// Returns the union of `self` and `other`.
303             #[inline]
304             pub const fn union(self, #[allow(unused_variables)] other: Self) -> Self {
305                 Self(self.0 | other.0)
306             }
307 
308             /// Returns the intersection of `self` and `other`.
309             #[inline]
310             pub const fn intersection(self, #[allow(unused_variables)] other: Self) -> Self {
311                 Self(self.0 & other.0)
312             }
313 
314             /// Returns `self` without the flags set in `other`.
315             #[inline]
316             pub const fn difference(self, #[allow(unused_variables)] other: Self) -> Self {
317                 Self(self.0 & !other.0)
318             }
319 
320             /// Returns the flags that are set in `self` or `other`, but not in both.
321             #[inline]
322             pub const fn symmetric_difference(self, #[allow(unused_variables)] other: Self) -> Self {
323                 Self(self.0 ^ other.0)
324             }
325 
326             #[allow(dead_code)]
327             pub(crate) fn validate_device(
328                 self,
329                 #[allow(unused_variables)] device: &crate::device::Device,
330             ) -> Result<(), crate::RequirementNotMet> {
331                 $(
332                     $(
333                         if self.intersects(Self::$flag_name) && ![
334                             $(
335                                 device.api_version() >= crate::Version::$api_version,
336                             )?
337                             $($(
338                                 device.enabled_features().$feature,
339                             )+)?
340                             $($(
341                                 device.enabled_extensions().$device_extension,
342                             )+)?
343                             $($(
344                                 device.instance().enabled_extensions().$instance_extension,
345                             )+)?
346                         ].into_iter().any(|x| x) {
347                             return Err(crate::RequirementNotMet {
348                                 required_for: concat!("`", stringify!($ty), "::", stringify!($flag_name), "`"),
349                                 requires_one_of: crate::RequiresOneOf {
350                                     $(api_version: Some(crate::Version::$api_version),)?
351                                     $(features: &[$(stringify!($feature)),+],)?
352                                     $(device_extensions: &[$(stringify!($device_extension)),+],)?
353                                     $(instance_extensions: &[$(stringify!($instance_extension)),+],)?
354                                     ..Default::default()
355                                 },
356                             });
357                         }
358                     )?
359                 )*
360 
361                 Ok(())
362             }
363 
364             #[allow(dead_code)]
365             pub(crate) fn validate_physical_device(
366                 self,
367                 #[allow(unused_variables)] physical_device: &crate::device::physical::PhysicalDevice,
368             ) -> Result<(), crate::RequirementNotMet> {
369                 $(
370                     $(
371                         if self.intersects(Self::$flag_name) && ![
372                             $(
373                                 physical_device.api_version() >= crate::Version::$api_version,
374                             )?
375                             $($(
376                                 physical_device.supported_features().$feature,
377                             )+)?
378                             $($(
379                                 physical_device.supported_extensions().$device_extension,
380                             )+)?
381                             $($(
382                                 physical_device.instance().enabled_extensions().$instance_extension,
383                             )+)?
384                         ].into_iter().any(|x| x) {
385                             return Err(crate::RequirementNotMet {
386                                 required_for: concat!("`", stringify!($ty), "::", stringify!($flag_name), "`"),
387                                 requires_one_of: crate::RequiresOneOf {
388                                     $(api_version: Some(crate::Version::$api_version),)?
389                                     $(features: &[$(stringify!($feature)),+],)?
390                                     $(device_extensions: &[$(stringify!($device_extension)),+],)?
391                                     $(instance_extensions: &[$(stringify!($instance_extension)),+],)?
392                                     ..Default::default()
393                                 },
394                             });
395                         }
396                     )?
397                 )*
398 
399                 Ok(())
400             }
401 
402             #[allow(dead_code)]
403             pub(crate) fn validate_instance(
404                 self,
405                 #[allow(unused_variables)] instance: &crate::instance::Instance,
406             ) -> Result<(), crate::RequirementNotMet> {
407                 $(
408                     $(
409                         if self.intersects(Self::$flag_name) && ![
410                             $(
411                                 instance.api_version() >= crate::Version::$api_version,
412                             )?
413                             $($(
414                                 instance.enabled_extensions().$instance_extension,
415                             )+)?
416                         ].into_iter().any(|x| x) {
417                             return Err(crate::RequirementNotMet {
418                                 required_for: concat!("`", stringify!($ty), "::", stringify!($flag_name), "`"),
419                                 requires_one_of: crate::RequiresOneOf {
420                                     $(api_version: Some(crate::Version::$api_version),)?
421                                     $(instance_extensions: &[$(stringify!($instance_extension)),+],)?
422                                     ..Default::default()
423                                 },
424                             });
425                         }
426                     )?
427                 )*
428 
429                 Ok(())
430             }
431 
432             $( $($impls)* )?
433         }
434 
435         impl Default for $ty {
436             #[inline]
437             fn default() -> Self {
438                 Self::empty()
439             }
440         }
441 
442         impl std::fmt::Debug for $ty {
443             fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
444                 #[allow(unused_mut)]
445                 let mut written = false;
446 
447                 $(
448                     if self.intersects(Self::$flag_name) {
449                         if written {
450                             write!(f, " | ")?;
451                         }
452 
453                         write!(f, stringify!($flag_name))?;
454                         written = true;
455                     }
456                 )*
457 
458                 if !written {
459                     write!(f, "empty()")?;
460                 }
461 
462                 Ok(())
463             }
464         }
465 
466         impl From<$ty> for ash::vk::$ty_ffi {
467             #[inline]
468             fn from(val: $ty) -> Self {
469                 ash::vk::$ty_ffi::from_raw(val.0)
470             }
471         }
472 
473         impl From<ash::vk::$ty_ffi> for $ty {
474             #[inline]
475             fn from(val: ash::vk::$ty_ffi) -> Self {
476                 Self(val.as_raw() & Self::all_raw())
477             }
478         }
479 
480         impl std::ops::BitAnd for $ty {
481             type Output = Self;
482 
483             #[inline]
484             fn bitand(self, rhs: Self) -> Self {
485                 self.intersection(rhs)
486             }
487         }
488 
489         impl std::ops::BitAndAssign for $ty {
490             #[inline]
491             fn bitand_assign(&mut self, rhs: Self) {
492                 *self = self.intersection(rhs);
493             }
494         }
495 
496         impl std::ops::BitOr for $ty {
497             type Output = Self;
498 
499             #[inline]
500             fn bitor(self, rhs: Self) -> Self {
501                 self.union(rhs)
502             }
503         }
504 
505         impl std::ops::BitOrAssign for $ty {
506             #[inline]
507             fn bitor_assign(&mut self, rhs: Self) {
508                 *self = self.union(rhs);
509             }
510         }
511 
512         impl std::ops::BitXor for $ty {
513             type Output = Self;
514 
515             #[inline]
516             fn bitxor(self, rhs: Self) -> Self {
517                 self.symmetric_difference(rhs)
518             }
519         }
520 
521         impl std::ops::BitXorAssign for $ty {
522             #[inline]
523             fn bitxor_assign(&mut self, rhs: Self) {
524                 *self = self.symmetric_difference(rhs);
525             }
526         }
527 
528         impl std::ops::Sub for $ty {
529             type Output = Self;
530 
531             #[inline]
532             fn sub(self, rhs: Self) -> Self {
533                 self.difference(rhs)
534             }
535         }
536 
537         impl std::ops::SubAssign for $ty {
538             #[inline]
539             fn sub_assign(&mut self, rhs: Self) {
540                 *self = self.difference(rhs);
541             }
542         }
543     };
544 }
545 
546 macro_rules! vulkan_enum {
547     {
548         $(#[doc = $ty_doc:literal])*
549         $ty:ident
550         $( impl { $($impls:item)* } )?
551         = $ty_ffi:ident($repr:ty);
552 
553         $(
554             $(#[doc = $flag_doc:literal])*
555             $flag_name:ident = $flag_name_ffi:ident,
556         )+
557     } => {
558         $(#[doc = $ty_doc])*
559         #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
560         #[repr($repr)]
561         pub enum $ty {
562             $(
563                 $(#[doc = $flag_doc])*
564                 $flag_name = ash::vk::$ty_ffi::$flag_name_ffi.as_raw(),
565             )+
566         }
567 
568         $(
569             impl $ty {
570                 $($impls)*
571             }
572         )?
573 
574         impl From<$ty> for ash::vk::$ty_ffi {
575             #[inline]
576             fn from(val: $ty) -> Self {
577                 ash::vk::$ty_ffi::from_raw(val as $repr)
578             }
579         }
580 
581         impl TryFrom<ash::vk::$ty_ffi> for $ty {
582             type Error = ();
583 
584             #[inline]
585             fn try_from(val: ash::vk::$ty_ffi) -> Result<Self, Self::Error> {
586                 Ok(match val {
587                     $(
588                         ash::vk::$ty_ffi::$flag_name_ffi => Self::$flag_name,
589                     )+
590                     _ => return Err(()),
591                 })
592             }
593         }
594     };
595 
596     {
597         #[non_exhaustive]
598 
599         $(#[doc = $ty_doc:literal])*
600         $ty:ident
601         $( impl { $($impls:item)* } )?
602         = $ty_ffi:ident($repr:ty);
603 
604         $(
605             $(#[doc = $flag_doc:literal])*
606             $flag_name:ident = $flag_name_ffi:ident
607             $({
608                 $(api_version: $api_version:ident,)?
609                 $(features: [$($feature:ident),+ $(,)?],)?
610                 $(device_extensions: [$($device_extension:ident),+ $(,)?],)?
611                 $(instance_extensions: [$($instance_extension:ident),+ $(,)?],)?
612             })?
613             ,
614         )+
615     } => {
616         $(#[doc = $ty_doc])*
617         #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
618         #[non_exhaustive]
619         #[repr($repr)]
620         pub enum $ty {
621             $(
622                 $(#[doc = $flag_doc])*
623                 $flag_name = ash::vk::$ty_ffi::$flag_name_ffi.as_raw(),
624             )+
625         }
626 
627         impl $ty {
628             #[allow(dead_code)]
629             pub(crate) fn validate_device(
630                 self,
631                 #[allow(unused_variables)] device: &crate::device::Device,
632             ) -> Result<(), crate::RequirementNotMet> {
633                 match self {
634                     $(
635                         $(
636                             Self::$flag_name => {
637                                 if ![
638                                     $(
639                                         device.api_version() >= crate::Version::$api_version,
640                                     )?
641                                     $($(
642                                         device.enabled_features().$feature,
643                                     )+)?
644                                     $($(
645                                         device.enabled_extensions().$device_extension,
646                                     )+)?
647                                     $($(
648                                         device.instance().enabled_extensions().$instance_extension,
649                                     )+)?
650                                  ].into_iter().any(|x| x) {
651                                     return Err(crate::RequirementNotMet {
652                                         required_for: concat!("`", stringify!($ty), "::", stringify!($flag_name), "`"),
653                                         requires_one_of: crate::RequiresOneOf {
654                                             $(api_version: Some(crate::Version::$api_version),)?
655                                             $(features: &[$(stringify!($feature)),+],)?
656                                             $(device_extensions: &[$(stringify!($device_extension)),+],)?
657                                             $(instance_extensions: &[$(stringify!($instance_extension)),+],)?
658                                             ..Default::default()
659                                         },
660                                     });
661                                 }
662                             },
663                         )?
664                     )+
665                     _ => (),
666                 }
667 
668                 Ok(())
669             }
670 
671             #[allow(dead_code)]
672             pub(crate) fn validate_physical_device(
673                 self,
674                 #[allow(unused_variables)] physical_device: &crate::device::physical::PhysicalDevice,
675             ) -> Result<(), crate::RequirementNotMet> {
676                 match self {
677                     $(
678                         $(
679                             Self::$flag_name => {
680                                 if ![
681                                     $(
682                                         physical_device.api_version() >= crate::Version::$api_version,
683                                     )?
684                                     $($(
685                                         physical_device.supported_features().$feature,
686                                     )+)?
687                                     $($(
688                                         physical_device.supported_extensions().$device_extension,
689                                     )+)?
690                                     $($(
691                                         physical_device.instance().enabled_extensions().$instance_extension,
692                                     )+)?
693                                  ].into_iter().any(|x| x) {
694                                     return Err(crate::RequirementNotMet {
695                                         required_for: concat!("`", stringify!($ty), "::", stringify!($flag_name), "`"),
696                                         requires_one_of: crate::RequiresOneOf {
697                                             $(api_version: Some(crate::Version::$api_version),)?
698                                             $(features: &[$(stringify!($feature)),+],)?
699                                             $(device_extensions: &[$(stringify!($device_extension)),+],)?
700                                             $(instance_extensions: &[$(stringify!($instance_extension)),+],)?
701                                             ..Default::default()
702                                         },
703                                     });
704                                 }
705                             },
706                         )?
707                     )+
708                     _ => (),
709                 }
710 
711                 Ok(())
712             }
713 
714             #[allow(dead_code)]
715             pub(crate) fn validate_instance(
716                 self,
717                 #[allow(unused_variables)] instance: &crate::instance::Instance,
718             ) -> Result<(), crate::RequirementNotMet> {
719                 match self {
720                     $(
721                         $(
722                             Self::$flag_name => {
723                                 if ![
724                                     $(
725                                         instance.api_version() >= crate::Version::$api_version,
726                                     )?
727                                     $($(
728                                         instance.enabled_extensions().$instance_extension,
729                                     )+)?
730                                  ].into_iter().any(|x| x) {
731                                     return Err(crate::RequirementNotMet {
732                                         required_for: concat!("`", stringify!($ty), "::", stringify!($flag_name), "`"),
733                                         requires_one_of: crate::RequiresOneOf {
734                                             $(api_version: Some(crate::Version::$api_version),)?
735                                             $(instance_extensions: &[$(stringify!($instance_extension)),+],)?
736                                             ..Default::default()
737                                         },
738                                     });
739                                 }
740                             },
741                         )?
742                     )+
743                     _ => (),
744                 }
745 
746             Ok(())
747         }
748 
749         $(
750             $($impls)*
751         )?
752     }
753 
754     impl From<$ty> for ash::vk::$ty_ffi {
755         #[inline]
756         fn from(val: $ty) -> Self {
757             ash::vk::$ty_ffi::from_raw(val as $repr)
758         }
759     }
760 
761     impl TryFrom<ash::vk::$ty_ffi> for $ty {
762         type Error = ();
763 
764         #[inline]
765         fn try_from(val: ash::vk::$ty_ffi) -> Result<Self, Self::Error> {
766             Ok(match val {
767                 $(
768                     ash::vk::$ty_ffi::$flag_name_ffi => Self::$flag_name,
769                 )+
770                 _ => return Err(()),
771             })
772         }
773     }
774     };
775 }
776 
777 macro_rules! vulkan_bitflags_enum {
778     {
779         #[non_exhaustive]
780 
781         $(#[doc = $ty_bitflags_doc:literal])*
782         $ty_bitflags:ident
783         $( impl { $($impls_bitflags:item)* } )?
784         ,
785 
786         $(#[doc = $ty_enum_doc:literal])*
787         $ty_enum:ident
788         $( impl { $($impls_enum:item)* } )?
789         ,
790 
791         = $ty_ffi:ident($repr:ty);
792 
793         $(
794             $(#[doc = $flag_doc:literal])*
795             $flag_name_bitflags:ident, $flag_name_enum:ident = $flag_name_ffi:ident
796             $({
797                 $(api_version: $api_version:ident,)?
798                 $(features: [$($feature:ident),+ $(,)?],)?
799                 $(device_extensions: [$($device_extension:ident),+ $(,)?],)?
800                 $(instance_extensions: [$($instance_extension:ident),+ $(,)?],)?
801             })?
802             ,
803         )*
804     } => {
805         crate::macros::vulkan_bitflags! {
806             #[non_exhaustive]
807 
808             $(#[doc = $ty_bitflags_doc])*
809             $ty_bitflags
810             impl {
811                 /// Returns whether `self` contains the flag corresponding to `val`.
812                 #[inline]
813                 pub fn contains_enum(self, val: $ty_enum) -> bool {
814                     self.intersects(val.into())
815                 }
816 
817                 $( $($impls_bitflags)* )?
818             }
819             = $ty_ffi($repr);
820 
821             $(
822                 $(#[doc = $flag_doc])*
823                 $flag_name_bitflags = $flag_name_ffi
824                 $({
825                     $(api_version: $api_version,)?
826                     $(features: [$($feature),+],)?
827                     $(device_extensions: [$($device_extension),+],)?
828                     $(instance_extensions: [$($instance_extension),+],)?
829                 })?
830                 ,
831             )*
832         }
833 
834         crate::macros::vulkan_enum! {
835             #[non_exhaustive]
836 
837             $(#[doc = $ty_enum_doc])*
838             $ty_enum
839             $( impl { $($impls_enum)* } )?
840             = $ty_ffi($repr);
841 
842             $(
843                 $(#[doc = $flag_doc])*
844                 $flag_name_enum = $flag_name_ffi
845                 $({
846                     $(api_version: $api_version,)?
847                     $(features: [$($feature),+],)?
848                     $(device_extensions: [$($device_extension),+],)?
849                     $(instance_extensions: [$($instance_extension),+],)?
850                 })?
851                 ,
852             )*
853         }
854 
855         impl From<$ty_enum> for $ty_bitflags {
856             #[inline]
857             fn from(val: $ty_enum) -> Self {
858                 Self(val as $repr)
859             }
860         }
861 
862         impl FromIterator<$ty_enum> for $ty_bitflags {
863             #[inline]
864             fn from_iter<T>(iter: T) -> Self where T: IntoIterator<Item = $ty_enum> {
865                 iter.into_iter().map(|item| Self::from(item)).fold(Self::empty(), |r, i| r.union(i))
866             }
867         }
868 
869         impl IntoIterator for $ty_bitflags {
870             type Item = $ty_enum;
871             type IntoIter = std::iter::Flatten<
872                 std::array::IntoIter<
873                     Option<Self::Item>,
874                     { $ty_bitflags::all_raw().count_ones() as usize },
875                 >
876             >;
877 
878             #[inline]
879             fn into_iter(self) -> Self::IntoIter {
880                 [
881                     $(
882                         self.intersects(Self::$flag_name_bitflags)
883                             .then_some($ty_enum::$flag_name_enum),
884                     )*
885                 ].into_iter().flatten()
886             }
887         }
888     }
889 }
890 
891 macro_rules! impl_id_counter {
892     ($type:ident $(< $($param:ident $(: $bound:ident $(+ $bounds:ident)* )?),+ >)?) => {
893         $crate::macros::impl_id_counter!(
894             @inner $type $(< $($param),+ >)?, $( $($param $(: $bound $(+ $bounds)* )?),+)?
895         );
896     };
897     ($type:ident $(< $($param:ident $(: $bound:ident $(+ $bounds:ident)* )? + ?Sized),+ >)?) => {
898         $crate::macros::impl_id_counter!(
899             @inner $type $(< $($param),+ >)?, $( $($param $(: $bound $(+ $bounds)* )? + ?Sized),+)?
900         );
901     };
902     (@inner $type:ident $(< $($param:ident),+ >)?, $($bounds:tt)*) => {
903         impl< $($bounds)* > $type $(< $($param),+ >)? {
904             fn next_id() -> std::num::NonZeroU64 {
905                 use std::{
906                     num::NonZeroU64,
907                     sync::atomic::{AtomicU64, Ordering},
908                 };
909 
910                 static COUNTER: AtomicU64 = AtomicU64::new(1);
911 
912                 NonZeroU64::new(COUNTER.fetch_add(1, Ordering::Relaxed)).unwrap_or_else(|| {
913                     println!("an ID counter has overflown ...somehow");
914                     std::process::abort();
915                 })
916             }
917         }
918 
919         impl< $($bounds)* > PartialEq for $type $(< $($param),+ >)? {
920             #[inline]
921             fn eq(&self, other: &Self) -> bool {
922                 self.id == other.id
923             }
924         }
925 
926         impl< $($bounds)* > Eq for $type $(< $($param),+ >)? {}
927 
928         impl< $($bounds)* > std::hash::Hash for $type $(< $($param),+ >)? {
929             fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
930                 self.id.hash(state);
931             }
932         }
933     };
934 }
935 
936 // TODO: Replace with the `?` operator once its constness is stabilized.
937 macro_rules! try_opt {
938     ($e:expr) => {
939         if let Some(val) = $e {
940             val
941         } else {
942             return None;
943         }
944     };
945 }
946 
947 pub(crate) use {impl_id_counter, try_opt, vulkan_bitflags, vulkan_bitflags_enum, vulkan_enum};
948