1 // Copyright (c) 2021 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 super::QueueFamilyProperties;
11 use crate::{
12     buffer::{ExternalBufferInfo, ExternalBufferProperties},
13     cache::OnceCache,
14     device::{properties::Properties, DeviceExtensions, Features, FeaturesFfi, PropertiesFfi},
15     format::{Format, FormatProperties},
16     image::{
17         ImageAspects, ImageFormatInfo, ImageFormatProperties, ImageUsage, SparseImageFormatInfo,
18         SparseImageFormatProperties,
19     },
20     instance::Instance,
21     macros::{impl_id_counter, vulkan_bitflags, vulkan_enum},
22     memory::{ExternalMemoryHandleType, MemoryProperties},
23     swapchain::{
24         ColorSpace, FullScreenExclusive, PresentMode, Surface, SurfaceApi, SurfaceCapabilities,
25         SurfaceInfo, SurfaceTransforms,
26     },
27     sync::{
28         fence::{ExternalFenceInfo, ExternalFenceProperties},
29         semaphore::{ExternalSemaphoreInfo, ExternalSemaphoreProperties},
30     },
31     ExtensionProperties, RequirementNotMet, RequiresOneOf, Version, VulkanError, VulkanObject,
32 };
33 use bytemuck::cast_slice;
34 use std::{
35     error::Error,
36     fmt::{Debug, Display, Error as FmtError, Formatter},
37     mem::MaybeUninit,
38     num::NonZeroU64,
39     ptr,
40     sync::Arc,
41 };
42 
43 /// Represents one of the available physical devices on this machine.
44 ///
45 /// # Examples
46 ///
47 /// ```no_run
48 /// # use vulkano::{
49 /// #     instance::{Instance, InstanceExtensions},
50 /// #     Version, VulkanLibrary,
51 /// # };
52 /// use vulkano::device::physical::PhysicalDevice;
53 ///
54 /// # let library = VulkanLibrary::new().unwrap();
55 /// # let instance = Instance::new(library, Default::default()).unwrap();
56 /// for physical_device in instance.enumerate_physical_devices().unwrap() {
57 ///     print_infos(&physical_device);
58 /// }
59 ///
60 /// fn print_infos(dev: &PhysicalDevice) {
61 ///     println!("Name: {}", dev.properties().device_name);
62 /// }
63 /// ```
64 #[derive(Debug)]
65 pub struct PhysicalDevice {
66     handle: ash::vk::PhysicalDevice,
67     instance: Arc<Instance>,
68     id: NonZeroU64,
69 
70     // Data queried at `PhysicalDevice` creation.
71     api_version: Version,
72     supported_extensions: DeviceExtensions,
73     supported_features: Features,
74     properties: Properties,
75     extension_properties: Vec<ExtensionProperties>,
76     memory_properties: MemoryProperties,
77     queue_family_properties: Vec<QueueFamilyProperties>,
78 
79     // Data queried by the user at runtime, cached for faster lookups.
80     external_buffer_properties: OnceCache<ExternalBufferInfo, ExternalBufferProperties>,
81     external_fence_properties: OnceCache<ExternalFenceInfo, ExternalFenceProperties>,
82     external_semaphore_properties: OnceCache<ExternalSemaphoreInfo, ExternalSemaphoreProperties>,
83     format_properties: OnceCache<Format, FormatProperties>,
84     image_format_properties: OnceCache<ImageFormatInfo, Option<ImageFormatProperties>>,
85     sparse_image_format_properties:
86         OnceCache<SparseImageFormatInfo, Vec<SparseImageFormatProperties>>,
87 }
88 
89 impl PhysicalDevice {
90     /// Creates a new `PhysicalDevice` from a raw object handle.
91     ///
92     /// # Safety
93     ///
94     /// - `handle` must be a valid Vulkan object handle created from `instance`.
from_handle( instance: Arc<Instance>, handle: ash::vk::PhysicalDevice, ) -> Result<Arc<Self>, VulkanError>95     pub unsafe fn from_handle(
96         instance: Arc<Instance>,
97         handle: ash::vk::PhysicalDevice,
98     ) -> Result<Arc<Self>, VulkanError> {
99         let api_version = Self::get_api_version(handle, &instance);
100         let extension_properties = Self::get_extension_properties(handle, &instance)?;
101         let supported_extensions: DeviceExtensions = extension_properties
102             .iter()
103             .map(|property| property.extension_name.as_str())
104             .collect();
105 
106         let supported_features;
107         let properties;
108         let memory_properties;
109         let queue_family_properties;
110 
111         // Get the remaining infos.
112         // If possible, we use VK_KHR_get_physical_device_properties2.
113         if api_version >= Version::V1_1
114             || instance
115                 .enabled_extensions()
116                 .khr_get_physical_device_properties2
117         {
118             supported_features =
119                 Self::get_features2(handle, &instance, api_version, &supported_extensions);
120             properties =
121                 Self::get_properties2(handle, &instance, api_version, &supported_extensions);
122             memory_properties = Self::get_memory_properties2(handle, &instance);
123             queue_family_properties = Self::get_queue_family_properties2(handle, &instance);
124         } else {
125             supported_features = Self::get_features(handle, &instance);
126             properties =
127                 Self::get_properties(handle, &instance, api_version, &supported_extensions);
128             memory_properties = Self::get_memory_properties(handle, &instance);
129             queue_family_properties = Self::get_queue_family_properties(handle, &instance);
130         };
131 
132         Ok(Arc::new(PhysicalDevice {
133             handle,
134             instance,
135             id: Self::next_id(),
136             api_version,
137             supported_extensions,
138             supported_features,
139             properties,
140             extension_properties,
141             memory_properties,
142             queue_family_properties,
143             external_buffer_properties: OnceCache::new(),
144             external_fence_properties: OnceCache::new(),
145             external_semaphore_properties: OnceCache::new(),
146             format_properties: OnceCache::new(),
147             image_format_properties: OnceCache::new(),
148             sparse_image_format_properties: OnceCache::new(),
149         }))
150     }
151 
get_api_version(handle: ash::vk::PhysicalDevice, instance: &Instance) -> Version152     unsafe fn get_api_version(handle: ash::vk::PhysicalDevice, instance: &Instance) -> Version {
153         let fns = instance.fns();
154         let mut output = MaybeUninit::uninit();
155         (fns.v1_0.get_physical_device_properties)(handle, output.as_mut_ptr());
156         let api_version = Version::try_from(output.assume_init().api_version).unwrap();
157         std::cmp::min(instance.max_api_version(), api_version)
158     }
159 
get_extension_properties( handle: ash::vk::PhysicalDevice, instance: &Instance, ) -> Result<Vec<ExtensionProperties>, VulkanError>160     unsafe fn get_extension_properties(
161         handle: ash::vk::PhysicalDevice,
162         instance: &Instance,
163     ) -> Result<Vec<ExtensionProperties>, VulkanError> {
164         let fns = instance.fns();
165 
166         loop {
167             let mut count = 0;
168             (fns.v1_0.enumerate_device_extension_properties)(
169                 handle,
170                 ptr::null(),
171                 &mut count,
172                 ptr::null_mut(),
173             )
174             .result()
175             .map_err(VulkanError::from)?;
176 
177             let mut output = Vec::with_capacity(count as usize);
178             let result = (fns.v1_0.enumerate_device_extension_properties)(
179                 handle,
180                 ptr::null(),
181                 &mut count,
182                 output.as_mut_ptr(),
183             );
184 
185             match result {
186                 ash::vk::Result::SUCCESS => {
187                     output.set_len(count as usize);
188                     return Ok(output.into_iter().map(Into::into).collect());
189                 }
190                 ash::vk::Result::INCOMPLETE => (),
191                 err => return Err(VulkanError::from(err)),
192             }
193         }
194     }
195 
get_features(handle: ash::vk::PhysicalDevice, instance: &Instance) -> Features196     unsafe fn get_features(handle: ash::vk::PhysicalDevice, instance: &Instance) -> Features {
197         let mut output = FeaturesFfi::default();
198 
199         let fns = instance.fns();
200         (fns.v1_0.get_physical_device_features)(handle, &mut output.head_as_mut().features);
201 
202         Features::from(&output)
203     }
204 
get_features2( handle: ash::vk::PhysicalDevice, instance: &Instance, api_version: Version, supported_extensions: &DeviceExtensions, ) -> Features205     unsafe fn get_features2(
206         handle: ash::vk::PhysicalDevice,
207         instance: &Instance,
208         api_version: Version,
209         supported_extensions: &DeviceExtensions,
210     ) -> Features {
211         let mut output = FeaturesFfi::default();
212         output.make_chain(
213             api_version,
214             supported_extensions,
215             instance.enabled_extensions(),
216         );
217 
218         let fns = instance.fns();
219 
220         if instance.api_version() >= Version::V1_1 {
221             (fns.v1_1.get_physical_device_features2)(handle, output.head_as_mut());
222         } else {
223             (fns.khr_get_physical_device_properties2
224                 .get_physical_device_features2_khr)(handle, output.head_as_mut());
225         }
226 
227         Features::from(&output)
228     }
229 
get_properties( handle: ash::vk::PhysicalDevice, instance: &Instance, api_version: Version, supported_extensions: &DeviceExtensions, ) -> Properties230     unsafe fn get_properties(
231         handle: ash::vk::PhysicalDevice,
232         instance: &Instance,
233         api_version: Version,
234         supported_extensions: &DeviceExtensions,
235     ) -> Properties {
236         let mut output = PropertiesFfi::default();
237         output.make_chain(
238             api_version,
239             supported_extensions,
240             instance.enabled_extensions(),
241         );
242 
243         let fns = instance.fns();
244         (fns.v1_0.get_physical_device_properties)(handle, &mut output.head_as_mut().properties);
245 
246         Properties::from(&output)
247     }
248 
get_properties2( handle: ash::vk::PhysicalDevice, instance: &Instance, api_version: Version, supported_extensions: &DeviceExtensions, ) -> Properties249     unsafe fn get_properties2(
250         handle: ash::vk::PhysicalDevice,
251         instance: &Instance,
252         api_version: Version,
253         supported_extensions: &DeviceExtensions,
254     ) -> Properties {
255         let mut output = PropertiesFfi::default();
256         output.make_chain(
257             api_version,
258             supported_extensions,
259             instance.enabled_extensions(),
260         );
261 
262         let fns = instance.fns();
263 
264         if instance.api_version() >= Version::V1_1 {
265             (fns.v1_1.get_physical_device_properties2)(handle, output.head_as_mut());
266         } else {
267             (fns.khr_get_physical_device_properties2
268                 .get_physical_device_properties2_khr)(handle, output.head_as_mut());
269         }
270 
271         Properties::from(&output)
272     }
273 
get_memory_properties( handle: ash::vk::PhysicalDevice, instance: &Instance, ) -> MemoryProperties274     unsafe fn get_memory_properties(
275         handle: ash::vk::PhysicalDevice,
276         instance: &Instance,
277     ) -> MemoryProperties {
278         let mut output = MaybeUninit::uninit();
279 
280         let fns = instance.fns();
281         (fns.v1_0.get_physical_device_memory_properties)(handle, output.as_mut_ptr());
282 
283         output.assume_init().into()
284     }
285 
get_memory_properties2( handle: ash::vk::PhysicalDevice, instance: &Instance, ) -> MemoryProperties286     unsafe fn get_memory_properties2(
287         handle: ash::vk::PhysicalDevice,
288         instance: &Instance,
289     ) -> MemoryProperties {
290         let mut output = ash::vk::PhysicalDeviceMemoryProperties2KHR::default();
291 
292         let fns = instance.fns();
293 
294         if instance.api_version() >= Version::V1_1 {
295             (fns.v1_1.get_physical_device_memory_properties2)(handle, &mut output);
296         } else {
297             (fns.khr_get_physical_device_properties2
298                 .get_physical_device_memory_properties2_khr)(handle, &mut output);
299         }
300 
301         output.memory_properties.into()
302     }
303 
get_queue_family_properties( handle: ash::vk::PhysicalDevice, instance: &Instance, ) -> Vec<QueueFamilyProperties>304     unsafe fn get_queue_family_properties(
305         handle: ash::vk::PhysicalDevice,
306         instance: &Instance,
307     ) -> Vec<QueueFamilyProperties> {
308         let fns = instance.fns();
309 
310         let mut num = 0;
311         (fns.v1_0.get_physical_device_queue_family_properties)(handle, &mut num, ptr::null_mut());
312 
313         let mut output = Vec::with_capacity(num as usize);
314         (fns.v1_0.get_physical_device_queue_family_properties)(
315             handle,
316             &mut num,
317             output.as_mut_ptr(),
318         );
319         output.set_len(num as usize);
320 
321         output.into_iter().map(Into::into).collect()
322     }
323 
get_queue_family_properties2( handle: ash::vk::PhysicalDevice, instance: &Instance, ) -> Vec<QueueFamilyProperties>324     unsafe fn get_queue_family_properties2(
325         handle: ash::vk::PhysicalDevice,
326         instance: &Instance,
327     ) -> Vec<QueueFamilyProperties> {
328         let mut num = 0;
329         let fns = instance.fns();
330 
331         if instance.api_version() >= Version::V1_1 {
332             (fns.v1_1.get_physical_device_queue_family_properties2)(
333                 handle,
334                 &mut num,
335                 ptr::null_mut(),
336             );
337         } else {
338             (fns.khr_get_physical_device_properties2
339                 .get_physical_device_queue_family_properties2_khr)(
340                 handle,
341                 &mut num,
342                 ptr::null_mut(),
343             );
344         }
345 
346         let mut output = vec![ash::vk::QueueFamilyProperties2::default(); num as usize];
347 
348         if instance.api_version() >= Version::V1_1 {
349             (fns.v1_1.get_physical_device_queue_family_properties2)(
350                 handle,
351                 &mut num,
352                 output.as_mut_ptr(),
353             );
354         } else {
355             (fns.khr_get_physical_device_properties2
356                 .get_physical_device_queue_family_properties2_khr)(
357                 handle,
358                 &mut num,
359                 output.as_mut_ptr(),
360             );
361         }
362 
363         output
364             .into_iter()
365             .map(|family| family.queue_family_properties.into())
366             .collect()
367     }
368 
369     /// Returns the instance that owns the physical device.
370     #[inline]
instance(&self) -> &Arc<Instance>371     pub fn instance(&self) -> &Arc<Instance> {
372         &self.instance
373     }
374 
375     /// Returns the version of Vulkan supported by the physical device.
376     ///
377     /// Unlike the `api_version` property, which is the version reported by the device directly,
378     /// this function returns the version the device can actually support, based on the instance's
379     /// `max_api_version`.
380     #[inline]
api_version(&self) -> Version381     pub fn api_version(&self) -> Version {
382         self.api_version
383     }
384 
385     /// Returns the properties reported by the physical device.
386     #[inline]
properties(&self) -> &Properties387     pub fn properties(&self) -> &Properties {
388         &self.properties
389     }
390 
391     /// Returns the extension properties reported by the physical device.
392     #[inline]
extension_properties(&self) -> &[ExtensionProperties]393     pub fn extension_properties(&self) -> &[ExtensionProperties] {
394         &self.extension_properties
395     }
396 
397     /// Returns the extensions that are supported by the physical device.
398     #[inline]
supported_extensions(&self) -> &DeviceExtensions399     pub fn supported_extensions(&self) -> &DeviceExtensions {
400         &self.supported_extensions
401     }
402 
403     /// Returns the features that are supported by the physical device.
404     #[inline]
supported_features(&self) -> &Features405     pub fn supported_features(&self) -> &Features {
406         &self.supported_features
407     }
408 
409     /// Returns the memory properties reported by the physical device.
410     #[inline]
memory_properties(&self) -> &MemoryProperties411     pub fn memory_properties(&self) -> &MemoryProperties {
412         &self.memory_properties
413     }
414 
415     /// Returns the queue family properties reported by the physical device.
416     #[inline]
queue_family_properties(&self) -> &[QueueFamilyProperties]417     pub fn queue_family_properties(&self) -> &[QueueFamilyProperties] {
418         &self.queue_family_properties
419     }
420 
421     /// Queries whether the physical device supports presenting to DirectFB surfaces from queues of
422     /// the given queue family.
423     ///
424     /// # Safety
425     ///
426     /// - `dfb` must be a valid DirectFB `IDirectFB` handle.
427     #[inline]
directfb_presentation_support<D>( &self, queue_family_index: u32, dfb: *const D, ) -> Result<bool, PhysicalDeviceError>428     pub unsafe fn directfb_presentation_support<D>(
429         &self,
430         queue_family_index: u32,
431         dfb: *const D,
432     ) -> Result<bool, PhysicalDeviceError> {
433         self.validate_directfb_presentation_support(queue_family_index, dfb)?;
434 
435         Ok(self.directfb_presentation_support_unchecked(queue_family_index, dfb))
436     }
437 
validate_directfb_presentation_support<D>( &self, queue_family_index: u32, _dfb: *const D, ) -> Result<(), PhysicalDeviceError>438     fn validate_directfb_presentation_support<D>(
439         &self,
440         queue_family_index: u32,
441         _dfb: *const D,
442     ) -> Result<(), PhysicalDeviceError> {
443         if !self.instance.enabled_extensions().ext_directfb_surface {
444             return Err(PhysicalDeviceError::RequirementNotMet {
445                 required_for: "`PhysicalDevice::directfb_presentation_support`",
446                 requires_one_of: RequiresOneOf {
447                     instance_extensions: &["ext_directfb_surface"],
448                     ..Default::default()
449                 },
450             });
451         }
452 
453         // VUID-vkGetPhysicalDeviceDirectFBPresentationSupportEXT-queueFamilyIndex-04119
454         if queue_family_index >= self.queue_family_properties.len() as u32 {
455             return Err(PhysicalDeviceError::QueueFamilyIndexOutOfRange {
456                 queue_family_index,
457                 queue_family_count: self.queue_family_properties.len() as u32,
458             });
459         }
460 
461         // VUID-vkGetPhysicalDeviceDirectFBPresentationSupportEXT-dfb-parameter
462         // Can't validate, therefore unsafe
463 
464         Ok(())
465     }
466 
467     #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
468     #[inline]
directfb_presentation_support_unchecked<D>( &self, queue_family_index: u32, dfb: *const D, ) -> bool469     pub unsafe fn directfb_presentation_support_unchecked<D>(
470         &self,
471         queue_family_index: u32,
472         dfb: *const D,
473     ) -> bool {
474         let fns = self.instance.fns();
475         (fns.ext_directfb_surface
476             .get_physical_device_direct_fb_presentation_support_ext)(
477             self.handle,
478             queue_family_index,
479             dfb as *mut _,
480         ) != 0
481     }
482 
483     /// Retrieves the external memory properties supported for buffers with a given configuration.
484     ///
485     /// Instance API version must be at least 1.1, or the [`khr_external_memory_capabilities`]
486     /// extension must be enabled on the instance.
487     ///
488     /// The results of this function are cached, so that future calls with the same arguments
489     /// do not need to make a call to the Vulkan API again.
490     ///
491     /// [`khr_external_memory_capabilities`]: crate::instance::InstanceExtensions::khr_external_memory_capabilities
492     #[inline]
external_buffer_properties( &self, info: ExternalBufferInfo, ) -> Result<ExternalBufferProperties, PhysicalDeviceError>493     pub fn external_buffer_properties(
494         &self,
495         info: ExternalBufferInfo,
496     ) -> Result<ExternalBufferProperties, PhysicalDeviceError> {
497         self.validate_external_buffer_properties(&info)?;
498 
499         unsafe { Ok(self.external_buffer_properties_unchecked(info)) }
500     }
501 
validate_external_buffer_properties( &self, info: &ExternalBufferInfo, ) -> Result<(), PhysicalDeviceError>502     fn validate_external_buffer_properties(
503         &self,
504         info: &ExternalBufferInfo,
505     ) -> Result<(), PhysicalDeviceError> {
506         if !(self.instance.api_version() >= Version::V1_1
507             || self
508                 .instance
509                 .enabled_extensions()
510                 .khr_external_memory_capabilities)
511         {
512             return Err(PhysicalDeviceError::RequirementNotMet {
513                 required_for: "`PhysicalDevice::external_buffer_properties`",
514                 requires_one_of: RequiresOneOf {
515                     api_version: Some(Version::V1_1),
516                     instance_extensions: &["khr_external_memory_capabilities"],
517                     ..Default::default()
518                 },
519             });
520         }
521 
522         let &ExternalBufferInfo {
523             handle_type,
524             usage,
525             sparse: _,
526             _ne: _,
527         } = info;
528 
529         // VUID-VkPhysicalDeviceExternalBufferInfo-usage-parameter
530         usage.validate_physical_device(self)?;
531 
532         // VUID-VkPhysicalDeviceExternalBufferInfo-usage-requiredbitmask
533         assert!(!usage.is_empty());
534 
535         // VUID-VkPhysicalDeviceExternalBufferInfo-handleType-parameter
536         handle_type.validate_physical_device(self)?;
537 
538         Ok(())
539     }
540 
541     #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
542     #[inline]
external_buffer_properties_unchecked( &self, info: ExternalBufferInfo, ) -> ExternalBufferProperties543     pub unsafe fn external_buffer_properties_unchecked(
544         &self,
545         info: ExternalBufferInfo,
546     ) -> ExternalBufferProperties {
547         self.external_buffer_properties.get_or_insert(info, |info| {
548             /* Input */
549 
550             let &ExternalBufferInfo {
551                 handle_type,
552                 usage,
553                 sparse,
554                 _ne: _,
555             } = info;
556 
557             let external_buffer_info = ash::vk::PhysicalDeviceExternalBufferInfo {
558                 flags: sparse.map(Into::into).unwrap_or_default(),
559                 usage: usage.into(),
560                 handle_type: handle_type.into(),
561                 ..Default::default()
562             };
563 
564             /* Output */
565 
566             let mut external_buffer_properties = ash::vk::ExternalBufferProperties::default();
567 
568             /* Call */
569 
570             let fns = self.instance.fns();
571 
572             if self.instance.api_version() >= Version::V1_1 {
573                 (fns.v1_1.get_physical_device_external_buffer_properties)(
574                     self.handle,
575                     &external_buffer_info,
576                     &mut external_buffer_properties,
577                 )
578             } else {
579                 (fns.khr_external_memory_capabilities
580                     .get_physical_device_external_buffer_properties_khr)(
581                     self.handle,
582                     &external_buffer_info,
583                     &mut external_buffer_properties,
584                 );
585             }
586 
587             ExternalBufferProperties {
588                 external_memory_properties: external_buffer_properties
589                     .external_memory_properties
590                     .into(),
591             }
592         })
593     }
594 
595     /// Retrieves the external handle properties supported for fences with a given
596     /// configuration.
597     ///
598     /// The instance API version must be at least 1.1, or the [`khr_external_fence_capabilities`]
599     /// extension must be enabled on the instance.
600     ///
601     /// The results of this function are cached, so that future calls with the same arguments
602     /// do not need to make a call to the Vulkan API again.
603     ///
604     /// [`khr_external_fence_capabilities`]: crate::instance::InstanceExtensions::khr_external_fence_capabilities
605     #[inline]
external_fence_properties( &self, info: ExternalFenceInfo, ) -> Result<ExternalFenceProperties, PhysicalDeviceError>606     pub fn external_fence_properties(
607         &self,
608         info: ExternalFenceInfo,
609     ) -> Result<ExternalFenceProperties, PhysicalDeviceError> {
610         self.validate_external_fence_properties(&info)?;
611 
612         unsafe { Ok(self.external_fence_properties_unchecked(info)) }
613     }
614 
validate_external_fence_properties( &self, info: &ExternalFenceInfo, ) -> Result<(), PhysicalDeviceError>615     fn validate_external_fence_properties(
616         &self,
617         info: &ExternalFenceInfo,
618     ) -> Result<(), PhysicalDeviceError> {
619         if !(self.instance.api_version() >= Version::V1_1
620             || self
621                 .instance
622                 .enabled_extensions()
623                 .khr_external_fence_capabilities)
624         {
625             return Err(PhysicalDeviceError::RequirementNotMet {
626                 required_for: "`PhysicalDevice::external_fence_properties`",
627                 requires_one_of: RequiresOneOf {
628                     api_version: Some(Version::V1_1),
629                     instance_extensions: &["khr_external_fence_capabilities"],
630                     ..Default::default()
631                 },
632             });
633         }
634 
635         let &ExternalFenceInfo {
636             handle_type,
637             _ne: _,
638         } = info;
639 
640         // VUID-VkPhysicalDeviceExternalFenceInfo-handleType-parameter
641         handle_type.validate_physical_device(self)?;
642 
643         Ok(())
644     }
645 
646     #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
647     #[inline]
external_fence_properties_unchecked( &self, info: ExternalFenceInfo, ) -> ExternalFenceProperties648     pub unsafe fn external_fence_properties_unchecked(
649         &self,
650         info: ExternalFenceInfo,
651     ) -> ExternalFenceProperties {
652         self.external_fence_properties.get_or_insert(info, |info| {
653             /* Input */
654 
655             let &ExternalFenceInfo {
656                 handle_type,
657                 _ne: _,
658             } = info;
659 
660             let external_fence_info = ash::vk::PhysicalDeviceExternalFenceInfo {
661                 handle_type: handle_type.into(),
662                 ..Default::default()
663             };
664 
665             /* Output */
666 
667             let mut external_fence_properties = ash::vk::ExternalFenceProperties::default();
668 
669             /* Call */
670 
671             let fns = self.instance.fns();
672 
673             if self.instance.api_version() >= Version::V1_1 {
674                 (fns.v1_1.get_physical_device_external_fence_properties)(
675                     self.handle,
676                     &external_fence_info,
677                     &mut external_fence_properties,
678                 )
679             } else {
680                 (fns.khr_external_fence_capabilities
681                     .get_physical_device_external_fence_properties_khr)(
682                     self.handle,
683                     &external_fence_info,
684                     &mut external_fence_properties,
685                 );
686             }
687 
688             ExternalFenceProperties {
689                 exportable: external_fence_properties
690                     .external_fence_features
691                     .intersects(ash::vk::ExternalFenceFeatureFlags::EXPORTABLE),
692                 importable: external_fence_properties
693                     .external_fence_features
694                     .intersects(ash::vk::ExternalFenceFeatureFlags::IMPORTABLE),
695                 export_from_imported_handle_types: external_fence_properties
696                     .export_from_imported_handle_types
697                     .into(),
698                 compatible_handle_types: external_fence_properties.compatible_handle_types.into(),
699             }
700         })
701     }
702 
703     /// Retrieves the external handle properties supported for semaphores with a given
704     /// configuration.
705     ///
706     /// The instance API version must be at least 1.1, or the
707     /// [`khr_external_semaphore_capabilities`] extension must be enabled on the instance.
708     ///
709     /// The results of this function are cached, so that future calls with the same arguments
710     /// do not need to make a call to the Vulkan API again.
711     ///
712     /// [`khr_external_semaphore_capabilities`]: crate::instance::InstanceExtensions::khr_external_semaphore_capabilities
713     #[inline]
external_semaphore_properties( &self, info: ExternalSemaphoreInfo, ) -> Result<ExternalSemaphoreProperties, PhysicalDeviceError>714     pub fn external_semaphore_properties(
715         &self,
716         info: ExternalSemaphoreInfo,
717     ) -> Result<ExternalSemaphoreProperties, PhysicalDeviceError> {
718         self.validate_external_semaphore_properties(&info)?;
719 
720         unsafe { Ok(self.external_semaphore_properties_unchecked(info)) }
721     }
722 
validate_external_semaphore_properties( &self, info: &ExternalSemaphoreInfo, ) -> Result<(), PhysicalDeviceError>723     fn validate_external_semaphore_properties(
724         &self,
725         info: &ExternalSemaphoreInfo,
726     ) -> Result<(), PhysicalDeviceError> {
727         if !(self.instance.api_version() >= Version::V1_1
728             || self
729                 .instance
730                 .enabled_extensions()
731                 .khr_external_semaphore_capabilities)
732         {
733             return Err(PhysicalDeviceError::RequirementNotMet {
734                 required_for: "`PhysicalDevice::external_semaphore_properties`",
735                 requires_one_of: RequiresOneOf {
736                     api_version: Some(Version::V1_1),
737                     instance_extensions: &["khr_external_semaphore_capabilities"],
738                     ..Default::default()
739                 },
740             });
741         }
742 
743         let &ExternalSemaphoreInfo {
744             handle_type,
745             _ne: _,
746         } = info;
747 
748         // VUID-VkPhysicalDeviceExternalSemaphoreInfo-handleType-parameter
749         handle_type.validate_physical_device(self)?;
750 
751         Ok(())
752     }
753 
754     #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
755     #[inline]
external_semaphore_properties_unchecked( &self, info: ExternalSemaphoreInfo, ) -> ExternalSemaphoreProperties756     pub unsafe fn external_semaphore_properties_unchecked(
757         &self,
758         info: ExternalSemaphoreInfo,
759     ) -> ExternalSemaphoreProperties {
760         self.external_semaphore_properties
761             .get_or_insert(info, |info| {
762                 /* Input */
763 
764                 let &ExternalSemaphoreInfo {
765                     handle_type,
766                     _ne: _,
767                 } = info;
768 
769                 let external_semaphore_info = ash::vk::PhysicalDeviceExternalSemaphoreInfo {
770                     handle_type: handle_type.into(),
771                     ..Default::default()
772                 };
773 
774                 /* Output */
775 
776                 let mut external_semaphore_properties =
777                     ash::vk::ExternalSemaphoreProperties::default();
778 
779                 /* Call */
780 
781                 let fns = self.instance.fns();
782 
783                 if self.instance.api_version() >= Version::V1_1 {
784                     (fns.v1_1.get_physical_device_external_semaphore_properties)(
785                         self.handle,
786                         &external_semaphore_info,
787                         &mut external_semaphore_properties,
788                     )
789                 } else {
790                     (fns.khr_external_semaphore_capabilities
791                         .get_physical_device_external_semaphore_properties_khr)(
792                         self.handle,
793                         &external_semaphore_info,
794                         &mut external_semaphore_properties,
795                     );
796                 }
797 
798                 ExternalSemaphoreProperties {
799                     exportable: external_semaphore_properties
800                         .external_semaphore_features
801                         .intersects(ash::vk::ExternalSemaphoreFeatureFlags::EXPORTABLE),
802                     importable: external_semaphore_properties
803                         .external_semaphore_features
804                         .intersects(ash::vk::ExternalSemaphoreFeatureFlags::IMPORTABLE),
805                     export_from_imported_handle_types: external_semaphore_properties
806                         .export_from_imported_handle_types
807                         .into(),
808                     compatible_handle_types: external_semaphore_properties
809                         .compatible_handle_types
810                         .into(),
811                 }
812             })
813     }
814 
815     /// Retrieves the properties of a format when used by this physical device.
816     ///
817     /// The results of this function are cached, so that future calls with the same arguments
818     /// do not need to make a call to the Vulkan API again.
819     #[inline]
format_properties( &self, format: Format, ) -> Result<FormatProperties, PhysicalDeviceError>820     pub fn format_properties(
821         &self,
822         format: Format,
823     ) -> Result<FormatProperties, PhysicalDeviceError> {
824         self.validate_format_properties(format)?;
825 
826         unsafe { Ok(self.format_properties_unchecked(format)) }
827     }
828 
validate_format_properties(&self, format: Format) -> Result<(), PhysicalDeviceError>829     fn validate_format_properties(&self, format: Format) -> Result<(), PhysicalDeviceError> {
830         // VUID-vkGetPhysicalDeviceFormatProperties2-format-parameter
831         format.validate_physical_device(self)?;
832 
833         Ok(())
834     }
835 
836     #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
837     #[inline]
format_properties_unchecked(&self, format: Format) -> FormatProperties838     pub unsafe fn format_properties_unchecked(&self, format: Format) -> FormatProperties {
839         self.format_properties.get_or_insert(format, |&format| {
840             let mut format_properties2 = ash::vk::FormatProperties2::default();
841             let mut format_properties3 = if self.api_version() >= Version::V1_3
842                 || self.supported_extensions().khr_format_feature_flags2
843             {
844                 Some(ash::vk::FormatProperties3KHR::default())
845             } else {
846                 None
847             };
848 
849             if let Some(next) = format_properties3.as_mut() {
850                 next.p_next = format_properties2.p_next;
851                 format_properties2.p_next = next as *mut _ as *mut _;
852             }
853 
854             let fns = self.instance.fns();
855 
856             if self.api_version() >= Version::V1_1 {
857                 (fns.v1_1.get_physical_device_format_properties2)(
858                     self.handle,
859                     format.into(),
860                     &mut format_properties2,
861                 );
862             } else if self
863                 .instance
864                 .enabled_extensions()
865                 .khr_get_physical_device_properties2
866             {
867                 (fns.khr_get_physical_device_properties2
868                     .get_physical_device_format_properties2_khr)(
869                     self.handle,
870                     format.into(),
871                     &mut format_properties2,
872                 );
873             } else {
874                 (fns.v1_0.get_physical_device_format_properties)(
875                     self.handle(),
876                     format.into(),
877                     &mut format_properties2.format_properties,
878                 );
879             }
880 
881             match format_properties3 {
882                 Some(format_properties3) => FormatProperties {
883                     linear_tiling_features: format_properties3.linear_tiling_features.into(),
884                     optimal_tiling_features: format_properties3.optimal_tiling_features.into(),
885                     buffer_features: format_properties3.buffer_features.into(),
886                     _ne: crate::NonExhaustive(()),
887                 },
888                 None => FormatProperties {
889                     linear_tiling_features: format_properties2
890                         .format_properties
891                         .linear_tiling_features
892                         .into(),
893                     optimal_tiling_features: format_properties2
894                         .format_properties
895                         .optimal_tiling_features
896                         .into(),
897                     buffer_features: format_properties2.format_properties.buffer_features.into(),
898                     _ne: crate::NonExhaustive(()),
899                 },
900             }
901         })
902     }
903 
904     /// Returns the properties supported for images with a given image configuration.
905     ///
906     /// `Some` is returned if the configuration is supported, `None` if it is not.
907     ///
908     /// The results of this function are cached, so that future calls with the same arguments
909     /// do not need to make a call to the Vulkan API again.
910     ///
911     /// # Panics
912     ///
913     /// - Panics if `image_format_info.format` is `None`.
914     #[inline]
image_format_properties( &self, image_format_info: ImageFormatInfo, ) -> Result<Option<ImageFormatProperties>, PhysicalDeviceError>915     pub fn image_format_properties(
916         &self,
917         image_format_info: ImageFormatInfo,
918     ) -> Result<Option<ImageFormatProperties>, PhysicalDeviceError> {
919         self.validate_image_format_properties(&image_format_info)?;
920 
921         unsafe { Ok(self.image_format_properties_unchecked(image_format_info)?) }
922     }
923 
924     // FIXME: Shouldn't this be private?
validate_image_format_properties( &self, image_format_info: &ImageFormatInfo, ) -> Result<(), PhysicalDeviceError>925     pub fn validate_image_format_properties(
926         &self,
927         image_format_info: &ImageFormatInfo,
928     ) -> Result<(), PhysicalDeviceError> {
929         let &ImageFormatInfo {
930             flags: _,
931             format,
932             image_type,
933             tiling,
934             usage,
935             mut stencil_usage,
936             external_memory_handle_type,
937             image_view_type,
938             _ne: _,
939         } = image_format_info;
940 
941         let format = format.unwrap();
942         let aspects = format.aspects();
943 
944         let has_separate_stencil_usage = if stencil_usage.is_empty()
945             || !aspects.contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
946         {
947             stencil_usage = usage;
948             false
949         } else {
950             stencil_usage == usage
951         };
952 
953         // VUID-VkPhysicalDeviceImageFormatInfo2-format-parameter
954         format.validate_physical_device(self)?;
955 
956         // VUID-VkPhysicalDeviceImageFormatInfo2-imageType-parameter
957         image_type.validate_physical_device(self)?;
958 
959         // VUID-VkPhysicalDeviceImageFormatInfo2-tiling-parameter
960         tiling.validate_physical_device(self)?;
961 
962         // VUID-VkPhysicalDeviceImageFormatInfo2-usage-parameter
963         usage.validate_physical_device(self)?;
964 
965         // VUID-VkPhysicalDeviceImageFormatInfo2-usage-requiredbitmask
966         assert!(!usage.is_empty());
967 
968         if has_separate_stencil_usage {
969             if !(self.api_version() >= Version::V1_2
970                 || self.supported_extensions().ext_separate_stencil_usage)
971             {
972                 return Err(PhysicalDeviceError::RequirementNotMet {
973                     required_for: "`image_format_info.stencil_usage` is `Some` and \
974                         `image_format_info.format` has both a depth and a stencil aspect",
975                     requires_one_of: RequiresOneOf {
976                         api_version: Some(Version::V1_2),
977                         device_extensions: &["ext_separate_stencil_usage"],
978                         ..Default::default()
979                     },
980                 });
981             }
982 
983             // VUID-VkImageStencilUsageCreateInfo-stencilUsage-parameter
984             stencil_usage.validate_physical_device(self)?;
985 
986             // VUID-VkImageStencilUsageCreateInfo-usage-requiredbitmask
987             assert!(!stencil_usage.is_empty());
988         }
989 
990         if let Some(handle_type) = external_memory_handle_type {
991             if !(self.api_version() >= Version::V1_1
992                 || self
993                     .instance()
994                     .enabled_extensions()
995                     .khr_external_memory_capabilities)
996             {
997                 return Err(PhysicalDeviceError::RequirementNotMet {
998                     required_for: "`image_format_info.external_memory_handle_type` is `Some`",
999                     requires_one_of: RequiresOneOf {
1000                         api_version: Some(Version::V1_1),
1001                         instance_extensions: &["khr_external_memory_capabilities"],
1002                         ..Default::default()
1003                     },
1004                 });
1005             }
1006 
1007             // VUID-VkPhysicalDeviceExternalImageFormatInfo-handleType-parameter
1008             handle_type.validate_physical_device(self)?;
1009         }
1010 
1011         if let Some(image_view_type) = image_view_type {
1012             if !self.supported_extensions().ext_filter_cubic {
1013                 return Err(PhysicalDeviceError::RequirementNotMet {
1014                     required_for: "`image_format_info.image_view_type` is `Some`",
1015                     requires_one_of: RequiresOneOf {
1016                         device_extensions: &["ext_filter_cubic"],
1017                         ..Default::default()
1018                     },
1019                 });
1020             }
1021 
1022             // VUID-VkPhysicalDeviceImageViewImageFormatInfoEXT-imageViewType-parameter
1023             image_view_type.validate_physical_device(self)?;
1024         }
1025 
1026         // TODO:  VUID-VkPhysicalDeviceImageFormatInfo2-tiling-02313
1027         // Currently there is nothing in Vulkano for for adding a VkImageFormatListCreateInfo.
1028 
1029         Ok(())
1030     }
1031 
1032     #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
1033     #[inline]
image_format_properties_unchecked( &self, mut image_format_info: ImageFormatInfo, ) -> Result<Option<ImageFormatProperties>, VulkanError>1034     pub unsafe fn image_format_properties_unchecked(
1035         &self,
1036         mut image_format_info: ImageFormatInfo,
1037     ) -> Result<Option<ImageFormatProperties>, VulkanError> {
1038         {
1039             let ImageFormatInfo {
1040                 format,
1041                 usage,
1042                 stencil_usage,
1043                 ..
1044             } = &mut image_format_info;
1045 
1046             let aspects = format.unwrap().aspects();
1047 
1048             if stencil_usage.is_empty()
1049                 || !aspects.contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
1050             {
1051                 *stencil_usage = *usage;
1052             }
1053         }
1054 
1055         self.image_format_properties
1056             .get_or_try_insert(image_format_info, |image_format_info| {
1057                 /* Input */
1058                 let &ImageFormatInfo {
1059                     flags,
1060                     format,
1061                     image_type,
1062                     tiling,
1063                     usage,
1064                     stencil_usage,
1065                     external_memory_handle_type,
1066                     image_view_type,
1067                     _ne: _,
1068                 } = image_format_info;
1069 
1070                 let has_separate_stencil_usage = stencil_usage == usage;
1071 
1072                 let mut info2_vk = ash::vk::PhysicalDeviceImageFormatInfo2 {
1073                     format: format.unwrap().into(),
1074                     ty: image_type.into(),
1075                     tiling: tiling.into(),
1076                     usage: usage.into(),
1077                     flags: flags.into(),
1078                     ..Default::default()
1079                 };
1080                 let mut external_info_vk = None;
1081                 let mut image_view_info_vk = None;
1082                 let mut stencil_usage_info_vk = None;
1083 
1084                 if let Some(handle_type) = external_memory_handle_type {
1085                     let next =
1086                         external_info_vk.insert(ash::vk::PhysicalDeviceExternalImageFormatInfo {
1087                             handle_type: handle_type.into(),
1088                             ..Default::default()
1089                         });
1090 
1091                     next.p_next = info2_vk.p_next;
1092                     info2_vk.p_next = next as *const _ as *const _;
1093                 }
1094 
1095                 if let Some(image_view_type) = image_view_type {
1096                     let next = image_view_info_vk.insert(
1097                         ash::vk::PhysicalDeviceImageViewImageFormatInfoEXT {
1098                             image_view_type: image_view_type.into(),
1099                             ..Default::default()
1100                         },
1101                     );
1102 
1103                     next.p_next = info2_vk.p_next as *mut _;
1104                     info2_vk.p_next = next as *const _ as *const _;
1105                 }
1106 
1107                 if has_separate_stencil_usage {
1108                     let next = stencil_usage_info_vk.insert(ash::vk::ImageStencilUsageCreateInfo {
1109                         stencil_usage: stencil_usage.into(),
1110                         ..Default::default()
1111                     });
1112 
1113                     next.p_next = info2_vk.p_next as *mut _;
1114                     info2_vk.p_next = next as *const _ as *const _;
1115                 }
1116 
1117                 /* Output */
1118 
1119                 let mut properties2_vk = ash::vk::ImageFormatProperties2::default();
1120                 let mut external_properties_vk = None;
1121                 let mut filter_cubic_image_view_properties_vk = None;
1122 
1123                 if external_info_vk.is_some() {
1124                     let next = external_properties_vk
1125                         .insert(ash::vk::ExternalImageFormatProperties::default());
1126 
1127                     next.p_next = properties2_vk.p_next;
1128                     properties2_vk.p_next = next as *mut _ as *mut _;
1129                 }
1130 
1131                 if image_view_info_vk.is_some() {
1132                     let next = filter_cubic_image_view_properties_vk
1133                         .insert(ash::vk::FilterCubicImageViewImageFormatPropertiesEXT::default());
1134 
1135                     next.p_next = properties2_vk.p_next;
1136                     properties2_vk.p_next = next as *mut _ as *mut _;
1137                 }
1138 
1139                 let result = {
1140                     let fns = self.instance.fns();
1141 
1142                     if self.api_version() >= Version::V1_1 {
1143                         (fns.v1_1.get_physical_device_image_format_properties2)(
1144                             self.handle,
1145                             &info2_vk,
1146                             &mut properties2_vk,
1147                         )
1148                     } else if self
1149                         .instance
1150                         .enabled_extensions()
1151                         .khr_get_physical_device_properties2
1152                     {
1153                         (fns.khr_get_physical_device_properties2
1154                             .get_physical_device_image_format_properties2_khr)(
1155                             self.handle,
1156                             &info2_vk,
1157                             &mut properties2_vk,
1158                         )
1159                     } else {
1160                         // Can't query this, return unsupported
1161                         if !info2_vk.p_next.is_null() {
1162                             return Ok(None);
1163                         }
1164                         if let Some(ExternalMemoryHandleType::DmaBuf) = external_memory_handle_type
1165                         {
1166                             // VUID-vkGetPhysicalDeviceImageFormatProperties-tiling-02248
1167                             // VUID-VkPhysicalDeviceImageFormatInfo2-tiling-02249
1168                             return Ok(None);
1169                         }
1170 
1171                         (fns.v1_0.get_physical_device_image_format_properties)(
1172                             self.handle,
1173                             info2_vk.format,
1174                             info2_vk.ty,
1175                             info2_vk.tiling,
1176                             info2_vk.usage,
1177                             info2_vk.flags,
1178                             &mut properties2_vk.image_format_properties,
1179                         )
1180                     }
1181                     .result()
1182                     .map_err(VulkanError::from)
1183                 };
1184 
1185                 Ok(match result {
1186                     Ok(_) => Some(ImageFormatProperties {
1187                         external_memory_properties: external_properties_vk
1188                             .map(|properties| properties.external_memory_properties.into())
1189                             .unwrap_or_default(),
1190                         filter_cubic: filter_cubic_image_view_properties_vk
1191                             .map_or(false, |properties| {
1192                                 properties.filter_cubic != ash::vk::FALSE
1193                             }),
1194                         filter_cubic_minmax: filter_cubic_image_view_properties_vk
1195                             .map_or(false, |properties| {
1196                                 properties.filter_cubic_minmax != ash::vk::FALSE
1197                             }),
1198                         ..properties2_vk.image_format_properties.into()
1199                     }),
1200                     Err(VulkanError::FormatNotSupported) => None,
1201                     Err(err) => return Err(err),
1202                 })
1203             })
1204     }
1205 
1206     /// Queries whether the physical device supports presenting to QNX Screen surfaces from queues
1207     /// of the given queue family.
1208     ///
1209     /// # Safety
1210     ///
1211     /// - `window` must be a valid QNX Screen `_screen_window` handle.
qnx_screen_presentation_support<W>( &self, queue_family_index: u32, window: *const W, ) -> Result<bool, PhysicalDeviceError>1212     pub unsafe fn qnx_screen_presentation_support<W>(
1213         &self,
1214         queue_family_index: u32,
1215         window: *const W,
1216     ) -> Result<bool, PhysicalDeviceError> {
1217         self.validate_qnx_screen_presentation_support(queue_family_index, window)?;
1218 
1219         Ok(self.qnx_screen_presentation_support_unchecked(queue_family_index, window))
1220     }
1221 
validate_qnx_screen_presentation_support<W>( &self, queue_family_index: u32, _window: *const W, ) -> Result<(), PhysicalDeviceError>1222     fn validate_qnx_screen_presentation_support<W>(
1223         &self,
1224         queue_family_index: u32,
1225         _window: *const W,
1226     ) -> Result<(), PhysicalDeviceError> {
1227         if !self.instance.enabled_extensions().qnx_screen_surface {
1228             return Err(PhysicalDeviceError::RequirementNotMet {
1229                 required_for: "`PhysicalDevice::qnx_screen_presentation_support`",
1230                 requires_one_of: RequiresOneOf {
1231                     instance_extensions: &["qnx_screen_surface"],
1232                     ..Default::default()
1233                 },
1234             });
1235         }
1236 
1237         // VUID-vkGetPhysicalDeviceScreenPresentationSupportQNX-queueFamilyIndex-04743
1238         if queue_family_index >= self.queue_family_properties.len() as u32 {
1239             return Err(PhysicalDeviceError::QueueFamilyIndexOutOfRange {
1240                 queue_family_index,
1241                 queue_family_count: self.queue_family_properties.len() as u32,
1242             });
1243         }
1244 
1245         // VUID-vkGetPhysicalDeviceScreenPresentationSupportQNX-window-parameter
1246         // Can't validate, therefore unsafe
1247 
1248         Ok(())
1249     }
1250 
1251     #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
qnx_screen_presentation_support_unchecked<W>( &self, queue_family_index: u32, window: *const W, ) -> bool1252     pub unsafe fn qnx_screen_presentation_support_unchecked<W>(
1253         &self,
1254         queue_family_index: u32,
1255         window: *const W,
1256     ) -> bool {
1257         let fns = self.instance.fns();
1258         (fns.qnx_screen_surface
1259             .get_physical_device_screen_presentation_support_qnx)(
1260             self.handle,
1261             queue_family_index,
1262             window as *mut _,
1263         ) != 0
1264     }
1265 
1266     /// Returns the properties of sparse images with a given image configuration.
1267     ///
1268     /// The results of this function are cached, so that future calls with the same arguments
1269     /// do not need to make a call to the Vulkan API again.
1270     ///
1271     /// # Panics
1272     ///
1273     /// - Panics if `format_info.format` is `None`.
1274     #[inline]
sparse_image_format_properties( &self, format_info: SparseImageFormatInfo, ) -> Result<Vec<SparseImageFormatProperties>, PhysicalDeviceError>1275     pub fn sparse_image_format_properties(
1276         &self,
1277         format_info: SparseImageFormatInfo,
1278     ) -> Result<Vec<SparseImageFormatProperties>, PhysicalDeviceError> {
1279         self.validate_sparse_image_format_properties(&format_info)?;
1280 
1281         unsafe { Ok(self.sparse_image_format_properties_unchecked(format_info)) }
1282     }
1283 
validate_sparse_image_format_properties( &self, format_info: &SparseImageFormatInfo, ) -> Result<(), PhysicalDeviceError>1284     fn validate_sparse_image_format_properties(
1285         &self,
1286         format_info: &SparseImageFormatInfo,
1287     ) -> Result<(), PhysicalDeviceError> {
1288         let &SparseImageFormatInfo {
1289             format,
1290             image_type,
1291             samples,
1292             usage,
1293             tiling,
1294             _ne: _,
1295         } = format_info;
1296 
1297         let format = format.unwrap();
1298 
1299         // VUID-VkPhysicalDeviceSparseImageFormatInfo2-format-parameter
1300         format.validate_physical_device(self)?;
1301 
1302         // VUID-VkPhysicalDeviceSparseImageFormatInfo2-type-parameter
1303         image_type.validate_physical_device(self)?;
1304 
1305         // VUID-VkPhysicalDeviceSparseImageFormatInfo2-samples-parameter
1306         samples.validate_physical_device(self)?;
1307 
1308         // VUID-VkPhysicalDeviceSparseImageFormatInfo2-usage-parameter
1309         usage.validate_physical_device(self)?;
1310 
1311         // VUID-VkPhysicalDeviceSparseImageFormatInfo2-usage-requiredbitmask
1312         assert!(!usage.is_empty());
1313 
1314         // VUID-VkPhysicalDeviceSparseImageFormatInfo2-tiling-parameter
1315         tiling.validate_physical_device(self)?;
1316 
1317         // VUID-VkPhysicalDeviceSparseImageFormatInfo2-samples-01095
1318         // TODO:
1319 
1320         Ok(())
1321     }
1322 
1323     #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
1324     #[inline]
sparse_image_format_properties_unchecked( &self, format_info: SparseImageFormatInfo, ) -> Vec<SparseImageFormatProperties>1325     pub unsafe fn sparse_image_format_properties_unchecked(
1326         &self,
1327         format_info: SparseImageFormatInfo,
1328     ) -> Vec<SparseImageFormatProperties> {
1329         self.sparse_image_format_properties
1330             .get_or_insert(format_info, |format_info| {
1331                 let &SparseImageFormatInfo {
1332                     format,
1333                     image_type,
1334                     samples,
1335                     usage,
1336                     tiling,
1337                     _ne: _,
1338                 } = format_info;
1339 
1340                 let format_info2 = ash::vk::PhysicalDeviceSparseImageFormatInfo2 {
1341                     format: format.unwrap().into(),
1342                     ty: image_type.into(),
1343                     samples: samples.into(),
1344                     usage: usage.into(),
1345                     tiling: tiling.into(),
1346                     ..Default::default()
1347                 };
1348 
1349                 let fns = self.instance.fns();
1350 
1351                 if self.api_version() >= Version::V1_1
1352                     || self
1353                         .instance
1354                         .enabled_extensions()
1355                         .khr_get_physical_device_properties2
1356                 {
1357                     let mut count = 0;
1358 
1359                     if self.api_version() >= Version::V1_1 {
1360                         (fns.v1_1.get_physical_device_sparse_image_format_properties2)(
1361                             self.handle,
1362                             &format_info2,
1363                             &mut count,
1364                             ptr::null_mut(),
1365                         );
1366                     } else {
1367                         (fns.khr_get_physical_device_properties2
1368                             .get_physical_device_sparse_image_format_properties2_khr)(
1369                             self.handle,
1370                             &format_info2,
1371                             &mut count,
1372                             ptr::null_mut(),
1373                         );
1374                     }
1375 
1376                     let mut sparse_image_format_properties2 =
1377                         vec![ash::vk::SparseImageFormatProperties2::default(); count as usize];
1378 
1379                     if self.api_version() >= Version::V1_1 {
1380                         (fns.v1_1.get_physical_device_sparse_image_format_properties2)(
1381                             self.handle,
1382                             &format_info2,
1383                             &mut count,
1384                             sparse_image_format_properties2.as_mut_ptr(),
1385                         );
1386                     } else {
1387                         (fns.khr_get_physical_device_properties2
1388                             .get_physical_device_sparse_image_format_properties2_khr)(
1389                             self.handle,
1390                             &format_info2,
1391                             &mut count,
1392                             sparse_image_format_properties2.as_mut_ptr(),
1393                         );
1394                     }
1395 
1396                     sparse_image_format_properties2.set_len(count as usize);
1397 
1398                     sparse_image_format_properties2
1399                         .into_iter()
1400                         .map(
1401                             |sparse_image_format_properties2| SparseImageFormatProperties {
1402                                 aspects: sparse_image_format_properties2
1403                                     .properties
1404                                     .aspect_mask
1405                                     .into(),
1406                                 image_granularity: [
1407                                     sparse_image_format_properties2
1408                                         .properties
1409                                         .image_granularity
1410                                         .width,
1411                                     sparse_image_format_properties2
1412                                         .properties
1413                                         .image_granularity
1414                                         .height,
1415                                     sparse_image_format_properties2
1416                                         .properties
1417                                         .image_granularity
1418                                         .depth,
1419                                 ],
1420                                 flags: sparse_image_format_properties2.properties.flags.into(),
1421                             },
1422                         )
1423                         .collect()
1424                 } else {
1425                     let mut count = 0;
1426 
1427                     (fns.v1_0.get_physical_device_sparse_image_format_properties)(
1428                         self.handle,
1429                         format_info2.format,
1430                         format_info2.ty,
1431                         format_info2.samples,
1432                         format_info2.usage,
1433                         format_info2.tiling,
1434                         &mut count,
1435                         ptr::null_mut(),
1436                     );
1437 
1438                     let mut sparse_image_format_properties =
1439                         vec![ash::vk::SparseImageFormatProperties::default(); count as usize];
1440 
1441                     (fns.v1_0.get_physical_device_sparse_image_format_properties)(
1442                         self.handle,
1443                         format_info2.format,
1444                         format_info2.ty,
1445                         format_info2.samples,
1446                         format_info2.usage,
1447                         format_info2.tiling,
1448                         &mut count,
1449                         sparse_image_format_properties.as_mut_ptr(),
1450                     );
1451 
1452                     sparse_image_format_properties.set_len(count as usize);
1453 
1454                     sparse_image_format_properties
1455                         .into_iter()
1456                         .map(
1457                             |sparse_image_format_properties| SparseImageFormatProperties {
1458                                 aspects: sparse_image_format_properties.aspect_mask.into(),
1459                                 image_granularity: [
1460                                     sparse_image_format_properties.image_granularity.width,
1461                                     sparse_image_format_properties.image_granularity.height,
1462                                     sparse_image_format_properties.image_granularity.depth,
1463                                 ],
1464                                 flags: sparse_image_format_properties.flags.into(),
1465                             },
1466                         )
1467                         .collect()
1468                 }
1469             })
1470     }
1471 
1472     /// Returns the capabilities that are supported by the physical device for the given surface.
1473     ///
1474     /// The results of this function are cached, so that future calls with the same arguments
1475     /// do not need to make a call to the Vulkan API again.
1476     ///
1477     /// # Panics
1478     ///
1479     /// - Panics if the physical device and the surface don't belong to the same instance.
surface_capabilities( &self, surface: &Surface, surface_info: SurfaceInfo, ) -> Result<SurfaceCapabilities, PhysicalDeviceError>1480     pub fn surface_capabilities(
1481         &self,
1482         surface: &Surface,
1483         surface_info: SurfaceInfo,
1484     ) -> Result<SurfaceCapabilities, PhysicalDeviceError> {
1485         self.validate_surface_capabilities(surface, &surface_info)?;
1486 
1487         unsafe { Ok(self.surface_capabilities_unchecked(surface, surface_info)?) }
1488     }
1489 
validate_surface_capabilities( &self, surface: &Surface, surface_info: &SurfaceInfo, ) -> Result<(), PhysicalDeviceError>1490     fn validate_surface_capabilities(
1491         &self,
1492         surface: &Surface,
1493         surface_info: &SurfaceInfo,
1494     ) -> Result<(), PhysicalDeviceError> {
1495         if !(self
1496             .instance
1497             .enabled_extensions()
1498             .khr_get_surface_capabilities2
1499             || self.instance.enabled_extensions().khr_surface)
1500         {
1501             return Err(PhysicalDeviceError::RequirementNotMet {
1502                 required_for: "`PhysicalDevice::surface_capabilities`",
1503                 requires_one_of: RequiresOneOf {
1504                     instance_extensions: &["khr_get_surface_capabilities2", "khr_surface"],
1505                     ..Default::default()
1506                 },
1507             });
1508         }
1509 
1510         // VUID-vkGetPhysicalDeviceSurfaceCapabilities2KHR-commonparent
1511         assert_eq!(self.instance(), surface.instance());
1512 
1513         // VUID-vkGetPhysicalDeviceSurfaceCapabilities2KHR-pSurfaceInfo-06210
1514         if !(0..self.queue_family_properties.len() as u32).any(|index| unsafe {
1515             self.surface_support_unchecked(index, surface)
1516                 .unwrap_or_default()
1517         }) {
1518             return Err(PhysicalDeviceError::SurfaceNotSupported);
1519         }
1520 
1521         let &SurfaceInfo {
1522             full_screen_exclusive,
1523             win32_monitor,
1524             _ne: _,
1525         } = surface_info;
1526 
1527         if !self.supported_extensions().ext_full_screen_exclusive
1528             && full_screen_exclusive != FullScreenExclusive::Default
1529         {
1530             return Err(PhysicalDeviceError::NotSupported);
1531         }
1532 
1533         // VUID-VkPhysicalDeviceSurfaceInfo2KHR-pNext-02672
1534         if (surface.api() == SurfaceApi::Win32
1535             && full_screen_exclusive == FullScreenExclusive::ApplicationControlled)
1536             != win32_monitor.is_some()
1537         {
1538             return Err(PhysicalDeviceError::NotSupported);
1539         }
1540 
1541         Ok(())
1542     }
1543 
1544     #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
surface_capabilities_unchecked( &self, surface: &Surface, surface_info: SurfaceInfo, ) -> Result<SurfaceCapabilities, VulkanError>1545     pub unsafe fn surface_capabilities_unchecked(
1546         &self,
1547         surface: &Surface,
1548         surface_info: SurfaceInfo,
1549     ) -> Result<SurfaceCapabilities, VulkanError> {
1550         /* Input */
1551 
1552         let SurfaceInfo {
1553             full_screen_exclusive,
1554             win32_monitor,
1555             _ne: _,
1556         } = surface_info;
1557 
1558         let mut info_vk = ash::vk::PhysicalDeviceSurfaceInfo2KHR {
1559             surface: surface.handle(),
1560             ..Default::default()
1561         };
1562         let mut full_screen_exclusive_info_vk = None;
1563         let mut full_screen_exclusive_win32_info_vk = None;
1564 
1565         if self.supported_extensions().ext_full_screen_exclusive && win32_monitor.is_some() {
1566             let next =
1567                 full_screen_exclusive_info_vk.insert(ash::vk::SurfaceFullScreenExclusiveInfoEXT {
1568                     full_screen_exclusive: full_screen_exclusive.into(),
1569                     ..Default::default()
1570                 });
1571 
1572             next.p_next = info_vk.p_next as *mut _;
1573             info_vk.p_next = next as *const _ as *const _;
1574         }
1575 
1576         if let Some(win32_monitor) = win32_monitor {
1577             let next = full_screen_exclusive_win32_info_vk.insert(
1578                 ash::vk::SurfaceFullScreenExclusiveWin32InfoEXT {
1579                     hmonitor: win32_monitor.0,
1580                     ..Default::default()
1581                 },
1582             );
1583 
1584             next.p_next = info_vk.p_next as *mut _;
1585             info_vk.p_next = next as *const _ as *const _;
1586         }
1587 
1588         /* Output */
1589 
1590         let mut capabilities_vk = ash::vk::SurfaceCapabilities2KHR::default();
1591         let mut capabilities_full_screen_exclusive_vk = None;
1592         let mut protected_capabilities_vk = None;
1593 
1594         if full_screen_exclusive_info_vk.is_some() {
1595             let next = capabilities_full_screen_exclusive_vk
1596                 .insert(ash::vk::SurfaceCapabilitiesFullScreenExclusiveEXT::default());
1597 
1598             next.p_next = capabilities_vk.p_next as *mut _;
1599             capabilities_vk.p_next = next as *mut _ as *mut _;
1600         }
1601 
1602         if self
1603             .instance
1604             .enabled_extensions()
1605             .khr_surface_protected_capabilities
1606         {
1607             let next = protected_capabilities_vk
1608                 .insert(ash::vk::SurfaceProtectedCapabilitiesKHR::default());
1609 
1610             next.p_next = capabilities_vk.p_next as *mut _;
1611             capabilities_vk.p_next = next as *mut _ as *mut _;
1612         }
1613 
1614         let fns = self.instance.fns();
1615 
1616         if self
1617             .instance
1618             .enabled_extensions()
1619             .khr_get_surface_capabilities2
1620         {
1621             (fns.khr_get_surface_capabilities2
1622                 .get_physical_device_surface_capabilities2_khr)(
1623                 self.handle(),
1624                 &info_vk,
1625                 &mut capabilities_vk,
1626             )
1627             .result()
1628             .map_err(VulkanError::from)?;
1629         } else {
1630             (fns.khr_surface.get_physical_device_surface_capabilities_khr)(
1631                 self.handle(),
1632                 info_vk.surface,
1633                 &mut capabilities_vk.surface_capabilities,
1634             )
1635             .result()
1636             .map_err(VulkanError::from)?;
1637         };
1638 
1639         Ok(SurfaceCapabilities {
1640             min_image_count: capabilities_vk.surface_capabilities.min_image_count,
1641             max_image_count: if capabilities_vk.surface_capabilities.max_image_count == 0 {
1642                 None
1643             } else {
1644                 Some(capabilities_vk.surface_capabilities.max_image_count)
1645             },
1646             current_extent: if capabilities_vk.surface_capabilities.current_extent.width
1647                 == 0xffffffff
1648                 && capabilities_vk.surface_capabilities.current_extent.height == 0xffffffff
1649             {
1650                 None
1651             } else {
1652                 Some([
1653                     capabilities_vk.surface_capabilities.current_extent.width,
1654                     capabilities_vk.surface_capabilities.current_extent.height,
1655                 ])
1656             },
1657             min_image_extent: [
1658                 capabilities_vk.surface_capabilities.min_image_extent.width,
1659                 capabilities_vk.surface_capabilities.min_image_extent.height,
1660             ],
1661             max_image_extent: [
1662                 capabilities_vk.surface_capabilities.max_image_extent.width,
1663                 capabilities_vk.surface_capabilities.max_image_extent.height,
1664             ],
1665             max_image_array_layers: capabilities_vk.surface_capabilities.max_image_array_layers,
1666             supported_transforms: capabilities_vk
1667                 .surface_capabilities
1668                 .supported_transforms
1669                 .into(),
1670 
1671             current_transform: SurfaceTransforms::from(
1672                 capabilities_vk.surface_capabilities.current_transform,
1673             )
1674             .into_iter()
1675             .next()
1676             .unwrap(), // TODO:
1677             supported_composite_alpha: capabilities_vk
1678                 .surface_capabilities
1679                 .supported_composite_alpha
1680                 .into(),
1681             supported_usage_flags: {
1682                 let usage =
1683                     ImageUsage::from(capabilities_vk.surface_capabilities.supported_usage_flags);
1684                 debug_assert!(usage.intersects(ImageUsage::COLOR_ATTACHMENT)); // specs say that this must be true
1685                 usage
1686             },
1687 
1688             supports_protected: protected_capabilities_vk
1689                 .map_or(false, |c| c.supports_protected != 0),
1690 
1691             full_screen_exclusive_supported: capabilities_full_screen_exclusive_vk
1692                 .map_or(false, |c| c.full_screen_exclusive_supported != 0),
1693         })
1694     }
1695 
1696     /// Returns the combinations of format and color space that are supported by the physical device
1697     /// for the given surface.
1698     ///
1699     /// The results of this function are cached, so that future calls with the same arguments
1700     /// do not need to make a call to the Vulkan API again.
1701     ///
1702     /// # Panics
1703     ///
1704     /// - Panics if the physical device and the surface don't belong to the same instance.
surface_formats( &self, surface: &Surface, surface_info: SurfaceInfo, ) -> Result<Vec<(Format, ColorSpace)>, PhysicalDeviceError>1705     pub fn surface_formats(
1706         &self,
1707         surface: &Surface,
1708         surface_info: SurfaceInfo,
1709     ) -> Result<Vec<(Format, ColorSpace)>, PhysicalDeviceError> {
1710         self.validate_surface_formats(surface, &surface_info)?;
1711 
1712         unsafe { Ok(self.surface_formats_unchecked(surface, surface_info)?) }
1713     }
1714 
validate_surface_formats( &self, surface: &Surface, surface_info: &SurfaceInfo, ) -> Result<(), PhysicalDeviceError>1715     fn validate_surface_formats(
1716         &self,
1717         surface: &Surface,
1718         surface_info: &SurfaceInfo,
1719     ) -> Result<(), PhysicalDeviceError> {
1720         if !(self
1721             .instance
1722             .enabled_extensions()
1723             .khr_get_surface_capabilities2
1724             || self.instance.enabled_extensions().khr_surface)
1725         {
1726             return Err(PhysicalDeviceError::RequirementNotMet {
1727                 required_for: "`PhysicalDevice::surface_formats`",
1728                 requires_one_of: RequiresOneOf {
1729                     instance_extensions: &["khr_get_surface_capabilities2", "khr_surface"],
1730                     ..Default::default()
1731                 },
1732             });
1733         }
1734 
1735         // VUID-vkGetPhysicalDeviceSurfaceFormats2KHR-commonparent
1736         assert_eq!(self.instance(), surface.instance());
1737 
1738         // VUID-vkGetPhysicalDeviceSurfaceFormats2KHR-pSurfaceInfo-06522
1739         if !(0..self.queue_family_properties.len() as u32).any(|index| unsafe {
1740             self.surface_support_unchecked(index, surface)
1741                 .unwrap_or_default()
1742         }) {
1743             return Err(PhysicalDeviceError::SurfaceNotSupported);
1744         }
1745 
1746         let &SurfaceInfo {
1747             full_screen_exclusive,
1748             win32_monitor,
1749             _ne: _,
1750         } = surface_info;
1751 
1752         if self
1753             .instance
1754             .enabled_extensions()
1755             .khr_get_surface_capabilities2
1756         {
1757             if !self.supported_extensions().ext_full_screen_exclusive
1758                 && full_screen_exclusive != FullScreenExclusive::Default
1759             {
1760                 return Err(PhysicalDeviceError::NotSupported);
1761             }
1762 
1763             // VUID-VkPhysicalDeviceSurfaceInfo2KHR-pNext-02672
1764             if (surface.api() == SurfaceApi::Win32
1765                 && full_screen_exclusive == FullScreenExclusive::ApplicationControlled)
1766                 != win32_monitor.is_some()
1767             {
1768                 return Err(PhysicalDeviceError::NotSupported);
1769             }
1770         } else {
1771             if full_screen_exclusive != FullScreenExclusive::Default {
1772                 return Err(PhysicalDeviceError::NotSupported);
1773             }
1774 
1775             if win32_monitor.is_some() {
1776                 return Err(PhysicalDeviceError::NotSupported);
1777             }
1778         }
1779 
1780         Ok(())
1781     }
1782 
1783     #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
surface_formats_unchecked( &self, surface: &Surface, surface_info: SurfaceInfo, ) -> Result<Vec<(Format, ColorSpace)>, VulkanError>1784     pub unsafe fn surface_formats_unchecked(
1785         &self,
1786         surface: &Surface,
1787         surface_info: SurfaceInfo,
1788     ) -> Result<Vec<(Format, ColorSpace)>, VulkanError> {
1789         surface.surface_formats.get_or_try_insert(
1790             (self.handle, surface_info),
1791             |(_, surface_info)| {
1792                 let &SurfaceInfo {
1793                     full_screen_exclusive,
1794                     win32_monitor,
1795                     _ne: _,
1796                 } = surface_info;
1797 
1798                 let mut surface_full_screen_exclusive_info = (full_screen_exclusive
1799                     != FullScreenExclusive::Default)
1800                     .then(|| ash::vk::SurfaceFullScreenExclusiveInfoEXT {
1801                         full_screen_exclusive: full_screen_exclusive.into(),
1802                         ..Default::default()
1803                     });
1804 
1805                 let mut surface_full_screen_exclusive_win32_info =
1806                     win32_monitor.map(|win32_monitor| {
1807                         ash::vk::SurfaceFullScreenExclusiveWin32InfoEXT {
1808                             hmonitor: win32_monitor.0,
1809                             ..Default::default()
1810                         }
1811                     });
1812 
1813                 let mut surface_info2 = ash::vk::PhysicalDeviceSurfaceInfo2KHR {
1814                     surface: surface.handle(),
1815                     ..Default::default()
1816                 };
1817 
1818                 if let Some(surface_full_screen_exclusive_info) =
1819                     surface_full_screen_exclusive_info.as_mut()
1820                 {
1821                     surface_full_screen_exclusive_info.p_next = surface_info2.p_next as *mut _;
1822                     surface_info2.p_next =
1823                         surface_full_screen_exclusive_info as *const _ as *const _;
1824                 }
1825 
1826                 if let Some(surface_full_screen_exclusive_win32_info) =
1827                     surface_full_screen_exclusive_win32_info.as_mut()
1828                 {
1829                     surface_full_screen_exclusive_win32_info.p_next =
1830                         surface_info2.p_next as *mut _;
1831                     surface_info2.p_next =
1832                         surface_full_screen_exclusive_win32_info as *const _ as *const _;
1833                 }
1834 
1835                 let fns = self.instance.fns();
1836 
1837                 if self
1838                     .instance
1839                     .enabled_extensions()
1840                     .khr_get_surface_capabilities2
1841                 {
1842                     let surface_format2s = loop {
1843                         let mut count = 0;
1844                         (fns.khr_get_surface_capabilities2
1845                             .get_physical_device_surface_formats2_khr)(
1846                             self.handle(),
1847                             &surface_info2,
1848                             &mut count,
1849                             ptr::null_mut(),
1850                         )
1851                         .result()
1852                         .map_err(VulkanError::from)?;
1853 
1854                         let mut surface_format2s =
1855                             vec![ash::vk::SurfaceFormat2KHR::default(); count as usize];
1856                         let result = (fns
1857                             .khr_get_surface_capabilities2
1858                             .get_physical_device_surface_formats2_khr)(
1859                             self.handle(),
1860                             &surface_info2,
1861                             &mut count,
1862                             surface_format2s.as_mut_ptr(),
1863                         );
1864 
1865                         match result {
1866                             ash::vk::Result::SUCCESS => {
1867                                 surface_format2s.set_len(count as usize);
1868                                 break surface_format2s;
1869                             }
1870                             ash::vk::Result::INCOMPLETE => (),
1871                             err => return Err(VulkanError::from(err)),
1872                         }
1873                     };
1874 
1875                     Ok(surface_format2s
1876                         .into_iter()
1877                         .filter_map(|surface_format2| {
1878                             (surface_format2.surface_format.format.try_into().ok())
1879                                 .zip(surface_format2.surface_format.color_space.try_into().ok())
1880                         })
1881                         .collect())
1882                 } else {
1883                     let surface_formats = loop {
1884                         let mut count = 0;
1885                         (fns.khr_surface.get_physical_device_surface_formats_khr)(
1886                             self.handle(),
1887                             surface.handle(),
1888                             &mut count,
1889                             ptr::null_mut(),
1890                         )
1891                         .result()
1892                         .map_err(VulkanError::from)?;
1893 
1894                         let mut surface_formats = Vec::with_capacity(count as usize);
1895                         let result = (fns.khr_surface.get_physical_device_surface_formats_khr)(
1896                             self.handle(),
1897                             surface.handle(),
1898                             &mut count,
1899                             surface_formats.as_mut_ptr(),
1900                         );
1901 
1902                         match result {
1903                             ash::vk::Result::SUCCESS => {
1904                                 surface_formats.set_len(count as usize);
1905                                 break surface_formats;
1906                             }
1907                             ash::vk::Result::INCOMPLETE => (),
1908                             err => return Err(VulkanError::from(err)),
1909                         }
1910                     };
1911 
1912                     Ok(surface_formats
1913                         .into_iter()
1914                         .filter_map(|surface_format| {
1915                             (surface_format.format.try_into().ok())
1916                                 .zip(surface_format.color_space.try_into().ok())
1917                         })
1918                         .collect())
1919                 }
1920             },
1921         )
1922     }
1923 
1924     /// Returns the present modes that are supported by the physical device for the given surface.
1925     ///
1926     /// The results of this function are cached, so that future calls with the same arguments
1927     /// do not need to make a call to the Vulkan API again.
1928     ///
1929     /// # Panics
1930     ///
1931     /// - Panics if the physical device and the surface don't belong to the same instance.
surface_present_modes( &self, surface: &Surface, ) -> Result<impl Iterator<Item = PresentMode>, PhysicalDeviceError>1932     pub fn surface_present_modes(
1933         &self,
1934         surface: &Surface,
1935     ) -> Result<impl Iterator<Item = PresentMode>, PhysicalDeviceError> {
1936         self.validate_surface_present_modes(surface)?;
1937 
1938         unsafe { Ok(self.surface_present_modes_unchecked(surface)?) }
1939     }
1940 
validate_surface_present_modes(&self, surface: &Surface) -> Result<(), PhysicalDeviceError>1941     fn validate_surface_present_modes(&self, surface: &Surface) -> Result<(), PhysicalDeviceError> {
1942         if !self.instance.enabled_extensions().khr_surface {
1943             return Err(PhysicalDeviceError::RequirementNotMet {
1944                 required_for: "`PhysicalDevice::surface_present_modes`",
1945                 requires_one_of: RequiresOneOf {
1946                     instance_extensions: &["khr_surface"],
1947                     ..Default::default()
1948                 },
1949             });
1950         }
1951 
1952         // VUID-vkGetPhysicalDeviceSurfacePresentModesKHR-commonparent
1953         assert_eq!(self.instance(), surface.instance());
1954 
1955         // VUID-vkGetPhysicalDeviceSurfacePresentModesKHR-surface-06525
1956         if !(0..self.queue_family_properties.len() as u32).any(|index| unsafe {
1957             self.surface_support_unchecked(index, surface)
1958                 .unwrap_or_default()
1959         }) {
1960             return Err(PhysicalDeviceError::SurfaceNotSupported);
1961         }
1962 
1963         Ok(())
1964     }
1965 
1966     #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
surface_present_modes_unchecked( &self, surface: &Surface, ) -> Result<impl Iterator<Item = PresentMode>, VulkanError>1967     pub unsafe fn surface_present_modes_unchecked(
1968         &self,
1969         surface: &Surface,
1970     ) -> Result<impl Iterator<Item = PresentMode>, VulkanError> {
1971         surface
1972             .surface_present_modes
1973             .get_or_try_insert(self.handle, |_| {
1974                 let fns = self.instance.fns();
1975 
1976                 let modes = loop {
1977                     let mut count = 0;
1978                     (fns.khr_surface
1979                         .get_physical_device_surface_present_modes_khr)(
1980                         self.handle(),
1981                         surface.handle(),
1982                         &mut count,
1983                         ptr::null_mut(),
1984                     )
1985                     .result()
1986                     .map_err(VulkanError::from)?;
1987 
1988                     let mut modes = Vec::with_capacity(count as usize);
1989                     let result = (fns
1990                         .khr_surface
1991                         .get_physical_device_surface_present_modes_khr)(
1992                         self.handle(),
1993                         surface.handle(),
1994                         &mut count,
1995                         modes.as_mut_ptr(),
1996                     );
1997 
1998                     match result {
1999                         ash::vk::Result::SUCCESS => {
2000                             modes.set_len(count as usize);
2001                             break modes;
2002                         }
2003                         ash::vk::Result::INCOMPLETE => (),
2004                         err => return Err(VulkanError::from(err)),
2005                     }
2006                 };
2007 
2008                 Ok(modes
2009                     .into_iter()
2010                     .filter_map(|mode_vk| mode_vk.try_into().ok())
2011                     .collect())
2012             })
2013             .map(IntoIterator::into_iter)
2014     }
2015 
2016     /// Returns whether queues of the given queue family can draw on the given surface.
2017     ///
2018     /// The results of this function are cached, so that future calls with the same arguments
2019     /// do not need to make a call to the Vulkan API again.
2020     #[inline]
surface_support( &self, queue_family_index: u32, surface: &Surface, ) -> Result<bool, PhysicalDeviceError>2021     pub fn surface_support(
2022         &self,
2023         queue_family_index: u32,
2024         surface: &Surface,
2025     ) -> Result<bool, PhysicalDeviceError> {
2026         self.validate_surface_support(queue_family_index, surface)?;
2027 
2028         unsafe { Ok(self.surface_support_unchecked(queue_family_index, surface)?) }
2029     }
2030 
validate_surface_support( &self, queue_family_index: u32, _surface: &Surface, ) -> Result<(), PhysicalDeviceError>2031     fn validate_surface_support(
2032         &self,
2033         queue_family_index: u32,
2034         _surface: &Surface,
2035     ) -> Result<(), PhysicalDeviceError> {
2036         if !self.instance.enabled_extensions().khr_surface {
2037             return Err(PhysicalDeviceError::RequirementNotMet {
2038                 required_for: "`PhysicalDevice::surface_support`",
2039                 requires_one_of: RequiresOneOf {
2040                     instance_extensions: &["khr_surface"],
2041                     ..Default::default()
2042                 },
2043             });
2044         }
2045 
2046         // VUID-vkGetPhysicalDeviceSurfaceSupportKHR-queueFamilyIndex-01269
2047         if queue_family_index >= self.queue_family_properties.len() as u32 {
2048             return Err(PhysicalDeviceError::QueueFamilyIndexOutOfRange {
2049                 queue_family_index,
2050                 queue_family_count: self.queue_family_properties.len() as u32,
2051             });
2052         }
2053 
2054         Ok(())
2055     }
2056 
2057     #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
surface_support_unchecked( &self, queue_family_index: u32, surface: &Surface, ) -> Result<bool, VulkanError>2058     pub unsafe fn surface_support_unchecked(
2059         &self,
2060         queue_family_index: u32,
2061         surface: &Surface,
2062     ) -> Result<bool, VulkanError> {
2063         surface
2064             .surface_support
2065             .get_or_try_insert((self.handle, queue_family_index), |_| {
2066                 let fns = self.instance.fns();
2067 
2068                 let mut output = MaybeUninit::uninit();
2069                 (fns.khr_surface.get_physical_device_surface_support_khr)(
2070                     self.handle,
2071                     queue_family_index,
2072                     surface.handle(),
2073                     output.as_mut_ptr(),
2074                 )
2075                 .result()
2076                 .map_err(VulkanError::from)?;
2077 
2078                 Ok(output.assume_init() != 0)
2079             })
2080     }
2081 
2082     /// Retrieves the properties of tools that are currently active on the physical device.
2083     ///
2084     /// These properties may change during runtime, so the result only reflects the current
2085     /// situation and is not cached.
2086     ///
2087     /// The physical device API version must be at least 1.3, or the
2088     /// [`ext_tooling_info`](crate::device::DeviceExtensions::ext_tooling_info)
2089     /// extension must be supported by the physical device.
2090     #[inline]
tool_properties(&self) -> Result<Vec<ToolProperties>, PhysicalDeviceError>2091     pub fn tool_properties(&self) -> Result<Vec<ToolProperties>, PhysicalDeviceError> {
2092         self.validate_tool_properties()?;
2093 
2094         unsafe { Ok(self.tool_properties_unchecked()?) }
2095     }
2096 
validate_tool_properties(&self) -> Result<(), PhysicalDeviceError>2097     fn validate_tool_properties(&self) -> Result<(), PhysicalDeviceError> {
2098         if !(self.api_version() >= Version::V1_3 || self.supported_extensions().ext_tooling_info) {
2099             return Err(PhysicalDeviceError::RequirementNotMet {
2100                 required_for: "`PhysicalDevice::tooling_properties`",
2101                 requires_one_of: RequiresOneOf {
2102                     api_version: Some(Version::V1_3),
2103                     device_extensions: &["ext_tooling_info"],
2104                     ..Default::default()
2105                 },
2106             });
2107         }
2108 
2109         Ok(())
2110     }
2111 
2112     #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
2113     #[inline]
tool_properties_unchecked(&self) -> Result<Vec<ToolProperties>, VulkanError>2114     pub unsafe fn tool_properties_unchecked(&self) -> Result<Vec<ToolProperties>, VulkanError> {
2115         let fns = self.instance.fns();
2116 
2117         loop {
2118             let mut count = 0;
2119 
2120             if self.api_version() >= Version::V1_3 {
2121                 (fns.v1_3.get_physical_device_tool_properties)(
2122                     self.handle(),
2123                     &mut count,
2124                     ptr::null_mut(),
2125                 )
2126             } else {
2127                 (fns.ext_tooling_info.get_physical_device_tool_properties_ext)(
2128                     self.handle(),
2129                     &mut count,
2130                     ptr::null_mut(),
2131                 )
2132             }
2133             .result()
2134             .map_err(VulkanError::from)?;
2135 
2136             let mut tool_properties = Vec::with_capacity(count as usize);
2137             let result = if self.api_version() >= Version::V1_3 {
2138                 (fns.v1_3.get_physical_device_tool_properties)(
2139                     self.handle(),
2140                     &mut count,
2141                     tool_properties.as_mut_ptr(),
2142                 )
2143             } else {
2144                 (fns.ext_tooling_info.get_physical_device_tool_properties_ext)(
2145                     self.handle(),
2146                     &mut count,
2147                     tool_properties.as_mut_ptr(),
2148                 )
2149             };
2150 
2151             match result {
2152                 ash::vk::Result::INCOMPLETE => (),
2153                 ash::vk::Result::SUCCESS => {
2154                     tool_properties.set_len(count as usize);
2155 
2156                     return Ok(tool_properties
2157                         .into_iter()
2158                         .map(|tool_properties| ToolProperties {
2159                             name: {
2160                                 let bytes = cast_slice(tool_properties.name.as_slice());
2161                                 let end = bytes.iter().position(|&b| b == 0).unwrap_or(bytes.len());
2162                                 String::from_utf8_lossy(&bytes[0..end]).into()
2163                             },
2164                             version: {
2165                                 let bytes = cast_slice(tool_properties.version.as_slice());
2166                                 let end = bytes.iter().position(|&b| b == 0).unwrap_or(bytes.len());
2167                                 String::from_utf8_lossy(&bytes[0..end]).into()
2168                             },
2169                             purposes: tool_properties.purposes.into(),
2170                             description: {
2171                                 let bytes = cast_slice(tool_properties.description.as_slice());
2172                                 let end = bytes.iter().position(|&b| b == 0).unwrap_or(bytes.len());
2173                                 String::from_utf8_lossy(&bytes[0..end]).into()
2174                             },
2175                             layer: {
2176                                 let bytes = cast_slice(tool_properties.layer.as_slice());
2177                                 let end = bytes.iter().position(|&b| b == 0).unwrap_or(bytes.len());
2178                                 String::from_utf8_lossy(&bytes[0..end]).into()
2179                             },
2180                         })
2181                         .collect());
2182                 }
2183                 err => return Err(VulkanError::from(err)),
2184             }
2185         }
2186     }
2187 
2188     /// Queries whether the physical device supports presenting to Wayland surfaces from queues of
2189     /// the given queue family.
2190     ///
2191     /// # Safety
2192     ///
2193     /// - `display` must be a valid Wayland `wl_display` handle.
wayland_presentation_support<D>( &self, queue_family_index: u32, display: *const D, ) -> Result<bool, PhysicalDeviceError>2194     pub unsafe fn wayland_presentation_support<D>(
2195         &self,
2196         queue_family_index: u32,
2197         display: *const D,
2198     ) -> Result<bool, PhysicalDeviceError> {
2199         self.validate_wayland_presentation_support(queue_family_index, display)?;
2200 
2201         Ok(self.wayland_presentation_support_unchecked(queue_family_index, display))
2202     }
2203 
validate_wayland_presentation_support<D>( &self, queue_family_index: u32, _display: *const D, ) -> Result<(), PhysicalDeviceError>2204     fn validate_wayland_presentation_support<D>(
2205         &self,
2206         queue_family_index: u32,
2207         _display: *const D,
2208     ) -> Result<(), PhysicalDeviceError> {
2209         if !self.instance.enabled_extensions().khr_wayland_surface {
2210             return Err(PhysicalDeviceError::RequirementNotMet {
2211                 required_for: "`PhysicalDevice::wayland_presentation_support`",
2212                 requires_one_of: RequiresOneOf {
2213                     instance_extensions: &["khr_wayland_surface"],
2214                     ..Default::default()
2215                 },
2216             });
2217         }
2218 
2219         // VUID-vkGetPhysicalDeviceWaylandPresentationSupportKHR-queueFamilyIndex-01306
2220         if queue_family_index >= self.queue_family_properties.len() as u32 {
2221             return Err(PhysicalDeviceError::QueueFamilyIndexOutOfRange {
2222                 queue_family_index,
2223                 queue_family_count: self.queue_family_properties.len() as u32,
2224             });
2225         }
2226 
2227         // VUID-vkGetPhysicalDeviceWaylandPresentationSupportKHR-display-parameter
2228         // Can't validate, therefore unsafe
2229 
2230         Ok(())
2231     }
2232 
2233     #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
wayland_presentation_support_unchecked<D>( &self, queue_family_index: u32, display: *const D, ) -> bool2234     pub unsafe fn wayland_presentation_support_unchecked<D>(
2235         &self,
2236         queue_family_index: u32,
2237         display: *const D,
2238     ) -> bool {
2239         let fns = self.instance.fns();
2240         (fns.khr_wayland_surface
2241             .get_physical_device_wayland_presentation_support_khr)(
2242             self.handle,
2243             queue_family_index,
2244             display as *mut _,
2245         ) != 0
2246     }
2247 
2248     /// Queries whether the physical device supports presenting to Win32 surfaces from queues of the
2249     /// given queue family.
2250     #[inline]
win32_presentation_support( &self, queue_family_index: u32, ) -> Result<bool, PhysicalDeviceError>2251     pub fn win32_presentation_support(
2252         &self,
2253         queue_family_index: u32,
2254     ) -> Result<bool, PhysicalDeviceError> {
2255         self.validate_win32_presentation_support(queue_family_index)?;
2256 
2257         unsafe { Ok(self.win32_presentation_support_unchecked(queue_family_index)) }
2258     }
2259 
validate_win32_presentation_support( &self, queue_family_index: u32, ) -> Result<(), PhysicalDeviceError>2260     fn validate_win32_presentation_support(
2261         &self,
2262         queue_family_index: u32,
2263     ) -> Result<(), PhysicalDeviceError> {
2264         if !self.instance.enabled_extensions().khr_win32_surface {
2265             return Err(PhysicalDeviceError::RequirementNotMet {
2266                 required_for: "`PhysicalDevice::win32_presentation_support`",
2267                 requires_one_of: RequiresOneOf {
2268                     instance_extensions: &["khr_win32_surface"],
2269                     ..Default::default()
2270                 },
2271             });
2272         }
2273 
2274         // VUID-vkGetPhysicalDeviceWin32PresentationSupportKHR-queueFamilyIndex-01309
2275         if queue_family_index >= self.queue_family_properties.len() as u32 {
2276             return Err(PhysicalDeviceError::QueueFamilyIndexOutOfRange {
2277                 queue_family_index,
2278                 queue_family_count: self.queue_family_properties.len() as u32,
2279             });
2280         }
2281 
2282         Ok(())
2283     }
2284 
2285     #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
2286     #[inline]
win32_presentation_support_unchecked(&self, queue_family_index: u32) -> bool2287     pub unsafe fn win32_presentation_support_unchecked(&self, queue_family_index: u32) -> bool {
2288         let fns = self.instance.fns();
2289         (fns.khr_win32_surface
2290             .get_physical_device_win32_presentation_support_khr)(
2291             self.handle, queue_family_index
2292         ) != 0
2293     }
2294 
2295     /// Queries whether the physical device supports presenting to XCB surfaces from queues of the
2296     /// given queue family.
2297     ///
2298     /// # Safety
2299     ///
2300     /// - `connection` must be a valid X11 `xcb_connection_t` handle.
xcb_presentation_support<C>( &self, queue_family_index: u32, connection: *const C, visual_id: ash::vk::xcb_visualid_t, ) -> Result<bool, PhysicalDeviceError>2301     pub unsafe fn xcb_presentation_support<C>(
2302         &self,
2303         queue_family_index: u32,
2304         connection: *const C,
2305         visual_id: ash::vk::xcb_visualid_t,
2306     ) -> Result<bool, PhysicalDeviceError> {
2307         self.validate_xcb_presentation_support(queue_family_index, connection, visual_id)?;
2308 
2309         Ok(self.xcb_presentation_support_unchecked(queue_family_index, connection, visual_id))
2310     }
2311 
validate_xcb_presentation_support<C>( &self, queue_family_index: u32, _connection: *const C, _visual_id: ash::vk::xcb_visualid_t, ) -> Result<(), PhysicalDeviceError>2312     fn validate_xcb_presentation_support<C>(
2313         &self,
2314         queue_family_index: u32,
2315         _connection: *const C,
2316         _visual_id: ash::vk::xcb_visualid_t,
2317     ) -> Result<(), PhysicalDeviceError> {
2318         if !self.instance.enabled_extensions().khr_xcb_surface {
2319             return Err(PhysicalDeviceError::RequirementNotMet {
2320                 required_for: "`PhysicalDevice::xcb_presentation_support`",
2321                 requires_one_of: RequiresOneOf {
2322                     instance_extensions: &["khr_xcb_surface"],
2323                     ..Default::default()
2324                 },
2325             });
2326         }
2327 
2328         // VUID-vkGetPhysicalDeviceXcbPresentationSupportKHR-queueFamilyIndex-01312
2329         if queue_family_index >= self.queue_family_properties.len() as u32 {
2330             return Err(PhysicalDeviceError::QueueFamilyIndexOutOfRange {
2331                 queue_family_index,
2332                 queue_family_count: self.queue_family_properties.len() as u32,
2333             });
2334         }
2335 
2336         // VUID-vkGetPhysicalDeviceXcbPresentationSupportKHR-connection-parameter
2337         // Can't validate, therefore unsafe
2338 
2339         Ok(())
2340     }
2341 
2342     #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
xcb_presentation_support_unchecked<C>( &self, queue_family_index: u32, connection: *const C, visual_id: ash::vk::VisualID, ) -> bool2343     pub unsafe fn xcb_presentation_support_unchecked<C>(
2344         &self,
2345         queue_family_index: u32,
2346         connection: *const C,
2347         visual_id: ash::vk::VisualID,
2348     ) -> bool {
2349         let fns = self.instance.fns();
2350         (fns.khr_xcb_surface
2351             .get_physical_device_xcb_presentation_support_khr)(
2352             self.handle,
2353             queue_family_index,
2354             connection as *mut _,
2355             visual_id,
2356         ) != 0
2357     }
2358 
2359     /// Queries whether the physical device supports presenting to Xlib surfaces from queues of the
2360     /// given queue family.
2361     ///
2362     /// # Safety
2363     ///
2364     /// - `display` must be a valid Xlib `Display` handle.
xlib_presentation_support<D>( &self, queue_family_index: u32, display: *const D, visual_id: ash::vk::VisualID, ) -> Result<bool, PhysicalDeviceError>2365     pub unsafe fn xlib_presentation_support<D>(
2366         &self,
2367         queue_family_index: u32,
2368         display: *const D,
2369         visual_id: ash::vk::VisualID,
2370     ) -> Result<bool, PhysicalDeviceError> {
2371         self.validate_xlib_presentation_support(queue_family_index, display, visual_id)?;
2372 
2373         Ok(self.xlib_presentation_support_unchecked(queue_family_index, display, visual_id))
2374     }
2375 
validate_xlib_presentation_support<D>( &self, queue_family_index: u32, _display: *const D, _visual_id: ash::vk::VisualID, ) -> Result<(), PhysicalDeviceError>2376     fn validate_xlib_presentation_support<D>(
2377         &self,
2378         queue_family_index: u32,
2379         _display: *const D,
2380         _visual_id: ash::vk::VisualID,
2381     ) -> Result<(), PhysicalDeviceError> {
2382         if !self.instance.enabled_extensions().khr_xlib_surface {
2383             return Err(PhysicalDeviceError::RequirementNotMet {
2384                 required_for: "`PhysicalDevice::xlib_presentation_support`",
2385                 requires_one_of: RequiresOneOf {
2386                     instance_extensions: &["khr_xlib_surface"],
2387                     ..Default::default()
2388                 },
2389             });
2390         }
2391 
2392         // VUID-vkGetPhysicalDeviceXlibPresentationSupportKHR-queueFamilyIndex-01315
2393         if queue_family_index >= self.queue_family_properties.len() as u32 {
2394             return Err(PhysicalDeviceError::QueueFamilyIndexOutOfRange {
2395                 queue_family_index,
2396                 queue_family_count: self.queue_family_properties.len() as u32,
2397             });
2398         }
2399 
2400         // VUID-vkGetPhysicalDeviceXlibPresentationSupportKHR-dpy-parameter
2401         // Can't validate, therefore unsafe
2402 
2403         Ok(())
2404     }
2405 
2406     #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
xlib_presentation_support_unchecked<D>( &self, queue_family_index: u32, display: *const D, visual_id: ash::vk::VisualID, ) -> bool2407     pub unsafe fn xlib_presentation_support_unchecked<D>(
2408         &self,
2409         queue_family_index: u32,
2410         display: *const D,
2411         visual_id: ash::vk::VisualID,
2412     ) -> bool {
2413         let fns = self.instance.fns();
2414         (fns.khr_xlib_surface
2415             .get_physical_device_xlib_presentation_support_khr)(
2416             self.handle,
2417             queue_family_index,
2418             display as *mut _,
2419             visual_id,
2420         ) != 0
2421     }
2422 }
2423 
2424 unsafe impl VulkanObject for PhysicalDevice {
2425     type Handle = ash::vk::PhysicalDevice;
2426 
2427     #[inline]
handle(&self) -> Self::Handle2428     fn handle(&self) -> Self::Handle {
2429         self.handle
2430     }
2431 }
2432 
2433 impl_id_counter!(PhysicalDevice);
2434 
2435 vulkan_enum! {
2436     #[non_exhaustive]
2437 
2438     /// Type of a physical device.
2439     PhysicalDeviceType = PhysicalDeviceType(i32);
2440 
2441     /// The device is an integrated GPU.
2442     IntegratedGpu = INTEGRATED_GPU,
2443 
2444     /// The device is a discrete GPU.
2445     DiscreteGpu = DISCRETE_GPU,
2446 
2447     /// The device is a virtual GPU.
2448     VirtualGpu = VIRTUAL_GPU,
2449 
2450     /// The device is a CPU.
2451     Cpu = CPU,
2452 
2453     /// The device is something else.
2454     Other = OTHER,
2455 }
2456 
2457 impl Default for PhysicalDeviceType {
2458     #[inline]
default() -> Self2459     fn default() -> Self {
2460         PhysicalDeviceType::Other
2461     }
2462 }
2463 
2464 /// The version of the Vulkan conformance test that a driver is conformant against.
2465 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
2466 pub struct ConformanceVersion {
2467     pub major: u8,
2468     pub minor: u8,
2469     pub subminor: u8,
2470     pub patch: u8,
2471 }
2472 
2473 impl From<ash::vk::ConformanceVersion> for ConformanceVersion {
2474     #[inline]
from(val: ash::vk::ConformanceVersion) -> Self2475     fn from(val: ash::vk::ConformanceVersion) -> Self {
2476         ConformanceVersion {
2477             major: val.major,
2478             minor: val.minor,
2479             subminor: val.subminor,
2480             patch: val.patch,
2481         }
2482     }
2483 }
2484 
2485 impl Debug for ConformanceVersion {
fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError>2486     fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
2487         write!(f, "{}.{}.{}", self.major, self.minor, self.patch)
2488     }
2489 }
2490 
2491 impl Display for ConformanceVersion {
2492     #[inline]
fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError>2493     fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
2494         Debug::fmt(self, f)
2495     }
2496 }
2497 
2498 vulkan_enum! {
2499     #[non_exhaustive]
2500 
2501     /// An identifier for the driver of a physical device.
2502     DriverId = DriverId(i32);
2503 
2504     // TODO: document
2505     AMDProprietary = AMD_PROPRIETARY,
2506 
2507     // TODO: document
2508     AMDOpenSource = AMD_OPEN_SOURCE,
2509 
2510     // TODO: document
2511     MesaRADV = MESA_RADV,
2512 
2513     // TODO: document
2514     NvidiaProprietary = NVIDIA_PROPRIETARY,
2515 
2516     // TODO: document
2517     IntelProprietaryWindows = INTEL_PROPRIETARY_WINDOWS,
2518 
2519     // TODO: document
2520     IntelOpenSourceMesa = INTEL_OPEN_SOURCE_MESA,
2521 
2522     // TODO: document
2523     ImaginationProprietary = IMAGINATION_PROPRIETARY,
2524 
2525     // TODO: document
2526     QualcommProprietary = QUALCOMM_PROPRIETARY,
2527 
2528     // TODO: document
2529     ARMProprietary = ARM_PROPRIETARY,
2530 
2531     // TODO: document
2532     GoogleSwiftshader = GOOGLE_SWIFTSHADER,
2533 
2534     // TODO: document
2535     GGPProprietary = GGP_PROPRIETARY,
2536 
2537     // TODO: document
2538     BroadcomProprietary = BROADCOM_PROPRIETARY,
2539 
2540     // TODO: document
2541     MesaLLVMpipe = MESA_LLVMPIPE,
2542 
2543     // TODO: document
2544     MoltenVK = MOLTENVK,
2545 
2546     // TODO: document
2547     CoreAVIProprietary = COREAVI_PROPRIETARY,
2548 
2549     // TODO: document
2550     JuiceProprietary = JUICE_PROPRIETARY,
2551 
2552     // TODO: document
2553     VeriSiliconPropertary = VERISILICON_PROPRIETARY,
2554 
2555     // TODO: document
2556     MesaTurnip = MESA_TURNIP,
2557 
2558     // TODO: document
2559     MesaV3DV = MESA_V3DV,
2560 
2561     // TODO: document
2562     MesaPanVK = MESA_PANVK,
2563 
2564     // TODO: document
2565     SamsungProprietary = SAMSUNG_PROPRIETARY,
2566 
2567     // TODO: document
2568     MesaVenus = MESA_VENUS,
2569 
2570     // TODO: document
2571     MesaDozen = MESA_DOZEN,
2572 }
2573 
2574 /// Information provided about an active tool.
2575 #[derive(Clone, Debug)]
2576 #[non_exhaustive]
2577 pub struct ToolProperties {
2578     /// The name of the tool.
2579     pub name: String,
2580 
2581     /// The version of the tool.
2582     pub version: String,
2583 
2584     /// The purposes supported by the tool.
2585     pub purposes: ToolPurposes,
2586 
2587     /// A description of the tool.
2588     pub description: String,
2589 
2590     /// The layer implementing the tool, or empty if it is not implemented by a layer.
2591     pub layer: String,
2592 }
2593 
2594 vulkan_bitflags! {
2595     #[non_exhaustive]
2596 
2597     /// The purpose of an active tool.
2598     ToolPurposes = ToolPurposeFlags(u32);
2599 
2600     /// The tool provides validation of API usage.
2601     VALIDATION = VALIDATION,
2602 
2603     /// The tool provides profiling of API usage.
2604     PROFILING = PROFILING,
2605 
2606     /// The tool is capturing data about the application's API usage.
2607     TRACING = TRACING,
2608 
2609     /// The tool provides additional API features or extensions on top of the underlying
2610     /// implementation.
2611     ADDITIONAL_FEATURES = ADDITIONAL_FEATURES,
2612 
2613     /// The tool modifies the API features, limits or extensions presented to the application.
2614     MODIFYING_FEATURES = MODIFYING_FEATURES,
2615 
2616     /// The tool reports information to the user via a
2617     /// [`DebugUtilsMessenger`](crate::instance::debug::DebugUtilsMessenger).
2618     DEBUG_REPORTING = DEBUG_REPORTING_EXT {
2619         instance_extensions: [ext_debug_utils, ext_debug_report],
2620     },
2621 
2622     /// The tool consumes debug markers or object debug annotation, queue labels or command buffer
2623     /// labels.
2624     DEBUG_MARKERS = DEBUG_MARKERS_EXT {
2625         device_extensions: [ext_debug_marker],
2626         instance_extensions: [ext_debug_utils],
2627     },
2628 }
2629 
2630 vulkan_bitflags! {
2631     #[non_exhaustive]
2632 
2633     /// Specifies which subgroup operations are supported.
2634     SubgroupFeatures = SubgroupFeatureFlags(u32);
2635 
2636     // TODO: document
2637     BASIC = BASIC,
2638 
2639     // TODO: document
2640     VOTE = VOTE,
2641 
2642     // TODO: document
2643     ARITHMETIC = ARITHMETIC,
2644 
2645     // TODO: document
2646     BALLOT = BALLOT,
2647 
2648     // TODO: document
2649     SHUFFLE = SHUFFLE,
2650 
2651     // TODO: document
2652     SHUFFLE_RELATIVE = SHUFFLE_RELATIVE,
2653 
2654     // TODO: document
2655     CLUSTERED = CLUSTERED,
2656 
2657     // TODO: document
2658     QUAD = QUAD,
2659 
2660     // TODO: document
2661     PARTITIONED = PARTITIONED_NV {
2662         device_extensions: [nv_shader_subgroup_partitioned],
2663     },
2664 }
2665 
2666 vulkan_enum! {
2667     #[non_exhaustive]
2668 
2669     /// Specifies how the device clips single point primitives.
2670     PointClippingBehavior = PointClippingBehavior(i32);
2671 
2672     /// Points are clipped if they lie outside any clip plane, both those bounding the view volume
2673     /// and user-defined clip planes.
2674     AllClipPlanes = ALL_CLIP_PLANES,
2675 
2676     /// Points are clipped only if they lie outside a user-defined clip plane.
2677     UserClipPlanesOnly = USER_CLIP_PLANES_ONLY,
2678 }
2679 
2680 vulkan_enum! {
2681     #[non_exhaustive]
2682 
2683     /// Specifies whether, and how, shader float controls can be set independently.
2684     ShaderFloatControlsIndependence = ShaderFloatControlsIndependence(i32);
2685 
2686     // TODO: document
2687     Float32Only = TYPE_32_ONLY,
2688 
2689     // TODO: document
2690     All = ALL,
2691 
2692     // TODO: document
2693     None = NONE,
2694 }
2695 
2696 /// Specifies shader core properties.
2697 #[derive(Clone, Copy, Debug)]
2698 pub struct ShaderCoreProperties {}
2699 
2700 impl From<ash::vk::ShaderCorePropertiesFlagsAMD> for ShaderCoreProperties {
2701     #[inline]
from(_val: ash::vk::ShaderCorePropertiesFlagsAMD) -> Self2702     fn from(_val: ash::vk::ShaderCorePropertiesFlagsAMD) -> Self {
2703         Self {}
2704     }
2705 }
2706 
2707 vulkan_bitflags! {
2708     #[non_exhaustive]
2709 
2710     // TODO: document
2711     MemoryDecompressionMethods = MemoryDecompressionMethodFlagsNV(u64);
2712 
2713     // TODO: document
2714     GDEFLATE_1_0 = GDEFLATE_1_0,
2715 }
2716 
2717 vulkan_bitflags! {
2718     #[non_exhaustive]
2719 
2720     // TODO: document
2721     OpticalFlowGridSizes = OpticalFlowGridSizeFlagsNV(u32);
2722 
2723     // TODO: document
2724     SIZE_1X1 = TYPE_1X1,
2725 
2726     // TODO: document
2727     SIZE_2X2 = TYPE_2X2,
2728 
2729     // TODO: document
2730     SIZE_4X4 = TYPE_4X4,
2731 
2732     // TODO: document
2733     SIZE_8X8 = TYPE_8X8,
2734 }
2735 
2736 vulkan_enum! {
2737     #[non_exhaustive]
2738 
2739     // TODO: document
2740     PipelineRobustnessBufferBehavior = PipelineRobustnessBufferBehaviorEXT(i32);
2741 
2742     // TODO: document
2743     DeviceDefault = DEVICE_DEFAULT,
2744 
2745     // TODO: document
2746     Disabled = DISABLED,
2747 
2748     // TODO: document
2749     RobustBufferAccess = ROBUST_BUFFER_ACCESS,
2750 
2751     // TODO: document
2752     RobustBufferAccess2 = ROBUST_BUFFER_ACCESS_2,
2753 }
2754 
2755 vulkan_enum! {
2756     #[non_exhaustive]
2757 
2758     // TODO: document
2759     PipelineRobustnessImageBehavior = PipelineRobustnessImageBehaviorEXT(i32);
2760 
2761     // TODO: document
2762     DeviceDefault = DEVICE_DEFAULT,
2763 
2764     // TODO: document
2765     Disabled = DISABLED,
2766 
2767     // TODO: document
2768     RobustImageAccess = ROBUST_IMAGE_ACCESS,
2769 
2770     // TODO: document
2771     RobustImageAccess2 = ROBUST_IMAGE_ACCESS_2,
2772 }
2773 
2774 vulkan_enum! {
2775     #[non_exhaustive]
2776 
2777     // TODO: document
2778     RayTracingInvocationReorderMode = RayTracingInvocationReorderModeNV(i32);
2779 
2780     // TODO: document
2781     None = NONE,
2782 
2783     // TODO: document
2784     Reorder = REORDER,
2785 }
2786 
2787 /// Error that can happen when using a physical device.
2788 #[derive(Clone, Debug, PartialEq, Eq)]
2789 pub enum PhysicalDeviceError {
2790     VulkanError(VulkanError),
2791 
2792     RequirementNotMet {
2793         required_for: &'static str,
2794         requires_one_of: RequiresOneOf,
2795     },
2796 
2797     // The given `SurfaceInfo` values are not supported for the surface by the physical device.
2798     NotSupported,
2799 
2800     /// The provided `queue_family_index` was not less than the number of queue families in the
2801     /// physical device.
2802     QueueFamilyIndexOutOfRange {
2803         queue_family_index: u32,
2804         queue_family_count: u32,
2805     },
2806 
2807     // The provided `surface` is not supported by any of the physical device's queue families.
2808     SurfaceNotSupported,
2809 }
2810 
2811 impl Error for PhysicalDeviceError {
source(&self) -> Option<&(dyn Error + 'static)>2812     fn source(&self) -> Option<&(dyn Error + 'static)> {
2813         match self {
2814             Self::VulkanError(err) => Some(err),
2815             _ => None,
2816         }
2817     }
2818 }
2819 
2820 impl Display for PhysicalDeviceError {
fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError>2821     fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
2822         match self {
2823             Self::VulkanError(_) => write!(f, "a runtime error occurred"),
2824             Self::RequirementNotMet {
2825                 required_for,
2826                 requires_one_of,
2827             } => write!(
2828                 f,
2829                 "a requirement was not met for: {}; requires one of: {}",
2830                 required_for, requires_one_of,
2831             ),
2832             Self::NotSupported => write!(
2833                 f,
2834                 "the given `SurfaceInfo` values are not supported for the surface by the physical \
2835                 device",
2836             ),
2837             Self::QueueFamilyIndexOutOfRange {
2838                 queue_family_index,
2839                 queue_family_count,
2840             } => write!(
2841                 f,
2842                 "the provided `queue_family_index` ({}) was not less than the number of queue \
2843                 families in the physical device ({})",
2844                 queue_family_index, queue_family_count,
2845             ),
2846             Self::SurfaceNotSupported => write!(
2847                 f,
2848                 "the provided `surface` is not supported by any of the physical device's queue families",
2849             ),
2850         }
2851     }
2852 }
2853 
2854 impl From<VulkanError> for PhysicalDeviceError {
from(err: VulkanError) -> Self2855     fn from(err: VulkanError) -> Self {
2856         Self::VulkanError(err)
2857     }
2858 }
2859 
2860 impl From<RequirementNotMet> for PhysicalDeviceError {
from(err: RequirementNotMet) -> Self2861     fn from(err: RequirementNotMet) -> Self {
2862         Self::RequirementNotMet {
2863             required_for: err.required_for,
2864             requires_one_of: err.requires_one_of,
2865         }
2866     }
2867 }
2868