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