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