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