1 // Copyright (c) 2016 The vulkano developers 2 // Licensed under the Apache License, Version 2.0 3 // <LICENSE-APACHE or 4 // https://www.apache.org/licenses/LICENSE-2.0> or the MIT 5 // license <LICENSE-MIT or https://opensource.org/licenses/MIT>, 6 // at your option. All files in the project carrying such 7 // notice may not be copied, modified, or distributed except 8 // according to those terms. 9 10 //! Communication channel with a physical device. 11 //! 12 //! The `Device` is one of the most important objects of Vulkan. Creating a `Device` is required 13 //! before you can create buffers, textures, shaders, etc. 14 //! 15 //! Basic example: 16 //! 17 //! ```no_run 18 //! use vulkano::{ 19 //! device::{physical::PhysicalDevice, Device, DeviceCreateInfo, DeviceExtensions, Features, QueueCreateInfo}, 20 //! instance::{Instance, InstanceExtensions}, 21 //! Version, VulkanLibrary, 22 //! }; 23 //! 24 //! // Creating the instance. See the documentation of the `instance` module. 25 //! let library = VulkanLibrary::new() 26 //! .unwrap_or_else(|err| panic!("Couldn't load Vulkan library: {:?}", err)); 27 //! let instance = Instance::new(library, Default::default()) 28 //! .unwrap_or_else(|err| panic!("Couldn't create instance: {:?}", err)); 29 //! 30 //! // We just choose the first physical device. In a real application you would choose depending 31 //! // on the capabilities of the physical device and the user's preferences. 32 //! let physical_device = instance 33 //! .enumerate_physical_devices() 34 //! .unwrap_or_else(|err| panic!("Couldn't enumerate physical devices: {:?}", err)) 35 //! .next().expect("No physical device"); 36 //! 37 //! // Here is the device-creating code. 38 //! let device = { 39 //! let features = Features::empty(); 40 //! let extensions = DeviceExtensions::empty(); 41 //! 42 //! match Device::new( 43 //! physical_device, 44 //! DeviceCreateInfo { 45 //! enabled_extensions: extensions, 46 //! enabled_features: features, 47 //! queue_create_infos: vec![QueueCreateInfo { 48 //! queue_family_index: 0, 49 //! ..Default::default() 50 //! }], 51 //! ..Default::default() 52 //! }, 53 //! ) { 54 //! Ok(d) => d, 55 //! Err(err) => panic!("Couldn't build device: {:?}", err) 56 //! } 57 //! }; 58 //! ``` 59 //! 60 //! # Features and extensions 61 //! 62 //! Two of the parameters that you pass to `Device::new` are the list of the features and the list 63 //! of extensions to enable on the newly-created device. 64 //! 65 //! > **Note**: Device extensions are the same as instance extensions, except for the device. 66 //! > Features are similar to extensions, except that they are part of the core Vulkan 67 //! > specifications instead of being separate documents. 68 //! 69 //! Some Vulkan capabilities, such as swapchains (that allow you to render on the screen) or 70 //! geometry shaders for example, require that you enable a certain feature or extension when you 71 //! create the device. Contrary to OpenGL, you can't use the functions provided by a feature or an 72 //! extension if you didn't explicitly enable it when creating the device. 73 //! 74 //! Not all physical devices support all possible features and extensions. For example mobile 75 //! devices tend to not support geometry shaders, because their hardware is not capable of it. You 76 //! can query what is supported with respectively `PhysicalDevice::supported_features` and 77 //! `DeviceExtensions::supported_by_device`. 78 //! 79 //! > **Note**: The fact that you need to manually enable features at initialization also means 80 //! > that you don't need to worry about a capability not being supported later on in your code. 81 //! 82 //! # Queues 83 //! 84 //! Each physical device proposes one or more *queues* that are divided in *queue families*. A 85 //! queue is a thread of execution to which you can submit commands that the GPU will execute. 86 //! 87 //! > **Note**: You can think of a queue like a CPU thread. Each queue executes its commands one 88 //! > after the other, and queues run concurrently. A GPU behaves similarly to the hyper-threading 89 //! > technology, in the sense that queues will only run partially in parallel. 90 //! 91 //! The Vulkan API requires that you specify the list of queues that you are going to use at the 92 //! same time as when you create the device. This is done in vulkano by passing an iterator where 93 //! each element is a tuple containing a queue family and a number between 0.0 and 1.0 indicating 94 //! the priority of execution of the queue relative to the others. 95 //! 96 //! TODO: write better doc here 97 //! 98 //! The `Device::new` function returns the newly-created device, but also the list of queues. 99 //! 100 //! # Extended example 101 //! 102 //! TODO: write 103 104 use self::physical::PhysicalDevice; 105 pub(crate) use self::{features::FeaturesFfi, properties::PropertiesFfi}; 106 pub use self::{ 107 features::{FeatureRestriction, FeatureRestrictionError, Features}, 108 properties::Properties, 109 queue::{Queue, QueueError, QueueFamilyProperties, QueueFlags, QueueGuard}, 110 }; 111 pub use crate::{ 112 device::extensions::DeviceExtensions, 113 extensions::{ExtensionRestriction, ExtensionRestrictionError}, 114 fns::DeviceFunctions, 115 }; 116 use crate::{ 117 instance::Instance, macros::impl_id_counter, memory::ExternalMemoryHandleType, OomError, 118 RequirementNotMet, RequiresOneOf, Version, VulkanError, VulkanObject, 119 }; 120 use ash::vk::Handle; 121 use parking_lot::Mutex; 122 use smallvec::SmallVec; 123 use std::{ 124 error::Error, 125 ffi::CString, 126 fmt::{Display, Error as FmtError, Formatter}, 127 fs::File, 128 mem::MaybeUninit, 129 num::NonZeroU64, 130 ops::Deref, 131 ptr, 132 sync::{ 133 atomic::{AtomicU32, Ordering}, 134 Arc, 135 }, 136 }; 137 138 pub(crate) mod extensions; 139 pub(crate) mod features; 140 pub mod physical; 141 pub(crate) mod properties; 142 mod queue; 143 144 /// Represents a Vulkan context. 145 #[derive(Debug)] 146 pub struct Device { 147 handle: ash::vk::Device, 148 physical_device: Arc<PhysicalDevice>, 149 id: NonZeroU64, 150 151 // The highest version that is supported for this device. 152 // This is the minimum of Instance::max_api_version and PhysicalDevice::api_version. 153 api_version: Version, 154 155 fns: DeviceFunctions, 156 enabled_extensions: DeviceExtensions, 157 enabled_features: Features, 158 active_queue_family_indices: SmallVec<[u32; 2]>, 159 // This is required for validation in `memory::device_memory`, the count must only be modified 160 // in that module. 161 pub(crate) allocation_count: AtomicU32, 162 fence_pool: Mutex<Vec<ash::vk::Fence>>, 163 semaphore_pool: Mutex<Vec<ash::vk::Semaphore>>, 164 event_pool: Mutex<Vec<ash::vk::Event>>, 165 } 166 167 impl Device { 168 /// Creates a new `Device`. 169 /// 170 /// # Panics 171 /// 172 /// - Panics if `create_info.queues` is empty. 173 /// - Panics if one of the queue families in `create_info.queues` doesn't belong to the given 174 /// physical device. 175 /// - Panics if `create_info.queues` contains multiple elements for the same queue family. 176 /// - Panics if `create_info.queues` contains an element where `queues` is empty. 177 /// - Panics if `create_info.queues` contains an element where `queues` contains a value that is 178 /// not between 0.0 and 1.0 inclusive. new( physical_device: Arc<PhysicalDevice>, create_info: DeviceCreateInfo, ) -> Result<(Arc<Device>, impl ExactSizeIterator<Item = Arc<Queue>>), DeviceCreationError>179 pub fn new( 180 physical_device: Arc<PhysicalDevice>, 181 create_info: DeviceCreateInfo, 182 ) -> Result<(Arc<Device>, impl ExactSizeIterator<Item = Arc<Queue>>), DeviceCreationError> { 183 let DeviceCreateInfo { 184 mut enabled_extensions, 185 mut enabled_features, 186 queue_create_infos, 187 _ne: _, 188 } = create_info; 189 190 let instance = physical_device.instance(); 191 let fns_i = instance.fns(); 192 let api_version = physical_device.api_version(); 193 194 /* 195 Queues 196 */ 197 198 struct QueueToGet { 199 queue_family_index: u32, 200 id: u32, 201 } 202 203 // VUID-VkDeviceCreateInfo-queueCreateInfoCount-arraylength 204 assert!(!queue_create_infos.is_empty()); 205 206 let mut queue_create_infos_vk: SmallVec<[_; 2]> = 207 SmallVec::with_capacity(queue_create_infos.len()); 208 let mut active_queue_family_indices: SmallVec<[_; 2]> = 209 SmallVec::with_capacity(queue_create_infos.len()); 210 let mut queues_to_get: SmallVec<[_; 2]> = SmallVec::with_capacity(queue_create_infos.len()); 211 212 for queue_create_info in &queue_create_infos { 213 let &QueueCreateInfo { 214 queue_family_index, 215 ref queues, 216 _ne: _, 217 } = queue_create_info; 218 219 // VUID-VkDeviceQueueCreateInfo-queueFamilyIndex-00381 220 // TODO: return error instead of panicking? 221 let queue_family_properties = 222 &physical_device.queue_family_properties()[queue_family_index as usize]; 223 224 // VUID-VkDeviceCreateInfo-queueFamilyIndex-02802 225 assert!( 226 queue_create_infos 227 .iter() 228 .filter(|qc2| qc2.queue_family_index == queue_family_index) 229 .count() 230 == 1 231 ); 232 233 // VUID-VkDeviceQueueCreateInfo-queueCount-arraylength 234 assert!(!queues.is_empty()); 235 236 // VUID-VkDeviceQueueCreateInfo-pQueuePriorities-00383 237 assert!(queues 238 .iter() 239 .all(|&priority| (0.0..=1.0).contains(&priority))); 240 241 if queues.len() > queue_family_properties.queue_count as usize { 242 return Err(DeviceCreationError::TooManyQueuesForFamily); 243 } 244 245 queue_create_infos_vk.push(ash::vk::DeviceQueueCreateInfo { 246 flags: ash::vk::DeviceQueueCreateFlags::empty(), 247 queue_family_index, 248 queue_count: queues.len() as u32, 249 p_queue_priorities: queues.as_ptr(), // borrows from queue_create 250 ..Default::default() 251 }); 252 active_queue_family_indices.push(queue_family_index); 253 queues_to_get.extend((0..queues.len() as u32).map(move |id| QueueToGet { 254 queue_family_index, 255 id, 256 })); 257 } 258 259 active_queue_family_indices.sort_unstable(); 260 active_queue_family_indices.dedup(); 261 let supported_extensions = physical_device.supported_extensions(); 262 263 if supported_extensions.khr_portability_subset { 264 enabled_extensions.khr_portability_subset = true; 265 } 266 267 /* 268 Extensions 269 */ 270 271 // VUID-VkDeviceCreateInfo-ppEnabledExtensionNames-01840 272 // VUID-VkDeviceCreateInfo-ppEnabledExtensionNames-03328 273 // VUID-VkDeviceCreateInfo-pProperties-04451 274 enabled_extensions.check_requirements( 275 supported_extensions, 276 api_version, 277 instance.enabled_extensions(), 278 )?; 279 280 let enabled_extensions_strings = Vec::<CString>::from(&enabled_extensions); 281 let enabled_extensions_ptrs = enabled_extensions_strings 282 .iter() 283 .map(|extension| extension.as_ptr()) 284 .collect::<SmallVec<[_; 16]>>(); 285 286 /* 287 Features 288 */ 289 290 // TODO: The plan regarding `robust_buffer_access` is to check the shaders' code to see 291 // if they can possibly perform out-of-bounds reads and writes. If the user tries 292 // to use a shader that can perform out-of-bounds operations without having 293 // `robust_buffer_access` enabled, an error is returned. 294 // 295 // However for the moment this verification isn't performed. In order to be safe, 296 // we always enable the `robust_buffer_access` feature as it is guaranteed to be 297 // supported everywhere. 298 // 299 // The only alternative (while waiting for shaders introspection to work) is to 300 // make all shaders depend on `robust_buffer_access`. But since usually the 301 // majority of shaders don't need this feature, it would be very annoying to have 302 // to enable it manually when you don't need it. 303 // 304 // Note that if we ever remove this, don't forget to adjust the change in 305 // `Device`'s construction below. 306 enabled_features.robust_buffer_access = true; 307 308 // VUID-VkDeviceCreateInfo-pNext-04748 309 // VUID-VkDeviceCreateInfo-ppEnabledExtensionNames-04476 310 // VUID-VkDeviceCreateInfo-ppEnabledExtensionNames-02831 311 // VUID-VkDeviceCreateInfo-ppEnabledExtensionNames-02832 312 // VUID-VkDeviceCreateInfo-ppEnabledExtensionNames-02833 313 // VUID-VkDeviceCreateInfo-ppEnabledExtensionNames-02834 314 // VUID-VkDeviceCreateInfo-ppEnabledExtensionNames-02835 315 // VUID-VkDeviceCreateInfo-shadingRateImage-04478 316 // VUID-VkDeviceCreateInfo-shadingRateImage-04479 317 // VUID-VkDeviceCreateInfo-shadingRateImage-04480 318 // VUID-VkDeviceCreateInfo-fragmentDensityMap-04481 319 // VUID-VkDeviceCreateInfo-fragmentDensityMap-04482 320 // VUID-VkDeviceCreateInfo-fragmentDensityMap-04483 321 // VUID-VkDeviceCreateInfo-None-04896 322 // VUID-VkDeviceCreateInfo-None-04897 323 // VUID-VkDeviceCreateInfo-None-04898 324 // VUID-VkDeviceCreateInfo-sparseImageFloat32AtomicMinMax-04975 325 enabled_features.check_requirements( 326 physical_device.supported_features(), 327 api_version, 328 &enabled_extensions, 329 )?; 330 331 // VUID-VkDeviceCreateInfo-pNext-02829 332 // VUID-VkDeviceCreateInfo-pNext-02830 333 // VUID-VkDeviceCreateInfo-pNext-06532 334 let mut features_ffi = FeaturesFfi::default(); 335 features_ffi.make_chain( 336 api_version, 337 &enabled_extensions, 338 instance.enabled_extensions(), 339 ); 340 features_ffi.write(&enabled_features); 341 342 // Device layers were deprecated in Vulkan 1.0.13, and device layer requests should be 343 // ignored by the driver. For backwards compatibility, the spec recommends passing the 344 // exact instance layers to the device as well. There's no need to support separate 345 // requests at device creation time for legacy drivers: the spec claims that "[at] the 346 // time of deprecation there were no known device-only layers." 347 // 348 // Because there's no way to query the list of layers enabled for an instance, we need 349 // to save it alongside the instance. (`vkEnumerateDeviceLayerProperties` should get 350 // the right list post-1.0.13, but not pre-1.0.13, so we can't use it here.) 351 let enabled_layers_cstr: Vec<CString> = instance 352 .enabled_layers() 353 .iter() 354 .map(|name| CString::new(name.clone()).unwrap()) 355 .collect(); 356 let enabled_layers_ptrs = enabled_layers_cstr 357 .iter() 358 .map(|layer| layer.as_ptr()) 359 .collect::<SmallVec<[_; 2]>>(); 360 361 /* 362 Create the device 363 */ 364 365 let has_khr_get_physical_device_properties2 = instance 366 .enabled_extensions() 367 .khr_get_physical_device_properties2; 368 369 let mut create_info = ash::vk::DeviceCreateInfo { 370 flags: ash::vk::DeviceCreateFlags::empty(), 371 queue_create_info_count: queue_create_infos_vk.len() as u32, 372 p_queue_create_infos: queue_create_infos_vk.as_ptr(), 373 enabled_layer_count: enabled_layers_ptrs.len() as u32, 374 pp_enabled_layer_names: enabled_layers_ptrs.as_ptr(), 375 enabled_extension_count: enabled_extensions_ptrs.len() as u32, 376 pp_enabled_extension_names: enabled_extensions_ptrs.as_ptr(), 377 p_enabled_features: ptr::null(), 378 ..Default::default() 379 }; 380 381 // VUID-VkDeviceCreateInfo-pNext-00373 382 if has_khr_get_physical_device_properties2 { 383 create_info.p_next = features_ffi.head_as_ref() as *const _ as _; 384 } else { 385 create_info.p_enabled_features = &features_ffi.head_as_ref().features; 386 } 387 388 let handle = unsafe { 389 let mut output = MaybeUninit::uninit(); 390 (fns_i.v1_0.create_device)( 391 physical_device.handle(), 392 &create_info, 393 ptr::null(), 394 output.as_mut_ptr(), 395 ) 396 .result() 397 .map_err(VulkanError::from)?; 398 output.assume_init() 399 }; 400 401 // loading the function pointers of the newly-created device 402 let fns = DeviceFunctions::load(|name| unsafe { 403 (fns_i.v1_0.get_device_proc_addr)(handle, name.as_ptr()) 404 .map_or(ptr::null(), |func| func as _) 405 }); 406 407 let device = Arc::new(Device { 408 handle, 409 physical_device, 410 id: Self::next_id(), 411 api_version, 412 fns, 413 enabled_extensions, 414 enabled_features, 415 active_queue_family_indices, 416 allocation_count: AtomicU32::new(0), 417 fence_pool: Mutex::new(Vec::new()), 418 semaphore_pool: Mutex::new(Vec::new()), 419 event_pool: Mutex::new(Vec::new()), 420 }); 421 422 // Iterator to return the queues 423 let queues_iter = { 424 let device = device.clone(); 425 queues_to_get.into_iter().map( 426 move |QueueToGet { 427 queue_family_index, 428 id, 429 }| unsafe { 430 let fns = device.fns(); 431 let mut output = MaybeUninit::uninit(); 432 (fns.v1_0.get_device_queue)( 433 handle, 434 queue_family_index, 435 id, 436 output.as_mut_ptr(), 437 ); 438 439 Queue::from_handle(device.clone(), output.assume_init(), queue_family_index, id) 440 }, 441 ) 442 }; 443 444 Ok((device, queues_iter)) 445 } 446 447 /// Returns the Vulkan version supported by the device. 448 /// 449 /// This is the lower of the 450 /// [physical device's supported version](crate::device::physical::PhysicalDevice::api_version) 451 /// and the instance's [`max_api_version`](crate::instance::Instance::max_api_version). 452 #[inline] api_version(&self) -> Version453 pub fn api_version(&self) -> Version { 454 self.api_version 455 } 456 457 /// Returns pointers to the raw Vulkan functions of the device. 458 #[inline] fns(&self) -> &DeviceFunctions459 pub fn fns(&self) -> &DeviceFunctions { 460 &self.fns 461 } 462 463 /// Returns the physical device that was used to create this device. 464 #[inline] physical_device(&self) -> &Arc<PhysicalDevice>465 pub fn physical_device(&self) -> &Arc<PhysicalDevice> { 466 &self.physical_device 467 } 468 469 /// Returns the instance used to create this device. 470 #[inline] instance(&self) -> &Arc<Instance>471 pub fn instance(&self) -> &Arc<Instance> { 472 self.physical_device.instance() 473 } 474 475 /// Returns the queue family indices that this device uses. 476 #[inline] active_queue_family_indices(&self) -> &[u32]477 pub fn active_queue_family_indices(&self) -> &[u32] { 478 &self.active_queue_family_indices 479 } 480 481 /// Returns the extensions that have been enabled on the device. 482 #[inline] enabled_extensions(&self) -> &DeviceExtensions483 pub fn enabled_extensions(&self) -> &DeviceExtensions { 484 &self.enabled_extensions 485 } 486 487 /// Returns the features that have been enabled on the device. 488 #[inline] enabled_features(&self) -> &Features489 pub fn enabled_features(&self) -> &Features { 490 &self.enabled_features 491 } 492 493 /// Returns the current number of active [`DeviceMemory`] allocations the device has. 494 /// 495 /// [`DeviceMemory`]: crate::memory::DeviceMemory 496 #[inline] allocation_count(&self) -> u32497 pub fn allocation_count(&self) -> u32 { 498 self.allocation_count.load(Ordering::Acquire) 499 } 500 fence_pool(&self) -> &Mutex<Vec<ash::vk::Fence>>501 pub(crate) fn fence_pool(&self) -> &Mutex<Vec<ash::vk::Fence>> { 502 &self.fence_pool 503 } 504 semaphore_pool(&self) -> &Mutex<Vec<ash::vk::Semaphore>>505 pub(crate) fn semaphore_pool(&self) -> &Mutex<Vec<ash::vk::Semaphore>> { 506 &self.semaphore_pool 507 } 508 event_pool(&self) -> &Mutex<Vec<ash::vk::Event>>509 pub(crate) fn event_pool(&self) -> &Mutex<Vec<ash::vk::Event>> { 510 &self.event_pool 511 } 512 513 /// Retrieves the properties of an external file descriptor when imported as a given external 514 /// handle type. 515 /// 516 /// An error will be returned if the 517 /// [`khr_external_memory_fd`](DeviceExtensions::khr_external_memory_fd) extension was not 518 /// enabled on the device, or if `handle_type` is [`ExternalMemoryHandleType::OpaqueFd`]. 519 /// 520 /// # Safety 521 /// 522 /// - `file` must be a handle to external memory that was created outside the Vulkan API. 523 #[cfg_attr(not(unix), allow(unused_variables))] 524 #[inline] memory_fd_properties( &self, handle_type: ExternalMemoryHandleType, file: File, ) -> Result<MemoryFdProperties, MemoryFdPropertiesError>525 pub unsafe fn memory_fd_properties( 526 &self, 527 handle_type: ExternalMemoryHandleType, 528 file: File, 529 ) -> Result<MemoryFdProperties, MemoryFdPropertiesError> { 530 if !self.enabled_extensions().khr_external_memory_fd { 531 return Err(MemoryFdPropertiesError::NotSupported); 532 } 533 534 #[cfg(not(unix))] 535 unreachable!("`khr_external_memory_fd` was somehow enabled on a non-Unix system"); 536 537 #[cfg(unix)] 538 { 539 use std::os::unix::io::IntoRawFd; 540 541 // VUID-vkGetMemoryFdPropertiesKHR-handleType-parameter 542 handle_type.validate_device(self)?; 543 544 // VUID-vkGetMemoryFdPropertiesKHR-handleType-00674 545 if handle_type == ExternalMemoryHandleType::OpaqueFd { 546 return Err(MemoryFdPropertiesError::InvalidExternalHandleType); 547 } 548 549 let mut memory_fd_properties = ash::vk::MemoryFdPropertiesKHR::default(); 550 551 let fns = self.fns(); 552 (fns.khr_external_memory_fd.get_memory_fd_properties_khr)( 553 self.handle, 554 handle_type.into(), 555 file.into_raw_fd(), 556 &mut memory_fd_properties, 557 ) 558 .result() 559 .map_err(VulkanError::from)?; 560 561 Ok(MemoryFdProperties { 562 memory_type_bits: memory_fd_properties.memory_type_bits, 563 }) 564 } 565 } 566 567 /// Assigns a human-readable name to `object` for debugging purposes. 568 /// 569 /// If `object_name` is `None`, a previously set object name is removed. 570 /// 571 /// # Panics 572 /// - If `object` is not owned by this device. set_debug_utils_object_name<T: VulkanObject + DeviceOwned>( &self, object: &T, object_name: Option<&str>, ) -> Result<(), OomError>573 pub fn set_debug_utils_object_name<T: VulkanObject + DeviceOwned>( 574 &self, 575 object: &T, 576 object_name: Option<&str>, 577 ) -> Result<(), OomError> { 578 assert!(object.device().handle() == self.handle()); 579 580 let object_name_vk = object_name.map(|object_name| CString::new(object_name).unwrap()); 581 let info = ash::vk::DebugUtilsObjectNameInfoEXT { 582 object_type: T::Handle::TYPE, 583 object_handle: object.handle().as_raw(), 584 p_object_name: object_name_vk.map_or(ptr::null(), |object_name| object_name.as_ptr()), 585 ..Default::default() 586 }; 587 588 unsafe { 589 let fns = self.instance().fns(); 590 (fns.ext_debug_utils.set_debug_utils_object_name_ext)(self.handle, &info) 591 .result() 592 .map_err(VulkanError::from)?; 593 } 594 595 Ok(()) 596 } 597 598 /// Waits until all work on this device has finished. You should never need to call 599 /// this function, but it can be useful for debugging or benchmarking purposes. 600 /// 601 /// > **Note**: This is the Vulkan equivalent of OpenGL's `glFinish`. 602 /// 603 /// # Safety 604 /// 605 /// This function is not thread-safe. You must not submit anything to any of the queue 606 /// of the device (either explicitly or implicitly, for example with a future's destructor) 607 /// while this function is waiting. 608 #[inline] wait_idle(&self) -> Result<(), OomError>609 pub unsafe fn wait_idle(&self) -> Result<(), OomError> { 610 let fns = self.fns(); 611 (fns.v1_0.device_wait_idle)(self.handle) 612 .result() 613 .map_err(VulkanError::from)?; 614 615 Ok(()) 616 } 617 } 618 619 impl Drop for Device { 620 #[inline] drop(&mut self)621 fn drop(&mut self) { 622 let fns = self.fns(); 623 624 unsafe { 625 for &raw_fence in self.fence_pool.lock().iter() { 626 (fns.v1_0.destroy_fence)(self.handle, raw_fence, ptr::null()); 627 } 628 for &raw_sem in self.semaphore_pool.lock().iter() { 629 (fns.v1_0.destroy_semaphore)(self.handle, raw_sem, ptr::null()); 630 } 631 for &raw_event in self.event_pool.lock().iter() { 632 (fns.v1_0.destroy_event)(self.handle, raw_event, ptr::null()); 633 } 634 (fns.v1_0.destroy_device)(self.handle, ptr::null()); 635 } 636 } 637 } 638 639 unsafe impl VulkanObject for Device { 640 type Handle = ash::vk::Device; 641 642 #[inline] handle(&self) -> Self::Handle643 fn handle(&self) -> Self::Handle { 644 self.handle 645 } 646 } 647 648 impl_id_counter!(Device); 649 650 /// Error that can be returned when creating a device. 651 #[derive(Copy, Clone, Debug)] 652 pub enum DeviceCreationError { 653 /// Failed to create the device for an implementation-specific reason. 654 InitializationFailed, 655 /// You have reached the limit to the number of devices that can be created from the same 656 /// physical device. 657 TooManyObjects, 658 /// Failed to connect to the device. 659 DeviceLost, 660 /// Some of the requested features are unsupported by the physical device. 661 FeatureNotPresent, 662 /// Some of the requested device extensions are not supported by the physical device. 663 ExtensionNotPresent, 664 /// Tried to create too many queues for a given family. 665 TooManyQueuesForFamily, 666 /// The priority of one of the queues is out of the [0.0; 1.0] range. 667 PriorityOutOfRange, 668 /// There is no memory available on the host (ie. the CPU, RAM, etc.). 669 OutOfHostMemory, 670 /// There is no memory available on the device (ie. video memory). 671 OutOfDeviceMemory, 672 /// A restriction for an extension was not met. 673 ExtensionRestrictionNotMet(ExtensionRestrictionError), 674 /// A restriction for a feature was not met. 675 FeatureRestrictionNotMet(FeatureRestrictionError), 676 } 677 678 impl Error for DeviceCreationError {} 679 680 impl Display for DeviceCreationError { fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError>681 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { 682 match self { 683 Self::InitializationFailed => write!( 684 f, 685 "failed to create the device for an implementation-specific reason", 686 ), 687 Self::OutOfHostMemory => write!(f, "no memory available on the host"), 688 Self::OutOfDeviceMemory => { 689 write!(f, "no memory available on the graphical device") 690 } 691 Self::DeviceLost => write!(f, "failed to connect to the device"), 692 Self::TooManyQueuesForFamily => { 693 write!(f, "tried to create too many queues for a given family") 694 } 695 Self::FeatureNotPresent => write!( 696 f, 697 "some of the requested features are unsupported by the physical device", 698 ), 699 Self::PriorityOutOfRange => write!( 700 f, 701 "the priority of one of the queues is out of the [0.0; 1.0] range", 702 ), 703 Self::ExtensionNotPresent => write!( 704 f, 705 "some of the requested device extensions are not supported by the physical device", 706 ), 707 Self::TooManyObjects => write!( 708 f, 709 "you have reached the limit to the number of devices that can be created from the \ 710 same physical device", 711 ), 712 Self::ExtensionRestrictionNotMet(err) => err.fmt(f), 713 Self::FeatureRestrictionNotMet(err) => err.fmt(f), 714 } 715 } 716 } 717 718 impl From<VulkanError> for DeviceCreationError { from(err: VulkanError) -> Self719 fn from(err: VulkanError) -> Self { 720 match err { 721 VulkanError::InitializationFailed => Self::InitializationFailed, 722 VulkanError::OutOfHostMemory => Self::OutOfHostMemory, 723 VulkanError::OutOfDeviceMemory => Self::OutOfDeviceMemory, 724 VulkanError::DeviceLost => Self::DeviceLost, 725 VulkanError::ExtensionNotPresent => Self::ExtensionNotPresent, 726 VulkanError::FeatureNotPresent => Self::FeatureNotPresent, 727 VulkanError::TooManyObjects => Self::TooManyObjects, 728 _ => panic!("Unexpected error value"), 729 } 730 } 731 } 732 733 impl From<ExtensionRestrictionError> for DeviceCreationError { from(err: ExtensionRestrictionError) -> Self734 fn from(err: ExtensionRestrictionError) -> Self { 735 Self::ExtensionRestrictionNotMet(err) 736 } 737 } 738 739 impl From<FeatureRestrictionError> for DeviceCreationError { from(err: FeatureRestrictionError) -> Self740 fn from(err: FeatureRestrictionError) -> Self { 741 Self::FeatureRestrictionNotMet(err) 742 } 743 } 744 745 /// Parameters to create a new `Device`. 746 #[derive(Clone, Debug)] 747 pub struct DeviceCreateInfo { 748 /// The extensions to enable on the device. 749 /// 750 /// If the [`khr_portability_subset`](DeviceExtensions::khr_portability_subset) extension is 751 /// available, it will be enabled automatically, so you do not have to do this yourself. 752 /// You are responsible for ensuring that your program can work correctly on such devices. 753 /// See [the documentation of the `instance` module](crate::instance#portability-subset-devices-and-the-enumerate_portability-flag) 754 /// for more information. 755 /// 756 /// The default value is [`DeviceExtensions::empty()`]. 757 pub enabled_extensions: DeviceExtensions, 758 759 /// The features to enable on the device. 760 /// 761 /// The default value is [`Features::empty()`]. 762 pub enabled_features: Features, 763 764 /// The queues to create for the device. 765 /// 766 /// The default value is empty, which must be overridden. 767 pub queue_create_infos: Vec<QueueCreateInfo>, 768 769 pub _ne: crate::NonExhaustive, 770 } 771 772 impl Default for DeviceCreateInfo { 773 #[inline] default() -> Self774 fn default() -> Self { 775 Self { 776 enabled_extensions: DeviceExtensions::empty(), 777 enabled_features: Features::empty(), 778 queue_create_infos: Vec::new(), 779 _ne: crate::NonExhaustive(()), 780 } 781 } 782 } 783 784 /// Parameters to create queues in a new `Device`. 785 #[derive(Clone, Debug)] 786 pub struct QueueCreateInfo { 787 /// The index of the queue family to create queues for. 788 /// 789 /// The default value is `0`. 790 pub queue_family_index: u32, 791 792 /// The queues to create for the given queue family, each with a relative priority. 793 /// 794 /// The relative priority value is an arbitrary number between 0.0 and 1.0. Giving a queue a 795 /// higher priority is a hint to the driver that the queue should be given more processing time. 796 /// As this is only a hint, different drivers may handle this value differently and there are no 797 /// guarantees about its behavior. 798 /// 799 /// The default value is a single queue with a priority of 0.5. 800 pub queues: Vec<f32>, 801 802 pub _ne: crate::NonExhaustive, 803 } 804 805 impl Default for QueueCreateInfo { 806 #[inline] default() -> Self807 fn default() -> Self { 808 Self { 809 queue_family_index: 0, 810 queues: vec![0.5], 811 _ne: crate::NonExhaustive(()), 812 } 813 } 814 } 815 816 /// Implemented on objects that belong to a Vulkan device. 817 /// 818 /// # Safety 819 /// 820 /// - `device()` must return the correct device. 821 pub unsafe trait DeviceOwned { 822 /// Returns the device that owns `Self`. device(&self) -> &Arc<Device>823 fn device(&self) -> &Arc<Device>; 824 } 825 826 unsafe impl<T> DeviceOwned for T 827 where 828 T: Deref, 829 T::Target: DeviceOwned, 830 { device(&self) -> &Arc<Device>831 fn device(&self) -> &Arc<Device> { 832 (**self).device() 833 } 834 } 835 836 /// The properties of a Unix file descriptor when it is imported. 837 #[derive(Clone, Debug)] 838 #[non_exhaustive] 839 pub struct MemoryFdProperties { 840 /// A bitmask of the indices of memory types that can be used with the file. 841 pub memory_type_bits: u32, 842 } 843 844 /// Error that can happen when calling `memory_fd_properties`. 845 #[derive(Clone, Copy, Debug, PartialEq, Eq)] 846 pub enum MemoryFdPropertiesError { 847 /// No memory available on the host. 848 OutOfHostMemory, 849 850 RequirementNotMet { 851 required_for: &'static str, 852 requires_one_of: RequiresOneOf, 853 }, 854 855 /// The provided external handle was not valid. 856 InvalidExternalHandle, 857 858 /// The provided external handle type was not valid. 859 InvalidExternalHandleType, 860 861 /// The `khr_external_memory_fd` extension was not enabled on the device. 862 NotSupported, 863 } 864 865 impl Error for MemoryFdPropertiesError {} 866 867 impl Display for MemoryFdPropertiesError { fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError>868 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { 869 match self { 870 Self::OutOfHostMemory => write!(f, "no memory available on the host"), 871 Self::RequirementNotMet { 872 required_for, 873 requires_one_of, 874 } => write!( 875 f, 876 "a requirement was not met for: {}; requires one of: {}", 877 required_for, requires_one_of, 878 ), 879 Self::InvalidExternalHandle => { 880 write!(f, "the provided external handle was not valid") 881 } 882 Self::InvalidExternalHandleType => { 883 write!(f, "the provided external handle type was not valid") 884 } 885 Self::NotSupported => write!( 886 f, 887 "the `khr_external_memory_fd` extension was not enabled on the device", 888 ), 889 } 890 } 891 } 892 893 impl From<VulkanError> for MemoryFdPropertiesError { from(err: VulkanError) -> Self894 fn from(err: VulkanError) -> Self { 895 match err { 896 VulkanError::OutOfHostMemory => Self::OutOfHostMemory, 897 VulkanError::InvalidExternalHandle => Self::InvalidExternalHandle, 898 _ => panic!("Unexpected error value"), 899 } 900 } 901 } 902 903 impl From<RequirementNotMet> for MemoryFdPropertiesError { from(err: RequirementNotMet) -> Self904 fn from(err: RequirementNotMet) -> Self { 905 Self::RequirementNotMet { 906 required_for: err.required_for, 907 requires_one_of: err.requires_one_of, 908 } 909 } 910 } 911 912 #[cfg(test)] 913 mod tests { 914 use crate::device::{ 915 Device, DeviceCreateInfo, DeviceCreationError, FeatureRestriction, FeatureRestrictionError, 916 Features, QueueCreateInfo, 917 }; 918 use std::sync::Arc; 919 920 #[test] one_ref()921 fn one_ref() { 922 let (mut device, _) = gfx_dev_and_queue!(); 923 assert!(Arc::get_mut(&mut device).is_some()); 924 } 925 926 #[test] too_many_queues()927 fn too_many_queues() { 928 let instance = instance!(); 929 let physical_device = match instance.enumerate_physical_devices().unwrap().next() { 930 Some(p) => p, 931 None => return, 932 }; 933 934 let queue_family_index = 0; 935 let queue_family_properties = 936 &physical_device.queue_family_properties()[queue_family_index as usize]; 937 let queues = (0..queue_family_properties.queue_count + 1) 938 .map(|_| (0.5)) 939 .collect(); 940 941 match Device::new( 942 physical_device, 943 DeviceCreateInfo { 944 queue_create_infos: vec![QueueCreateInfo { 945 queue_family_index, 946 queues, 947 ..Default::default() 948 }], 949 ..Default::default() 950 }, 951 ) { 952 Err(DeviceCreationError::TooManyQueuesForFamily) => (), // Success 953 _ => panic!(), 954 }; 955 } 956 957 #[test] unsupported_features()958 fn unsupported_features() { 959 let instance = instance!(); 960 let physical_device = match instance.enumerate_physical_devices().unwrap().next() { 961 Some(p) => p, 962 None => return, 963 }; 964 965 let features = Features::all(); 966 // In the unlikely situation where the device supports everything, we ignore the test. 967 if physical_device.supported_features().contains(&features) { 968 return; 969 } 970 971 match Device::new( 972 physical_device, 973 DeviceCreateInfo { 974 enabled_features: features, 975 queue_create_infos: vec![QueueCreateInfo { 976 queue_family_index: 0, 977 ..Default::default() 978 }], 979 ..Default::default() 980 }, 981 ) { 982 Err(DeviceCreationError::FeatureRestrictionNotMet(FeatureRestrictionError { 983 restriction: FeatureRestriction::NotSupported, 984 .. 985 })) => (), // Success 986 _ => panic!(), 987 }; 988 } 989 990 #[test] priority_out_of_range()991 fn priority_out_of_range() { 992 let instance = instance!(); 993 let physical_device = match instance.enumerate_physical_devices().unwrap().next() { 994 Some(p) => p, 995 None => return, 996 }; 997 998 assert_should_panic!({ 999 Device::new( 1000 physical_device.clone(), 1001 DeviceCreateInfo { 1002 queue_create_infos: vec![QueueCreateInfo { 1003 queue_family_index: 0, 1004 queues: vec![1.4], 1005 ..Default::default() 1006 }], 1007 ..Default::default() 1008 }, 1009 ) 1010 }); 1011 1012 assert_should_panic!({ 1013 Device::new( 1014 physical_device, 1015 DeviceCreateInfo { 1016 queue_create_infos: vec![QueueCreateInfo { 1017 queue_family_index: 0, 1018 queues: vec![-0.2], 1019 ..Default::default() 1020 }], 1021 ..Default::default() 1022 }, 1023 ) 1024 }); 1025 } 1026 } 1027