aboutsummaryrefslogtreecommitdiff
path: root/src/instance/loader.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/instance/loader.rs')
-rw-r--r--src/instance/loader.rs316
1 files changed, 0 insertions, 316 deletions
diff --git a/src/instance/loader.rs b/src/instance/loader.rs
deleted file mode 100644
index 7714fd2..0000000
--- a/src/instance/loader.rs
+++ /dev/null
@@ -1,316 +0,0 @@
-// Copyright (c) 2016 The vulkano developers
-// Licensed under the Apache License, Version 2.0
-// <LICENSE-APACHE or
-// https://www.apache.org/licenses/LICENSE-2.0> or the MIT
-// license <LICENSE-MIT or https://opensource.org/licenses/MIT>,
-// at your option. All files in the project carrying such
-// notice may not be copied, modified, or distributed except
-// according to those terms.
-
-//! Vulkan implementation loading system.
-//!
-//! Before vulkano can do anything, it first needs to find an implementation of Vulkan. A Vulkan
-//! implementation is defined as a single `vkGetInstanceProcAddr` function, which can be accessed
-//! through the `Loader` trait.
-//!
-//! This module provides various implementations of the `Loader` trait.
-//!
-//! Once you have a struct that implements `Loader`, you can create a `FunctionPointers` struct
-//! from it and use this `FunctionPointers` struct to build an `Instance`.
-//!
-//! By default vulkano will use the `auto_loader()` function, which tries to automatically load
-//! a Vulkan implementation from the system.
-
-use crate::check_errors;
-use crate::fns::EntryFunctions;
-use crate::OomError;
-use crate::SafeDeref;
-use crate::Version;
-use lazy_static::lazy_static;
-use shared_library;
-use std::error;
-use std::ffi::CStr;
-use std::fmt;
-use std::mem;
-use std::ops::Deref;
-use std::os::raw::c_char;
-use std::os::raw::c_void;
-use std::path::Path;
-
-/// Implemented on objects that grant access to a Vulkan implementation.
-pub unsafe trait Loader {
- /// Calls the `vkGetInstanceProcAddr` function. The parameters are the same.
- ///
- /// The returned function must stay valid for as long as `self` is alive.
- fn get_instance_proc_addr(
- &self,
- instance: ash::vk::Instance,
- name: *const c_char,
- ) -> *const c_void;
-}
-
-unsafe impl<T> Loader for T
-where
- T: SafeDeref,
- T::Target: Loader,
-{
- #[inline]
- fn get_instance_proc_addr(
- &self,
- instance: ash::vk::Instance,
- name: *const c_char,
- ) -> *const c_void {
- (**self).get_instance_proc_addr(instance, name)
- }
-}
-
-/// Implementation of `Loader` that loads Vulkan from a dynamic library.
-pub struct DynamicLibraryLoader {
- vk_lib: shared_library::dynamic_library::DynamicLibrary,
- get_proc_addr:
- extern "system" fn(instance: ash::vk::Instance, pName: *const c_char) -> *const c_void,
-}
-
-impl DynamicLibraryLoader {
- /// Tries to load the dynamic library at the given path, and tries to
- /// load `vkGetInstanceProcAddr` in it.
- ///
- /// # Safety
- ///
- /// - The dynamic library must be a valid Vulkan implementation.
- ///
- pub unsafe fn new<P>(path: P) -> Result<DynamicLibraryLoader, LoadingError>
- where
- P: AsRef<Path>,
- {
- let vk_lib = shared_library::dynamic_library::DynamicLibrary::open(Some(path.as_ref()))
- .map_err(LoadingError::LibraryLoadFailure)?;
-
- let get_proc_addr = {
- let ptr: *mut c_void = vk_lib
- .symbol("vkGetInstanceProcAddr")
- .map_err(|_| LoadingError::MissingEntryPoint("vkGetInstanceProcAddr".to_owned()))?;
- mem::transmute(ptr)
- };
-
- Ok(DynamicLibraryLoader {
- vk_lib,
- get_proc_addr,
- })
- }
-}
-
-unsafe impl Loader for DynamicLibraryLoader {
- #[inline]
- fn get_instance_proc_addr(
- &self,
- instance: ash::vk::Instance,
- name: *const c_char,
- ) -> *const c_void {
- (self.get_proc_addr)(instance, name)
- }
-}
-
-/// Wraps around a loader and contains function pointers.
-pub struct FunctionPointers<L> {
- loader: L,
- fns: EntryFunctions,
-}
-
-impl<L> FunctionPointers<L> {
- /// Loads some global function pointer from the loader.
- pub fn new(loader: L) -> FunctionPointers<L>
- where
- L: Loader,
- {
- let fns = EntryFunctions::load(|name| unsafe {
- mem::transmute(loader.get_instance_proc_addr(ash::vk::Instance::null(), name.as_ptr()))
- });
-
- FunctionPointers { loader, fns }
- }
-
- /// Returns the collection of Vulkan entry points from the Vulkan loader.
- #[inline]
- pub fn fns(&self) -> &EntryFunctions {
- &self.fns
- }
-
- /// Returns the highest Vulkan version that is supported for instances.
- pub fn api_version(&self) -> Result<Version, OomError>
- where
- L: Loader,
- {
- // Per the Vulkan spec:
- // If the vkGetInstanceProcAddr returns NULL for vkEnumerateInstanceVersion, it is a
- // Vulkan 1.0 implementation. Otherwise, the application can call vkEnumerateInstanceVersion
- // to determine the version of Vulkan.
- unsafe {
- let name = CStr::from_bytes_with_nul_unchecked(b"vkEnumerateInstanceVersion\0");
- let func = self.get_instance_proc_addr(ash::vk::Instance::null(), name.as_ptr());
-
- if func.is_null() {
- Ok(Version {
- major: 1,
- minor: 0,
- patch: 0,
- })
- } else {
- type Pfn = extern "system" fn(pApiVersion: *mut u32) -> ash::vk::Result;
- let func: Pfn = mem::transmute(func);
- let mut api_version = 0;
- check_errors(func(&mut api_version))?;
- Ok(Version::from(api_version))
- }
- }
- }
-
- /// Calls `get_instance_proc_addr` on the underlying loader.
- #[inline]
- pub fn get_instance_proc_addr(
- &self,
- instance: ash::vk::Instance,
- name: *const c_char,
- ) -> *const c_void
- where
- L: Loader,
- {
- self.loader.get_instance_proc_addr(instance, name)
- }
-}
-
-/// Expression that returns a loader that assumes that Vulkan is linked to the executable you're
-/// compiling.
-///
-/// If you use this macro, you must linked to a library that provides the `vkGetInstanceProcAddr`
-/// symbol.
-///
-/// This is provided as a macro and not as a regular function, because the macro contains an
-/// `extern {}` block.
-// TODO: should this be unsafe?
-#[macro_export]
-macro_rules! statically_linked_vulkan_loader {
- () => {{
- extern "C" {
- fn vkGetInstanceProcAddr(
- instance: ash::vk::Instance,
- pName: *const c_char,
- ) -> ash::vk::PFN_vkVoidFunction;
- }
-
- struct StaticallyLinkedVulkanLoader;
- unsafe impl Loader for StaticallyLinkedVulkanLoader {
- fn get_instance_proc_addr(
- &self,
- instance: ash::vk::Instance,
- name: *const c_char,
- ) -> extern "system" fn() -> () {
- unsafe { vkGetInstanceProcAddr(instance, name) }
- }
- }
-
- StaticallyLinkedVulkanLoader
- }};
-}
-
-/// Returns the default `FunctionPointers` for this system.
-///
-/// This function tries to auto-guess where to find the Vulkan implementation, and loads it in a
-/// `lazy_static!`. The content of the lazy_static is then returned, or an error if we failed to
-/// load Vulkan.
-pub fn auto_loader(
-) -> Result<&'static FunctionPointers<Box<dyn Loader + Send + Sync>>, LoadingError> {
- #[cfg(target_os = "ios")]
- #[allow(non_snake_case)]
- fn def_loader_impl() -> Result<Box<Loader + Send + Sync>, LoadingError> {
- let loader = statically_linked_vulkan_loader!();
- Ok(Box::new(loader))
- }
-
- #[cfg(not(target_os = "ios"))]
- fn def_loader_impl() -> Result<Box<dyn Loader + Send + Sync>, LoadingError> {
- #[cfg(windows)]
- fn get_path() -> &'static Path {
- Path::new("vulkan-1.dll")
- }
- #[cfg(all(unix, not(target_os = "android"), not(target_os = "macos")))]
- fn get_path() -> &'static Path {
- Path::new("libvulkan.so.1")
- }
- #[cfg(target_os = "macos")]
- fn get_path() -> &'static Path {
- Path::new("libvulkan.1.dylib")
- }
- #[cfg(target_os = "android")]
- fn get_path() -> &'static Path {
- Path::new("libvulkan.so")
- }
-
- let loader = unsafe { DynamicLibraryLoader::new(get_path())? };
-
- Ok(Box::new(loader))
- }
-
- lazy_static! {
- static ref DEFAULT_LOADER: Result<FunctionPointers<Box<dyn Loader + Send + Sync>>, LoadingError> =
- def_loader_impl().map(FunctionPointers::new);
- }
-
- match DEFAULT_LOADER.deref() {
- &Ok(ref ptr) => Ok(ptr),
- &Err(ref err) => Err(err.clone()),
- }
-}
-
-/// Error that can happen when loading the Vulkan loader.
-#[derive(Debug, Clone)]
-pub enum LoadingError {
- /// Failed to load the Vulkan shared library.
- LibraryLoadFailure(String), // TODO: meh for error type, but this needs changes in shared_library
-
- /// One of the entry points required to be supported by the Vulkan implementation is missing.
- MissingEntryPoint(String),
-}
-
-impl error::Error for LoadingError {
- /*#[inline]
- fn source(&self) -> Option<&(dyn error::Error + 'static)> {
- match *self {
- LoadingError::LibraryLoadFailure(ref err) => Some(err),
- _ => None
- }
- }*/
-}
-
-impl fmt::Display for LoadingError {
- #[inline]
- fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
- write!(
- fmt,
- "{}",
- match *self {
- LoadingError::LibraryLoadFailure(_) => "failed to load the Vulkan shared library",
- LoadingError::MissingEntryPoint(_) => {
- "one of the entry points required to be supported by the Vulkan implementation \
- is missing"
- }
- }
- )
- }
-}
-
-#[cfg(test)]
-mod tests {
- use crate::instance::loader::DynamicLibraryLoader;
- use crate::instance::loader::LoadingError;
-
- #[test]
- fn dl_open_error() {
- unsafe {
- match DynamicLibraryLoader::new("_non_existing_library.void") {
- Err(LoadingError::LibraryLoadFailure(_)) => (),
- _ => panic!(),
- }
- }
- }
-}