Add Khronos doc links and other ergonomic cleanup
* Khronos doc links are now automatically generated in vk.rs * Added doc links to all other non-generated functions * Implemented std::error::Error for LoadingError * Made EntryCustom public in addition to the Entry typedef so that rustdoc no longer ignores it * Moved Entry::new into EntryCustom (non-breaking) * Added EntryCustom::try_enumerate_instance_version. The EntryV1_1 trait is not implemented for any type. Even if it were, the function would panic for Vulkan 1.0 implementations * Added entry and instance creation example to lib docs * Updated the Display impl for vk::Result so that it matches other bitmask and enum conventions * Removed lazy_static dependency because it was no longer being referenced
This commit is contained in:
parent
b570edcee2
commit
adb194891f
|
@ -11,7 +11,6 @@ documentation = "https://docs.rs/ash"
|
|||
|
||||
[dependencies]
|
||||
shared_library = "0.1.9"
|
||||
lazy_static = "1"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
|
112
ash/src/entry.rs
112
ash/src/entry.rs
|
@ -27,12 +27,10 @@ const LIB_PATH: &'static str = "libvulkan.so";
|
|||
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
||||
const LIB_PATH: &'static str = "libvulkan.dylib";
|
||||
|
||||
lazy_static! {
|
||||
static ref VK_LIB: Result<DynamicLibrary, String> =
|
||||
DynamicLibrary::open(Some(&Path::new(LIB_PATH)));
|
||||
}
|
||||
|
||||
/// Function loader
|
||||
pub type Entry = EntryCustom<Arc<DynamicLibrary>>;
|
||||
|
||||
/// Function loader
|
||||
#[derive(Clone)]
|
||||
pub struct EntryCustom<L> {
|
||||
static_fn: vk::StaticFn,
|
||||
|
@ -46,6 +44,22 @@ pub enum LoadingError {
|
|||
LibraryLoadError(String),
|
||||
}
|
||||
|
||||
impl fmt::Display for LoadingError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "LoadingError::{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for LoadingError {
|
||||
fn description(&self) -> &str {
|
||||
"LoadingError"
|
||||
}
|
||||
|
||||
fn cause(&self) -> Option<&Error> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum InstanceError {
|
||||
LoadError(Vec<&'static str>),
|
||||
|
@ -125,6 +139,7 @@ pub trait EntryV1_0 {
|
|||
}
|
||||
}
|
||||
|
||||
#[doc = "<https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/vkGetInstanceProcAddr.html>"]
|
||||
fn get_instance_proc_addr(
|
||||
&self,
|
||||
instance: vk::Instance,
|
||||
|
@ -177,6 +192,41 @@ pub trait EntryV1_1: EntryV1_0 {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl EntryCustom<Arc<DynamicLibrary>> {
|
||||
/// ```rust
|
||||
/// # #[macro_use]
|
||||
/// # extern crate ash;
|
||||
/// use ash::{vk, Entry, version::EntryV1_0};
|
||||
/// # fn main() -> Result<(), Box<std::error::Error>> {
|
||||
/// let entry = Entry::new()?;
|
||||
/// let app_info = vk::ApplicationInfo {
|
||||
/// api_version: vk_make_version!(1, 0, 0),
|
||||
/// ..Default::default()
|
||||
/// };
|
||||
/// let create_info = vk::InstanceCreateInfo {
|
||||
/// p_application_info: &app_info,
|
||||
/// ..Default::default()
|
||||
/// };
|
||||
/// let instance = unsafe { entry.create_instance(&create_info, None)? };
|
||||
/// # Ok(()) }
|
||||
/// ```
|
||||
pub fn new() -> Result<Entry, LoadingError> {
|
||||
Self::new_custom(
|
||||
|| {
|
||||
DynamicLibrary::open(Some(&Path::new(LIB_PATH)))
|
||||
.map_err(|err| LoadingError::LibraryLoadError(err.clone()))
|
||||
.map(|dl| Arc::new(dl))
|
||||
},
|
||||
|vk_lib, name| unsafe {
|
||||
vk_lib
|
||||
.symbol(&*name.to_string_lossy())
|
||||
.unwrap_or(ptr::null_mut())
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<L> EntryCustom<L> {
|
||||
pub fn new_custom<Open, Load>(open: Open, mut load: Load) -> Result<Self, LoadingError>
|
||||
where
|
||||
|
@ -201,21 +251,45 @@ impl<L> EntryCustom<L> {
|
|||
lib,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Entry {
|
||||
pub fn new() -> Result<Self, LoadingError> {
|
||||
Self::new_custom(
|
||||
|| {
|
||||
DynamicLibrary::open(Some(&Path::new(LIB_PATH)))
|
||||
.map_err(|err| LoadingError::LibraryLoadError(err.clone()))
|
||||
.map(|dl| Arc::new(dl))
|
||||
},
|
||||
|vk_lib, name| unsafe {
|
||||
vk_lib
|
||||
.symbol(&*name.to_string_lossy())
|
||||
.unwrap_or(ptr::null_mut())
|
||||
},
|
||||
#[doc = "<https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/vkEnumerateInstanceVersion.html>"]
|
||||
/// ```rust
|
||||
/// # #[macro_use]
|
||||
/// # extern crate ash;
|
||||
/// # use ash::Entry;
|
||||
/// # fn main() -> Result<(), Box<std::error::Error>> {
|
||||
/// let entry = Entry::new()?;
|
||||
/// match entry.try_enumerate_instance_version()? {
|
||||
/// // Vulkan 1.1+
|
||||
/// Some(version) => {
|
||||
/// let major = vk_version_major!(version);
|
||||
/// let minor = vk_version_minor!(version);
|
||||
/// let patch = vk_version_patch!(version);
|
||||
/// },
|
||||
/// // Vulkan 1.0
|
||||
/// None => {},
|
||||
/// }
|
||||
/// # Ok(()) }
|
||||
/// ```
|
||||
pub fn try_enumerate_instance_version(&self) -> VkResult<Option<u32>> {
|
||||
unsafe {
|
||||
let mut api_version = 0;
|
||||
let enumerate_instance_version: Option<vk::PFN_vkEnumerateInstanceVersion> = {
|
||||
let name = b"vkEnumerateInstanceVersion\0".as_ptr() as *const _;
|
||||
mem::transmute(
|
||||
self.static_fn()
|
||||
.get_instance_proc_addr(vk::Instance::null(), name),
|
||||
)
|
||||
};
|
||||
if let Some(enumerate_instance_version) = enumerate_instance_version {
|
||||
let err_code = (enumerate_instance_version)(&mut api_version);
|
||||
match err_code {
|
||||
vk::Result::SUCCESS => Ok(Some(api_version)),
|
||||
_ => Err(err_code),
|
||||
}
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,32 @@
|
|||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
//! # Vulkan API
|
||||
//!
|
||||
//! <https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/index.html>
|
||||
//!
|
||||
//! ## Examples
|
||||
//!
|
||||
//! ```rust
|
||||
//! # #[macro_use]
|
||||
//! # extern crate ash;
|
||||
//! use ash::{vk, Entry, version::EntryV1_0};
|
||||
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
//! let entry = Entry::new()?;
|
||||
//! let app_info = vk::ApplicationInfo {
|
||||
//! api_version: vk_make_version!(1, 0, 0),
|
||||
//! ..Default::default()
|
||||
//! };
|
||||
//! let create_info = vk::InstanceCreateInfo {
|
||||
//! p_application_info: &app_info,
|
||||
//! ..Default::default()
|
||||
//! };
|
||||
//! let instance = unsafe { entry.create_instance(&create_info, None)? };
|
||||
//! # Ok(()) }
|
||||
//! ```
|
||||
//!
|
||||
|
||||
extern crate shared_library;
|
||||
|
||||
pub use device::Device;
|
||||
pub use entry::{Entry, InstanceError, LoadingError};
|
||||
pub use entry::{Entry, EntryCustom, InstanceError, LoadingError};
|
||||
pub use instance::Instance;
|
||||
|
||||
mod device;
|
||||
|
|
|
@ -20,24 +20,28 @@ pub trait Handle {
|
|||
fn as_raw(self) -> u64;
|
||||
fn from_raw(u64) -> Self;
|
||||
}
|
||||
#[doc = "<https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/VK_MAKE_VERSION.html>"]
|
||||
#[macro_export]
|
||||
macro_rules! vk_make_version {
|
||||
( $ major : expr , $ minor : expr , $ patch : expr ) => {
|
||||
(($major as u32) << 22) | (($minor as u32) << 12) | $patch as u32
|
||||
};
|
||||
}
|
||||
#[doc = "<https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/VK_VERSION_MAJOR.html>"]
|
||||
#[macro_export]
|
||||
macro_rules! vk_version_major {
|
||||
( $ major : expr ) => {
|
||||
($major as u32) >> 22
|
||||
};
|
||||
}
|
||||
#[doc = "<https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/VK_VERSION_MINOR.html>"]
|
||||
#[macro_export]
|
||||
macro_rules! vk_version_minor {
|
||||
( $ minor : expr ) => {
|
||||
(($minor as u32) >> 12) & 0x3ff
|
||||
};
|
||||
}
|
||||
#[doc = "<https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/VK_VERSION_PATCH.html>"]
|
||||
#[macro_export]
|
||||
macro_rules! vk_version_patch {
|
||||
( $ minor : expr ) => {
|
||||
|
@ -41349,34 +41353,24 @@ impl ::std::error::Error for Result {
|
|||
impl fmt::Display for Result {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
let name = match *self {
|
||||
Result::SUCCESS => Some("Command completed successfully"),
|
||||
Result::NOT_READY => Some("A fence or query has not yet completed"),
|
||||
Result::TIMEOUT => Some("A wait operation has not completed in the specified time"),
|
||||
Result::EVENT_SET => Some("An event is signaled"),
|
||||
Result::EVENT_RESET => Some("An event is unsignaled"),
|
||||
Result::INCOMPLETE => Some("A return array was too small for the result"),
|
||||
Result::ERROR_OUT_OF_HOST_MEMORY => Some("A host memory allocation has failed"),
|
||||
Result::ERROR_OUT_OF_DEVICE_MEMORY => Some("A device memory allocation has failed"),
|
||||
Result::ERROR_INITIALIZATION_FAILED => Some("Initialization of a object has failed"),
|
||||
Result::ERROR_DEVICE_LOST => {
|
||||
Some("The logical device has been lost. See <<devsandqueues-lost-device>>")
|
||||
}
|
||||
Result::ERROR_MEMORY_MAP_FAILED => Some("Mapping of a memory object has failed"),
|
||||
Result::ERROR_LAYER_NOT_PRESENT => Some("Layer specified does not exist"),
|
||||
Result::ERROR_EXTENSION_NOT_PRESENT => Some("Extension specified does not exist"),
|
||||
Result::ERROR_FEATURE_NOT_PRESENT => {
|
||||
Some("Requested feature is not available on this device")
|
||||
}
|
||||
Result::ERROR_INCOMPATIBLE_DRIVER => Some("Unable to find a Vulkan driver"),
|
||||
Result::ERROR_TOO_MANY_OBJECTS => {
|
||||
Some("Too many objects of the type have already been created")
|
||||
}
|
||||
Result::ERROR_FORMAT_NOT_SUPPORTED => {
|
||||
Some("Requested format is not supported on this device")
|
||||
}
|
||||
Result::ERROR_FRAGMENTED_POOL => Some(
|
||||
"A requested pool allocation has failed due to fragmentation of the pool\'s memory",
|
||||
),
|
||||
Result::SUCCESS => Some(stringify!(SUCCESS)),
|
||||
Result::NOT_READY => Some(stringify!(NOT_READY)),
|
||||
Result::TIMEOUT => Some(stringify!(TIMEOUT)),
|
||||
Result::EVENT_SET => Some(stringify!(EVENT_SET)),
|
||||
Result::EVENT_RESET => Some(stringify!(EVENT_RESET)),
|
||||
Result::INCOMPLETE => Some(stringify!(INCOMPLETE)),
|
||||
Result::ERROR_OUT_OF_HOST_MEMORY => Some(stringify!(ERROR_OUT_OF_HOST_MEMORY)),
|
||||
Result::ERROR_OUT_OF_DEVICE_MEMORY => Some(stringify!(ERROR_OUT_OF_DEVICE_MEMORY)),
|
||||
Result::ERROR_INITIALIZATION_FAILED => Some(stringify!(ERROR_INITIALIZATION_FAILED)),
|
||||
Result::ERROR_DEVICE_LOST => Some(stringify!(ERROR_DEVICE_LOST)),
|
||||
Result::ERROR_MEMORY_MAP_FAILED => Some(stringify!(ERROR_MEMORY_MAP_FAILED)),
|
||||
Result::ERROR_LAYER_NOT_PRESENT => Some(stringify!(ERROR_LAYER_NOT_PRESENT)),
|
||||
Result::ERROR_EXTENSION_NOT_PRESENT => Some(stringify!(ERROR_EXTENSION_NOT_PRESENT)),
|
||||
Result::ERROR_FEATURE_NOT_PRESENT => Some(stringify!(ERROR_FEATURE_NOT_PRESENT)),
|
||||
Result::ERROR_INCOMPATIBLE_DRIVER => Some(stringify!(ERROR_INCOMPATIBLE_DRIVER)),
|
||||
Result::ERROR_TOO_MANY_OBJECTS => Some(stringify!(ERROR_TOO_MANY_OBJECTS)),
|
||||
Result::ERROR_FORMAT_NOT_SUPPORTED => Some(stringify!(ERROR_FORMAT_NOT_SUPPORTED)),
|
||||
Result::ERROR_FRAGMENTED_POOL => Some(stringify!(ERROR_FRAGMENTED_POOL)),
|
||||
_ => None,
|
||||
};
|
||||
if let Some(x) = name {
|
||||
|
|
|
@ -14,3 +14,17 @@ fn display_flags() {
|
|||
fn display_enum() {
|
||||
assert_eq!(vk::ChromaLocation::MIDPOINT.to_string(), "MIDPOINT");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn display_result() {
|
||||
assert_eq!(vk::Result::SUCCESS.to_string(), "SUCCESS");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn error_result_description() {
|
||||
use std::error::Error;
|
||||
assert_eq!(
|
||||
vk::Result::SUCCESS.description(),
|
||||
"Command completed successfully"
|
||||
);
|
||||
}
|
||||
|
|
|
@ -179,6 +179,7 @@ pub fn handle_nondispatchable_macro() -> Tokens {
|
|||
}
|
||||
pub fn vk_version_macros() -> Tokens {
|
||||
quote! {
|
||||
#[doc = "<https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/VK_MAKE_VERSION.html>"]
|
||||
#[macro_export]
|
||||
macro_rules! vk_make_version {
|
||||
($major:expr, $minor:expr, $patch:expr) => {
|
||||
|
@ -186,6 +187,7 @@ pub fn vk_version_macros() -> Tokens {
|
|||
};
|
||||
}
|
||||
|
||||
#[doc = "<https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/VK_VERSION_MAJOR.html>"]
|
||||
#[macro_export]
|
||||
macro_rules! vk_version_major {
|
||||
($major:expr) => {
|
||||
|
@ -193,6 +195,7 @@ pub fn vk_version_macros() -> Tokens {
|
|||
};
|
||||
}
|
||||
|
||||
#[doc = "<https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/VK_VERSION_MINOR.html>"]
|
||||
#[macro_export]
|
||||
macro_rules! vk_version_minor {
|
||||
($minor:expr) => {
|
||||
|
@ -200,6 +203,7 @@ pub fn vk_version_macros() -> Tokens {
|
|||
};
|
||||
}
|
||||
|
||||
#[doc = "<https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/VK_VERSION_PATCH.html>"]
|
||||
#[macro_export]
|
||||
macro_rules! vk_version_patch {
|
||||
($minor:expr) => {
|
||||
|
@ -1206,7 +1210,7 @@ pub fn generate_enum<'a>(
|
|||
}
|
||||
|
||||
pub fn generate_result(ident: Ident, _enum: &vkxml::Enumeration) -> Tokens {
|
||||
let notation = _enum.elements.iter().filter_map(|elem| {
|
||||
let description_notation = _enum.elements.iter().filter_map(|elem| {
|
||||
let (variant_name, notation) = match *elem {
|
||||
vkxml::EnumerationElement::Enum(ref constant) => (
|
||||
constant.name.as_str(),
|
||||
|
@ -1223,12 +1227,25 @@ pub fn generate_result(ident: Ident, _enum: &vkxml::Enumeration) -> Tokens {
|
|||
})
|
||||
});
|
||||
|
||||
let notation2 = notation.clone();
|
||||
let display_notation = _enum.elements.iter().filter_map(|elem| {
|
||||
let variant_name = match *elem {
|
||||
vkxml::EnumerationElement::Enum(ref constant) => constant.name.as_str(),
|
||||
_ => {
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
let variant_ident = variant_ident(&_enum.name, variant_name);
|
||||
Some(quote! {
|
||||
#ident::#variant_ident => Some(stringify!(#variant_ident))
|
||||
})
|
||||
});
|
||||
|
||||
quote! {
|
||||
impl ::std::error::Error for #ident {
|
||||
fn description(&self) -> &str {
|
||||
let name = match *self {
|
||||
#(#notation),*,
|
||||
#(#description_notation),*,
|
||||
_ => None,
|
||||
};
|
||||
name.unwrap_or("unknown error")
|
||||
|
@ -1237,7 +1254,7 @@ pub fn generate_result(ident: Ident, _enum: &vkxml::Enumeration) -> Tokens {
|
|||
impl fmt::Display for #ident {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
let name = match *self {
|
||||
#(#notation2),*,
|
||||
#(#display_notation),*,
|
||||
_ => None,
|
||||
};
|
||||
if let Some(x) = name {
|
||||
|
|
Loading…
Reference in a new issue