• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 use crate::check_errors;
11 use crate::device::physical::{init_physical_devices, PhysicalDeviceInfo};
12 use crate::extensions::ExtensionRestrictionError;
13 use crate::fns::InstanceFunctions;
14 use crate::instance::loader;
15 use crate::instance::loader::FunctionPointers;
16 use crate::instance::loader::Loader;
17 use crate::instance::loader::LoadingError;
18 use crate::instance::InstanceExtensions;
19 use crate::Error;
20 use crate::OomError;
21 use crate::Version;
22 use crate::VulkanObject;
23 use smallvec::SmallVec;
24 use std::borrow::Cow;
25 use std::convert::TryInto;
26 use std::error;
27 use std::ffi::CString;
28 use std::fmt;
29 use std::hash::Hash;
30 use std::hash::Hasher;
31 use std::mem::MaybeUninit;
32 use std::ops::Deref;
33 use std::ptr;
34 use std::slice;
35 use std::sync::Arc;
36 
37 /// An instance of a Vulkan context. This is the main object that should be created by an
38 /// application before everything else.
39 ///
40 /// # Application info
41 ///
42 /// When you create an instance, you have the possibility to pass an `ApplicationInfo` struct as
43 /// the first parameter. This struct contains various information about your application, most
44 /// notably its name and engine.
45 ///
46 /// Passing such a structure allows for example the driver to let the user configure the driver's
47 /// behavior for your application alone through a control panel.
48 ///
49 /// ```no_run
50 /// # #[macro_use] extern crate vulkano;
51 /// # fn main() {
52 /// use vulkano::instance::{Instance, InstanceExtensions};
53 /// use vulkano::Version;
54 ///
55 /// // Builds an `ApplicationInfo` by looking at the content of the `Cargo.toml` file at
56 /// // compile-time.
57 /// let app_infos = app_info_from_cargo_toml!();
58 ///
59 /// let _instance = Instance::new(Some(&app_infos), Version::V1_1, &InstanceExtensions::none(), None).unwrap();
60 /// # }
61 /// ```
62 ///
63 /// # API versions
64 ///
65 /// Both an `Instance` and a [`Device`](crate::device::Device) have a highest version of the Vulkan
66 /// API that they support. This places a limit on what Vulkan functions and features are available
67 /// to use when used on a particular instance or device. It is possible for the instance and the
68 /// device to support different versions. The supported version for an instance can be queried
69 /// before creation with
70 /// [`FunctionPointers::api_version`](crate::instance::loader::FunctionPointers::api_version),
71 /// while for a device it can be retrieved with
72 /// [`PhysicalDevice::api_version`](crate::instance::PhysicalDevice::api_version).
73 ///
74 /// When creating an `Instance`, you have to specify a maximum API version that you will use.
75 /// This restricts the API version that is available for the instance and any devices created from
76 /// it. For example, if both instance and device potentially support Vulkan 1.2, but you specify
77 /// 1.1 as the maximum API version when creating the `Instance`, then you can only use Vulkan 1.1
78 /// functions, even though they could theoretically support a higher version. You can think of it
79 /// as a promise never to use any functionality from a higher version.
80 ///
81 /// The maximum API version is not a _minimum_, so it is possible to set it to a higher version than
82 /// what the instance or device inherently support. The final API version that you are able to use
83 /// on an instance or device is the lower of the supported API version and the chosen maximum API
84 /// version of the `Instance`.
85 ///
86 /// However, due to a quirk in how the Vulkan 1.0 specification was written, if the instance only
87 /// supports Vulkan 1.0, then it is not possible to specify a maximum API version higher than 1.0.
88 /// Trying to create an `Instance` will return an `IncompatibleDriver` error. Consequently, it is
89 /// not possible to use a higher device API version with an instance that only supports 1.0.
90 ///
91 /// # Extensions
92 ///
93 /// When creating an `Instance`, you must provide a list of extensions that must be enabled on the
94 /// newly-created instance. Trying to enable an extension that is not supported by the system will
95 /// result in an error.
96 ///
97 /// Contrary to OpenGL, it is not possible to use the features of an extension if it was not
98 /// explicitly enabled.
99 ///
100 /// Extensions are especially important to take into account if you want to render images on the
101 /// screen, as the only way to do so is to use the `VK_KHR_surface` extension. More information
102 /// about this in the `swapchain` module.
103 ///
104 /// For example, here is how we create an instance with the `VK_KHR_surface` and
105 /// `VK_KHR_android_surface` extensions enabled, which will allow us to render images to an
106 /// Android screen. You can compile and run this code on any system, but it is highly unlikely to
107 /// succeed on anything else than an Android-running device.
108 ///
109 /// ```no_run
110 /// use vulkano::instance::Instance;
111 /// use vulkano::instance::InstanceExtensions;
112 /// use vulkano::Version;
113 ///
114 /// let extensions = InstanceExtensions {
115 ///     khr_surface: true,
116 ///     khr_android_surface: true,
117 ///     .. InstanceExtensions::none()
118 /// };
119 ///
120 /// let instance = match Instance::new(None, Version::V1_1, &extensions, None) {
121 ///     Ok(i) => i,
122 ///     Err(err) => panic!("Couldn't build instance: {:?}", err)
123 /// };
124 /// ```
125 ///
126 /// # Layers
127 ///
128 /// When creating an `Instance`, you have the possibility to pass a list of **layers** that will
129 /// be activated on the newly-created instance. The list of available layers can be retrieved by
130 /// calling [the `layers_list` function](fn.layers_list.html).
131 ///
132 /// A layer is a component that will hook and potentially modify the Vulkan function calls.
133 /// For example, activating a layer could add a frames-per-second counter on the screen, or it
134 /// could send information to a debugger that will debug your application.
135 ///
136 /// > **Note**: From an application's point of view, layers "just exist". In practice, on Windows
137 /// > and Linux, layers can be installed by third party installers or by package managers and can
138 /// > also be activated by setting the value of the `VK_INSTANCE_LAYERS` environment variable
139 /// > before starting the program. See the documentation of the official Vulkan loader for these
140 /// > platforms.
141 ///
142 /// > **Note**: In practice, the most common use of layers right now is for debugging purposes.
143 /// > To do so, you are encouraged to set the `VK_INSTANCE_LAYERS` environment variable on Windows
144 /// > or Linux instead of modifying the source code of your program. For example:
145 /// > `export VK_INSTANCE_LAYERS=VK_LAYER_LUNARG_api_dump` on Linux if you installed the Vulkan SDK
146 /// > will print the list of raw Vulkan function calls.
147 ///
148 /// ## Example
149 ///
150 /// ```
151 /// # use std::sync::Arc;
152 /// # use std::error::Error;
153 /// # use vulkano::instance;
154 /// # use vulkano::instance::Instance;
155 /// # use vulkano::instance::InstanceExtensions;
156 /// # use vulkano::Version;
157 /// # fn test() -> Result<Arc<Instance>, Box<dyn Error>> {
158 /// // For the sake of the example, we activate all the layers that
159 /// // contain the word "foo" in their description.
160 /// let layers: Vec<_> = instance::layers_list()?
161 ///     .filter(|l| l.description().contains("foo"))
162 ///     .collect();
163 ///
164 /// let layer_names = layers.iter()
165 ///     .map(|l| l.name());
166 ///
167 /// let instance = Instance::new(None, Version::V1_1, &InstanceExtensions::none(), layer_names)?;
168 /// # Ok(instance)
169 /// # }
170 /// ```
171 // TODO: mention that extensions must be supported by layers as well
172 pub struct Instance {
173     instance: ash::vk::Instance,
174     //alloc: Option<Box<Alloc + Send + Sync>>,
175 
176     // The highest version that is supported for this instance.
177     // This is the minimum of Instance::max_api_version and FunctionPointers::api_version.
178     api_version: Version,
179 
180     // The highest allowed API version for instances and devices created from it.
181     max_api_version: Version,
182 
183     pub(crate) physical_device_infos: Vec<PhysicalDeviceInfo>,
184     fns: InstanceFunctions,
185     extensions: InstanceExtensions,
186     layers: SmallVec<[CString; 16]>,
187     function_pointers: OwnedOrRef<FunctionPointers<Box<dyn Loader + Send + Sync>>>,
188 }
189 
190 // TODO: fix the underlying cause instead
191 impl ::std::panic::UnwindSafe for Instance {}
192 impl ::std::panic::RefUnwindSafe for Instance {}
193 
194 impl Instance {
195     /// Initializes a new instance of Vulkan.
196     ///
197     /// See the documentation of `Instance` or of [the `instance` module](index.html) for more
198     /// details.
199     ///
200     /// # Example
201     ///
202     /// ```no_run
203     /// use vulkano::instance::Instance;
204     /// use vulkano::instance::InstanceExtensions;
205     /// use vulkano::Version;
206     ///
207     /// let instance = match Instance::new(None, Version::V1_1, &InstanceExtensions::none(), None) {
208     ///     Ok(i) => i,
209     ///     Err(err) => panic!("Couldn't build instance: {:?}", err)
210     /// };
211     /// ```
212     ///
213     /// # Panic
214     ///
215     /// - Panics if the version numbers passed in `ApplicationInfo` are too large can't be
216     ///   converted into a Vulkan version number.
217     /// - Panics if the application name or engine name contain a null character.
218     // TODO: add a test for these ^
219     // TODO: if no allocator is specified by the user, use Rust's allocator instead of leaving
220     //       the choice to Vulkan
new<'a, L>( app_infos: Option<&ApplicationInfo>, max_api_version: Version, extensions: &InstanceExtensions, layers: L, ) -> Result<Arc<Instance>, InstanceCreationError> where L: IntoIterator<Item = &'a str>,221     pub fn new<'a, L>(
222         app_infos: Option<&ApplicationInfo>,
223         max_api_version: Version,
224         extensions: &InstanceExtensions,
225         layers: L,
226     ) -> Result<Arc<Instance>, InstanceCreationError>
227     where
228         L: IntoIterator<Item = &'a str>,
229     {
230         let layers = layers
231             .into_iter()
232             .map(|layer| CString::new(layer).unwrap())
233             .collect::<SmallVec<[_; 16]>>();
234 
235         Instance::new_inner(
236             app_infos,
237             max_api_version,
238             extensions,
239             layers,
240             OwnedOrRef::Ref(loader::auto_loader()?),
241         )
242     }
243 
244     /// Same as `new`, but allows specifying a loader where to load Vulkan from.
with_loader<'a, L>( loader: FunctionPointers<Box<dyn Loader + Send + Sync>>, app_infos: Option<&ApplicationInfo>, max_api_version: Version, extensions: &InstanceExtensions, layers: L, ) -> Result<Arc<Instance>, InstanceCreationError> where L: IntoIterator<Item = &'a str>,245     pub fn with_loader<'a, L>(
246         loader: FunctionPointers<Box<dyn Loader + Send + Sync>>,
247         app_infos: Option<&ApplicationInfo>,
248         max_api_version: Version,
249         extensions: &InstanceExtensions,
250         layers: L,
251     ) -> Result<Arc<Instance>, InstanceCreationError>
252     where
253         L: IntoIterator<Item = &'a str>,
254     {
255         let layers = layers
256             .into_iter()
257             .map(|layer| CString::new(layer).unwrap())
258             .collect::<SmallVec<[_; 16]>>();
259 
260         Instance::new_inner(
261             app_infos,
262             max_api_version,
263             extensions,
264             layers,
265             OwnedOrRef::Owned(loader),
266         )
267     }
268 
new_inner( app_infos: Option<&ApplicationInfo>, max_api_version: Version, extensions: &InstanceExtensions, layers: SmallVec<[CString; 16]>, function_pointers: OwnedOrRef<FunctionPointers<Box<dyn Loader + Send + Sync>>>, ) -> Result<Arc<Instance>, InstanceCreationError>269     fn new_inner(
270         app_infos: Option<&ApplicationInfo>,
271         max_api_version: Version,
272         extensions: &InstanceExtensions,
273         layers: SmallVec<[CString; 16]>,
274         function_pointers: OwnedOrRef<FunctionPointers<Box<dyn Loader + Send + Sync>>>,
275     ) -> Result<Arc<Instance>, InstanceCreationError> {
276         let api_version = std::cmp::min(max_api_version, function_pointers.api_version()?);
277 
278         // Check if the extensions are correct
279         extensions.check_requirements(
280             &InstanceExtensions::supported_by_core_with_loader(&function_pointers)?,
281             api_version,
282         )?;
283 
284         // TODO: For now there are still buggy drivers that will segfault if you don't pass any
285         //       appinfos. Therefore for now we ensure that it can't be `None`.
286         let def = Default::default();
287         let app_infos = match app_infos {
288             Some(a) => Some(a),
289             None => Some(&def),
290         };
291 
292         // Building the CStrings from the `str`s within `app_infos`.
293         // They need to be created ahead of time, since we pass pointers to them.
294         let app_infos_strings = if let Some(app_infos) = app_infos {
295             Some((
296                 app_infos
297                     .application_name
298                     .clone()
299                     .map(|n| CString::new(n.as_bytes().to_owned()).unwrap()),
300                 app_infos
301                     .engine_name
302                     .clone()
303                     .map(|n| CString::new(n.as_bytes().to_owned()).unwrap()),
304             ))
305         } else {
306             None
307         };
308 
309         // Building the `vk::ApplicationInfo` if required.
310         let app_infos = if let Some(app_infos) = app_infos {
311             Some(ash::vk::ApplicationInfo {
312                 p_application_name: app_infos_strings
313                     .as_ref()
314                     .unwrap()
315                     .0
316                     .as_ref()
317                     .map(|s| s.as_ptr())
318                     .unwrap_or(ptr::null()),
319                 application_version: app_infos
320                     .application_version
321                     .map(|v| v.try_into().expect("Version out of range"))
322                     .unwrap_or(0),
323                 p_engine_name: app_infos_strings
324                     .as_ref()
325                     .unwrap()
326                     .1
327                     .as_ref()
328                     .map(|s| s.as_ptr())
329                     .unwrap_or(ptr::null()),
330                 engine_version: app_infos
331                     .engine_version
332                     .map(|v| v.try_into().expect("Version out of range"))
333                     .unwrap_or(0),
334                 api_version: max_api_version.try_into().expect("Version out of range"),
335                 ..Default::default()
336             })
337         } else {
338             None
339         };
340 
341         // FIXME: check whether each layer is supported
342         let layers_ptrs = layers
343             .iter()
344             .map(|layer| layer.as_ptr())
345             .collect::<SmallVec<[_; 16]>>();
346 
347         let extensions_list: Vec<CString> = extensions.into();
348         let extensions_ptrs = extensions_list
349             .iter()
350             .map(|extension| extension.as_ptr())
351             .collect::<SmallVec<[_; 32]>>();
352 
353         // Creating the Vulkan instance.
354         let instance = unsafe {
355             let mut output = MaybeUninit::uninit();
356             let infos = ash::vk::InstanceCreateInfo {
357                 flags: ash::vk::InstanceCreateFlags::empty(),
358                 p_application_info: if let Some(app) = app_infos.as_ref() {
359                     app as *const _
360                 } else {
361                     ptr::null()
362                 },
363                 enabled_layer_count: layers_ptrs.len() as u32,
364                 pp_enabled_layer_names: layers_ptrs.as_ptr(),
365                 enabled_extension_count: extensions_ptrs.len() as u32,
366                 pp_enabled_extension_names: extensions_ptrs.as_ptr(),
367                 ..Default::default()
368             };
369 
370             let fns = function_pointers.fns();
371             check_errors(
372                 fns.v1_0
373                     .create_instance(&infos, ptr::null(), output.as_mut_ptr()),
374             )?;
375             output.assume_init()
376         };
377 
378         // Loading the function pointers of the newly-created instance.
379         let fns = {
380             InstanceFunctions::load(|name| {
381                 function_pointers.get_instance_proc_addr(instance, name.as_ptr())
382             })
383         };
384 
385         let mut instance = Instance {
386             instance,
387             api_version,
388             max_api_version,
389             //alloc: None,
390             physical_device_infos: Vec::new(),
391             fns,
392             extensions: extensions.clone(),
393             layers,
394             function_pointers,
395         };
396 
397         // Enumerating all physical devices.
398         instance.physical_device_infos = init_physical_devices(&instance)?;
399 
400         Ok(Arc::new(instance))
401     }
402 
403     /*/// Same as `new`, but provides an allocator that will be used by the Vulkan library whenever
404     /// it needs to allocate memory on the host.
405     ///
406     /// Note that this allocator can be overridden when you create a `Device`, a `MemoryPool`, etc.
407     pub fn with_alloc(app_infos: Option<&ApplicationInfo>, alloc: Box<Alloc + Send + Sync>) -> Arc<Instance> {
408         unimplemented!()
409     }*/
410 
411     /// Returns the Vulkan version supported by the instance.
412     ///
413     /// This is the lower of the
414     /// [driver's supported version](crate::instance::loader::FunctionPointers::api_version) and
415     /// [`max_api_version`](Instance::max_api_version).
416     #[inline]
api_version(&self) -> Version417     pub fn api_version(&self) -> Version {
418         self.api_version
419     }
420 
421     /// Returns the maximum Vulkan version that was specified when creating the instance.
422     #[inline]
max_api_version(&self) -> Version423     pub fn max_api_version(&self) -> Version {
424         self.max_api_version
425     }
426 
427     /// Grants access to the Vulkan functions of the instance.
428     #[inline]
fns(&self) -> &InstanceFunctions429     pub fn fns(&self) -> &InstanceFunctions {
430         &self.fns
431     }
432 
433     /// Returns the extensions that have been enabled on the instance.
434     #[inline]
enabled_extensions(&self) -> &InstanceExtensions435     pub fn enabled_extensions(&self) -> &InstanceExtensions {
436         &self.extensions
437     }
438 
439     /// Returns the layers that have been enabled on the instance.
440     #[doc(hidden)]
441     #[inline]
enabled_layers(&self) -> slice::Iter<CString>442     pub fn enabled_layers(&self) -> slice::Iter<CString> {
443         self.layers.iter()
444     }
445 }
446 
447 impl fmt::Debug for Instance {
448     #[inline]
fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error>449     fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
450         write!(fmt, "<Vulkan instance {:?}>", self.instance)
451     }
452 }
453 
454 unsafe impl VulkanObject for Instance {
455     type Object = ash::vk::Instance;
456 
457     #[inline]
internal_object(&self) -> ash::vk::Instance458     fn internal_object(&self) -> ash::vk::Instance {
459         self.instance
460     }
461 }
462 
463 impl Drop for Instance {
464     #[inline]
drop(&mut self)465     fn drop(&mut self) {
466         unsafe {
467             self.fns.v1_0.destroy_instance(self.instance, ptr::null());
468         }
469     }
470 }
471 
472 impl PartialEq for Instance {
473     #[inline]
eq(&self, other: &Self) -> bool474     fn eq(&self, other: &Self) -> bool {
475         self.instance == other.instance
476     }
477 }
478 
479 impl Eq for Instance {}
480 
481 impl Hash for Instance {
482     #[inline]
hash<H: Hasher>(&self, state: &mut H)483     fn hash<H: Hasher>(&self, state: &mut H) {
484         self.instance.hash(state);
485     }
486 }
487 
488 // Same as Cow but less annoying.
489 enum OwnedOrRef<T: 'static> {
490     Owned(T),
491     Ref(&'static T),
492 }
493 
494 impl<T> Deref for OwnedOrRef<T> {
495     type Target = T;
496     #[inline]
deref(&self) -> &T497     fn deref(&self) -> &T {
498         match *self {
499             OwnedOrRef::Owned(ref v) => v,
500             OwnedOrRef::Ref(v) => v,
501         }
502     }
503 }
504 
505 /// Information that can be given to the Vulkan driver so that it can identify your application.
506 // TODO: better documentation for struct and methods
507 #[derive(Debug, Clone)]
508 pub struct ApplicationInfo<'a> {
509     /// Name of the application.
510     pub application_name: Option<Cow<'a, str>>,
511     /// An opaque number that contains the version number of the application.
512     pub application_version: Option<Version>,
513     /// Name of the engine used to power the application.
514     pub engine_name: Option<Cow<'a, str>>,
515     /// An opaque number that contains the version number of the engine.
516     pub engine_version: Option<Version>,
517 }
518 
519 impl<'a> ApplicationInfo<'a> {
520     /// Builds an `ApplicationInfo` from the information gathered by Cargo.
521     ///
522     /// # Panic
523     ///
524     /// - Panics if the required environment variables are missing, which happens if the project
525     ///   wasn't built by Cargo.
526     ///
527     #[deprecated(note = "Please use the `app_info_from_cargo_toml!` macro instead")]
from_cargo_toml() -> ApplicationInfo<'a>528     pub fn from_cargo_toml() -> ApplicationInfo<'a> {
529         let version = Version {
530             major: 0,
531             minor: 0,
532             patch: 0,
533         };
534 
535         let name = "";
536 
537         ApplicationInfo {
538             application_name: Some(name.into()),
539             application_version: Some(version),
540             engine_name: None,
541             engine_version: None,
542         }
543     }
544 }
545 
546 /// Builds an `ApplicationInfo` from the information gathered by Cargo.
547 ///
548 /// # Panic
549 ///
550 /// - Panics if the required environment variables are missing, which happens if the project
551 ///   wasn't built by Cargo.
552 ///
553 #[macro_export]
554 macro_rules! app_info_from_cargo_toml {
555     () => {{
556         let version = $crate::instance::Version {
557             major: 0,
558             minor: 0,
559             patch: 0,
560         };
561 
562         let name = "";
563 
564         $crate::instance::ApplicationInfo {
565             application_name: Some(name.into()),
566             application_version: Some(version),
567             engine_name: None,
568             engine_version: None,
569         }
570     }};
571 }
572 
573 impl<'a> Default for ApplicationInfo<'a> {
default() -> ApplicationInfo<'a>574     fn default() -> ApplicationInfo<'a> {
575         ApplicationInfo {
576             application_name: None,
577             application_version: None,
578             engine_name: None,
579             engine_version: None,
580         }
581     }
582 }
583 
584 /// Error that can happen when creating an instance.
585 #[derive(Clone, Debug)]
586 pub enum InstanceCreationError {
587     /// Failed to load the Vulkan shared library.
588     LoadingError(LoadingError),
589     /// Not enough memory.
590     OomError(OomError),
591     /// Failed to initialize for an implementation-specific reason.
592     InitializationFailed,
593     /// One of the requested layers is missing.
594     LayerNotPresent,
595     /// One of the requested extensions is not supported by the implementation.
596     ExtensionNotPresent,
597     /// The version requested is not supported by the implementation.
598     IncompatibleDriver,
599     /// A restriction for an extension was not met.
600     ExtensionRestrictionNotMet(ExtensionRestrictionError),
601 }
602 
603 impl error::Error for InstanceCreationError {
604     #[inline]
source(&self) -> Option<&(dyn error::Error + 'static)>605     fn source(&self) -> Option<&(dyn error::Error + 'static)> {
606         match *self {
607             InstanceCreationError::LoadingError(ref err) => Some(err),
608             InstanceCreationError::OomError(ref err) => Some(err),
609             _ => None,
610         }
611     }
612 }
613 
614 impl fmt::Display for InstanceCreationError {
615     #[inline]
fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error>616     fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
617         match *self {
618             InstanceCreationError::LoadingError(_) => {
619                 write!(fmt, "failed to load the Vulkan shared library")
620             }
621             InstanceCreationError::OomError(_) => write!(fmt, "not enough memory available"),
622             InstanceCreationError::InitializationFailed => write!(fmt, "initialization failed"),
623             InstanceCreationError::LayerNotPresent => write!(fmt, "layer not present"),
624             InstanceCreationError::ExtensionNotPresent => write!(fmt, "extension not present"),
625             InstanceCreationError::IncompatibleDriver => write!(fmt, "incompatible driver"),
626             InstanceCreationError::ExtensionRestrictionNotMet(err) => err.fmt(fmt),
627         }
628     }
629 }
630 
631 impl From<OomError> for InstanceCreationError {
632     #[inline]
from(err: OomError) -> InstanceCreationError633     fn from(err: OomError) -> InstanceCreationError {
634         InstanceCreationError::OomError(err)
635     }
636 }
637 
638 impl From<LoadingError> for InstanceCreationError {
639     #[inline]
from(err: LoadingError) -> InstanceCreationError640     fn from(err: LoadingError) -> InstanceCreationError {
641         InstanceCreationError::LoadingError(err)
642     }
643 }
644 
645 impl From<ExtensionRestrictionError> for InstanceCreationError {
646     #[inline]
from(err: ExtensionRestrictionError) -> Self647     fn from(err: ExtensionRestrictionError) -> Self {
648         Self::ExtensionRestrictionNotMet(err)
649     }
650 }
651 
652 impl From<Error> for InstanceCreationError {
653     #[inline]
from(err: Error) -> InstanceCreationError654     fn from(err: Error) -> InstanceCreationError {
655         match err {
656             err @ Error::OutOfHostMemory => InstanceCreationError::OomError(OomError::from(err)),
657             err @ Error::OutOfDeviceMemory => InstanceCreationError::OomError(OomError::from(err)),
658             Error::InitializationFailed => InstanceCreationError::InitializationFailed,
659             Error::LayerNotPresent => InstanceCreationError::LayerNotPresent,
660             Error::ExtensionNotPresent => InstanceCreationError::ExtensionNotPresent,
661             Error::IncompatibleDriver => InstanceCreationError::IncompatibleDriver,
662             _ => panic!("unexpected error: {:?}", err),
663         }
664     }
665 }
666 
667 #[cfg(test)]
668 mod tests {
669     use crate::device::physical::PhysicalDevice;
670 
671     #[test]
create_instance()672     fn create_instance() {
673         let _ = instance!();
674     }
675 
676     #[test]
queue_family_by_id()677     fn queue_family_by_id() {
678         let instance = instance!();
679 
680         let phys = match PhysicalDevice::enumerate(&instance).next() {
681             Some(p) => p,
682             None => return,
683         };
684 
685         let queue_family = match phys.queue_families().next() {
686             Some(q) => q,
687             None => return,
688         };
689 
690         let by_id = phys.queue_family_by_id(queue_family.id()).unwrap();
691         assert_eq!(by_id.id(), queue_family.id());
692     }
693 }
694