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