• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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