1 // Copyright (c) 2016 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 use crate::device::physical::PhysicalDevice; 11 pub use crate::extensions::{ 12 ExtensionRestriction, ExtensionRestrictionError, SupportedExtensionsError, 13 }; 14 15 macro_rules! device_extensions { 16 ( 17 $($member:ident => { 18 doc: $doc:expr, 19 raw: $raw:expr, 20 requires_core: $requires_core:expr, 21 requires_device_extensions: [$($requires_device_extension:ident),*], 22 requires_instance_extensions: [$($requires_instance_extension:ident),*], 23 required_if_supported: $required_if_supported:expr, 24 conflicts_device_extensions: [$($conflicts_device_extension:ident),*], 25 },)* 26 ) => ( 27 extensions! { 28 DeviceExtensions, 29 $( $member => { 30 doc: $doc, 31 raw: $raw, 32 requires_core: $requires_core, 33 requires_device_extensions: [$($requires_device_extension),*], 34 requires_instance_extensions: [$($requires_instance_extension),*], 35 },)* 36 } 37 38 impl DeviceExtensions { 39 /// Checks enabled extensions against the device version, instance extensions and each other. 40 pub(super) fn check_requirements( 41 &self, 42 supported: &DeviceExtensions, 43 api_version: crate::Version, 44 instance_extensions: &InstanceExtensions, 45 ) -> Result<(), crate::extensions::ExtensionRestrictionError> { 46 $( 47 if self.$member { 48 if !supported.$member { 49 return Err(crate::extensions::ExtensionRestrictionError { 50 extension: stringify!($member), 51 restriction: crate::extensions::ExtensionRestriction::NotSupported, 52 }); 53 } 54 55 if api_version < $requires_core { 56 return Err(crate::extensions::ExtensionRestrictionError { 57 extension: stringify!($member), 58 restriction: crate::extensions::ExtensionRestriction::RequiresCore($requires_core), 59 }); 60 } 61 62 $( 63 if !self.$requires_device_extension { 64 return Err(crate::extensions::ExtensionRestrictionError { 65 extension: stringify!($member), 66 restriction: crate::extensions::ExtensionRestriction::RequiresDeviceExtension(stringify!($requires_device_extension)), 67 }); 68 } 69 )* 70 71 $( 72 if !instance_extensions.$requires_instance_extension { 73 return Err(crate::extensions::ExtensionRestrictionError { 74 extension: stringify!($member), 75 restriction: crate::extensions::ExtensionRestriction::RequiresInstanceExtension(stringify!($requires_instance_extension)), 76 }); 77 } 78 )* 79 80 $( 81 if self.$conflicts_device_extension { 82 return Err(crate::extensions::ExtensionRestrictionError { 83 extension: stringify!($member), 84 restriction: crate::extensions::ExtensionRestriction::ConflictsDeviceExtension(stringify!($conflicts_device_extension)), 85 }); 86 } 87 )* 88 } else { 89 if $required_if_supported && supported.$member { 90 return Err(crate::extensions::ExtensionRestrictionError { 91 extension: stringify!($member), 92 restriction: crate::extensions::ExtensionRestriction::RequiredIfSupported, 93 }); 94 } 95 } 96 )* 97 Ok(()) 98 } 99 100 pub(crate) fn required_if_supported_extensions() -> Self { 101 Self { 102 $( 103 $member: $required_if_supported, 104 )* 105 _unbuildable: crate::extensions::Unbuildable(()) 106 } 107 } 108 } 109 ); 110 } 111 112 pub use crate::autogen::DeviceExtensions; 113 pub(crate) use device_extensions; 114 115 impl DeviceExtensions { 116 /// See the docs of supported_by_device(). 117 #[deprecated( 118 since = "0.25", 119 note = "Use PhysicalDevice::supported_extensions instead" 120 )] supported_by_device_raw( physical_device: PhysicalDevice, ) -> Result<Self, SupportedExtensionsError>121 pub fn supported_by_device_raw( 122 physical_device: PhysicalDevice, 123 ) -> Result<Self, SupportedExtensionsError> { 124 Ok(*physical_device.supported_extensions()) 125 } 126 127 /// Returns a `DeviceExtensions` object with extensions supported by the `PhysicalDevice`. 128 #[deprecated( 129 since = "0.25", 130 note = "Use PhysicalDevice::supported_extensions instead" 131 )] supported_by_device(physical_device: PhysicalDevice) -> Self132 pub fn supported_by_device(physical_device: PhysicalDevice) -> Self { 133 *physical_device.supported_extensions() 134 } 135 136 /// Returns a `DeviceExtensions` object with extensions required as well as supported by the `PhysicalDevice`. 137 /// They are needed to be passed to `Device::new(...)`. 138 #[deprecated( 139 since = "0.25", 140 note = "Use PhysicalDevice::required_extensions instead" 141 )] required_extensions(physical_device: PhysicalDevice) -> Self142 pub fn required_extensions(physical_device: PhysicalDevice) -> Self { 143 *physical_device.required_extensions() 144 } 145 } 146 147 /// This helper type can only be instantiated inside this module. 148 /// See `*Extensions::_unbuildable`. 149 #[doc(hidden)] 150 #[derive(Debug, Copy, Clone, PartialEq, Eq)] 151 pub struct Unbuildable(()); 152 153 #[cfg(test)] 154 mod tests { 155 use crate::device::DeviceExtensions; 156 use std::ffi::CString; 157 158 #[test] empty_extensions()159 fn empty_extensions() { 160 let d: Vec<CString> = (&DeviceExtensions::none()).into(); 161 assert!(d.iter().next().is_none()); 162 } 163 164 #[test] required_if_supported_extensions()165 fn required_if_supported_extensions() { 166 assert_eq!( 167 DeviceExtensions::required_if_supported_extensions(), 168 DeviceExtensions { 169 khr_portability_subset: true, 170 ..DeviceExtensions::none() 171 } 172 ) 173 } 174 } 175