1 use crate::device::physical::{ 2 ConformanceVersion, DriverId, PhysicalDeviceType, PointClippingBehavior, ShaderCoreProperties, 3 ShaderFloatControlsIndependence, SubgroupFeatures, 4 }; 5 use crate::image::{SampleCount, SampleCounts}; 6 use crate::pipeline::shader::ShaderStages; 7 use crate::render_pass::ResolveModes; 8 use crate::Version; 9 use std::convert::TryInto; 10 use std::ffi::CStr; 11 12 /// this is a macro that outputs either T or Option<T> depending on the 2nd argument 13 macro_rules! property_type { 14 ($ty:ty, true) => { 15 $ty 16 }; 17 ($ty:ty, false) => { 18 Option<$ty> 19 }; 20 } 21 22 pub(crate) use property_type; 23 24 /// this is a macro that executes the correct from_vulkan call depending on whether or not the type is Option<T> 25 macro_rules! property_from_vulkan { 26 ($ty:ty, [$($ffi_struct:ident $(.$ffi_struct_field:ident)*),+], $ffi_field:ident, true, $properties:ident) => { 27 std::array::IntoIter::new([ 28 $($properties.$ffi_struct$(.$ffi_struct_field)*.$ffi_field),+ 29 ]).next().and_then(|x| <$ty>::from_vulkan(x)).expect(concat!("expected good ", stringify!($ffi_field))) 30 }; 31 ($ty:ty, [$($ffi_struct:ident $(.$ffi_struct_field:ident)*),+], $ffi_field:ident, false, $properties:ident) => { 32 std::array::IntoIter::new([ 33 $($properties.$ffi_struct.map(|s| s$(.$ffi_struct_field)*.$ffi_field)),+ 34 ]).flatten().next().and_then(|x| <$ty>::from_vulkan(x)) 35 }; 36 } 37 38 pub(crate) use property_from_vulkan; 39 40 macro_rules! properties { 41 { 42 $($member:ident => { 43 doc: $doc:expr, 44 ty: $ty:ty, 45 ffi_name: $ffi_field:ident, 46 ffi_members: [$($ffi_struct:ident $(.$ffi_struct_field:ident)*),+], 47 required: $required:tt, 48 },)* 49 } => { 50 /// Represents all the properties of a physical device. 51 /// 52 /// Depending on the highest version of Vulkan supported by the physical device, and the 53 /// available extensions, not every property may be available. For that reason, properties 54 /// are wrapped in an `Option`. 55 #[derive(Clone, Debug, Default)] 56 #[allow(missing_docs)] 57 pub struct Properties { 58 $( 59 #[doc = $doc] 60 pub $member: $crate::device::properties::property_type!($ty, $required), 61 )* 62 } 63 64 impl From<&PropertiesFfi> for Properties { 65 fn from(properties_ffi: &PropertiesFfi) -> Self { 66 use crate::device::properties::FromVulkan; 67 68 Properties { 69 $( 70 $member: crate::device::properties::property_from_vulkan!($ty, [ $($ffi_struct$(.$ffi_struct_field)*),+ ], $ffi_field, $required, properties_ffi), 71 )* 72 } 73 } 74 } 75 }; 76 } 77 78 pub use crate::autogen::Properties; 79 pub(crate) use properties; 80 81 macro_rules! properties_ffi { 82 { 83 $api_version:ident, 84 $device_extensions:ident, 85 $instance_extensions:ident, 86 $($member:ident => { 87 ty: $ty:ident, 88 provided_by: [$($provided_by:expr),+], 89 conflicts: [$($conflicts:ident),*], 90 },)+ 91 } => { 92 #[derive(Default)] 93 pub(crate) struct PropertiesFfi { 94 properties_vulkan10: ash::vk::PhysicalDeviceProperties2KHR, 95 96 $( 97 $member: Option<ash::vk::$ty>, 98 )+ 99 } 100 101 impl PropertiesFfi { 102 pub(crate) fn make_chain( 103 &mut self, 104 $api_version: crate::Version, 105 $device_extensions: &crate::device::DeviceExtensions, 106 $instance_extensions: &crate::instance::InstanceExtensions, 107 ) { 108 self.properties_vulkan10 = Default::default(); 109 let head = &mut self.properties_vulkan10; 110 111 $( 112 if std::array::IntoIter::new([$($provided_by),+]).any(|x| x) && 113 std::array::IntoIter::new([$(self.$conflicts.is_none()),*]).all(|x| x) { 114 self.$member = Some(Default::default()); 115 let member = self.$member.as_mut().unwrap(); 116 member.p_next = head.p_next; 117 head.p_next = member as *mut _ as _; 118 } 119 )+ 120 } 121 122 pub(crate) fn head_as_ref(&self) -> &ash::vk::PhysicalDeviceProperties2KHR { 123 &self.properties_vulkan10 124 } 125 126 pub(crate) fn head_as_mut(&mut self) -> &mut ash::vk::PhysicalDeviceProperties2KHR { 127 &mut self.properties_vulkan10 128 } 129 } 130 }; 131 } 132 133 pub(crate) use {crate::autogen::PropertiesFfi, properties_ffi}; 134 135 // A bit of a hack... 136 pub(crate) trait FromVulkan<F> 137 where 138 Self: Sized, 139 { from_vulkan(val: F) -> Option<Self>140 fn from_vulkan(val: F) -> Option<Self>; 141 } 142 143 impl FromVulkan<u8> for u8 { 144 #[inline] from_vulkan(val: u8) -> Option<Self>145 fn from_vulkan(val: u8) -> Option<Self> { 146 Some(val) 147 } 148 } 149 150 impl<const N: usize> FromVulkan<[u8; N]> for [u8; N] { 151 #[inline] from_vulkan(val: [u8; N]) -> Option<Self>152 fn from_vulkan(val: [u8; N]) -> Option<Self> { 153 Some(val) 154 } 155 } 156 157 impl FromVulkan<u32> for u32 { 158 #[inline] from_vulkan(val: u32) -> Option<Self>159 fn from_vulkan(val: u32) -> Option<Self> { 160 Some(val) 161 } 162 } 163 164 impl<const N: usize> FromVulkan<[u32; N]> for [u32; N] { 165 #[inline] from_vulkan(val: [u32; N]) -> Option<Self>166 fn from_vulkan(val: [u32; N]) -> Option<Self> { 167 Some(val) 168 } 169 } 170 171 impl FromVulkan<u64> for u64 { 172 #[inline] from_vulkan(val: u64) -> Option<Self>173 fn from_vulkan(val: u64) -> Option<Self> { 174 Some(val) 175 } 176 } 177 178 impl FromVulkan<usize> for usize { 179 #[inline] from_vulkan(val: usize) -> Option<Self>180 fn from_vulkan(val: usize) -> Option<Self> { 181 Some(val) 182 } 183 } 184 185 impl FromVulkan<i32> for i32 { 186 #[inline] from_vulkan(val: i32) -> Option<Self>187 fn from_vulkan(val: i32) -> Option<Self> { 188 Some(val) 189 } 190 } 191 192 impl FromVulkan<i64> for i64 { 193 #[inline] from_vulkan(val: i64) -> Option<Self>194 fn from_vulkan(val: i64) -> Option<Self> { 195 Some(val) 196 } 197 } 198 199 impl FromVulkan<f32> for f32 { 200 #[inline] from_vulkan(val: f32) -> Option<Self>201 fn from_vulkan(val: f32) -> Option<Self> { 202 Some(val) 203 } 204 } 205 206 impl<const N: usize> FromVulkan<[f32; N]> for [f32; N] { 207 #[inline] from_vulkan(val: [f32; N]) -> Option<Self>208 fn from_vulkan(val: [f32; N]) -> Option<Self> { 209 Some(val) 210 } 211 } 212 213 impl<const N: usize> FromVulkan<[std::os::raw::c_char; N]> for String { 214 #[inline] from_vulkan(val: [std::os::raw::c_char; N]) -> Option<Self>215 fn from_vulkan(val: [std::os::raw::c_char; N]) -> Option<Self> { 216 Some(unsafe { CStr::from_ptr(val.as_ptr()).to_string_lossy().into_owned() }) 217 } 218 } 219 220 impl FromVulkan<u32> for Version { 221 #[inline] from_vulkan(val: u32) -> Option<Self>222 fn from_vulkan(val: u32) -> Option<Self> { 223 val.try_into().ok() 224 } 225 } 226 227 impl FromVulkan<ash::vk::Bool32> for bool { 228 #[inline] from_vulkan(val: ash::vk::Bool32) -> Option<Self>229 fn from_vulkan(val: ash::vk::Bool32) -> Option<Self> { 230 Some(val != 0) 231 } 232 } 233 234 impl FromVulkan<ash::vk::ConformanceVersion> for ConformanceVersion { 235 #[inline] from_vulkan(val: ash::vk::ConformanceVersion) -> Option<Self>236 fn from_vulkan(val: ash::vk::ConformanceVersion) -> Option<Self> { 237 Some(val.into()) 238 } 239 } 240 241 impl FromVulkan<ash::vk::DriverId> for DriverId { 242 #[inline] from_vulkan(val: ash::vk::DriverId) -> Option<Self>243 fn from_vulkan(val: ash::vk::DriverId) -> Option<Self> { 244 val.try_into().ok() 245 } 246 } 247 248 impl FromVulkan<ash::vk::Extent2D> for [u32; 2] { 249 #[inline] from_vulkan(val: ash::vk::Extent2D) -> Option<Self>250 fn from_vulkan(val: ash::vk::Extent2D) -> Option<Self> { 251 Some([val.width, val.height]) 252 } 253 } 254 255 impl FromVulkan<ash::vk::PhysicalDeviceType> for PhysicalDeviceType { 256 #[inline] from_vulkan(val: ash::vk::PhysicalDeviceType) -> Option<Self>257 fn from_vulkan(val: ash::vk::PhysicalDeviceType) -> Option<Self> { 258 val.try_into().ok() 259 } 260 } 261 262 impl FromVulkan<ash::vk::PointClippingBehavior> for PointClippingBehavior { 263 #[inline] from_vulkan(val: ash::vk::PointClippingBehavior) -> Option<Self>264 fn from_vulkan(val: ash::vk::PointClippingBehavior) -> Option<Self> { 265 val.try_into().ok() 266 } 267 } 268 269 impl FromVulkan<ash::vk::ResolveModeFlags> for ResolveModes { 270 #[inline] from_vulkan(val: ash::vk::ResolveModeFlags) -> Option<Self>271 fn from_vulkan(val: ash::vk::ResolveModeFlags) -> Option<Self> { 272 Some(val.into()) 273 } 274 } 275 276 impl FromVulkan<ash::vk::SampleCountFlags> for SampleCounts { 277 #[inline] from_vulkan(val: ash::vk::SampleCountFlags) -> Option<Self>278 fn from_vulkan(val: ash::vk::SampleCountFlags) -> Option<Self> { 279 Some(val.into()) 280 } 281 } 282 283 impl FromVulkan<ash::vk::SampleCountFlags> for SampleCount { 284 #[inline] from_vulkan(val: ash::vk::SampleCountFlags) -> Option<Self>285 fn from_vulkan(val: ash::vk::SampleCountFlags) -> Option<Self> { 286 val.try_into().ok() 287 } 288 } 289 290 impl FromVulkan<ash::vk::ShaderCorePropertiesFlagsAMD> for ShaderCoreProperties { 291 #[inline] from_vulkan(val: ash::vk::ShaderCorePropertiesFlagsAMD) -> Option<Self>292 fn from_vulkan(val: ash::vk::ShaderCorePropertiesFlagsAMD) -> Option<Self> { 293 Some(val.into()) 294 } 295 } 296 297 impl FromVulkan<ash::vk::ShaderFloatControlsIndependence> for ShaderFloatControlsIndependence { 298 #[inline] from_vulkan(val: ash::vk::ShaderFloatControlsIndependence) -> Option<Self>299 fn from_vulkan(val: ash::vk::ShaderFloatControlsIndependence) -> Option<Self> { 300 val.try_into().ok() 301 } 302 } 303 304 impl FromVulkan<ash::vk::ShaderStageFlags> for ShaderStages { 305 #[inline] from_vulkan(val: ash::vk::ShaderStageFlags) -> Option<Self>306 fn from_vulkan(val: ash::vk::ShaderStageFlags) -> Option<Self> { 307 Some(val.into()) 308 } 309 } 310 311 impl FromVulkan<ash::vk::SubgroupFeatureFlags> for SubgroupFeatures { 312 #[inline] from_vulkan(val: ash::vk::SubgroupFeatureFlags) -> Option<Self>313 fn from_vulkan(val: ash::vk::SubgroupFeatureFlags) -> Option<Self> { 314 Some(val.into()) 315 } 316 } 317