// Copyright (c) 2016 The vulkano developers // Licensed under the Apache License, Version 2.0 // or the MIT // license , // at your option. All files in the project carrying such // notice may not be copied, modified, or distributed except // according to those terms. #![doc(html_logo_url = "https://raw.githubusercontent.com/vulkano-rs/vulkano/master/logo.png")] //! Safe and rich Rust wrapper around the Vulkan API. //! //! # Brief summary of Vulkan //! //! - The [`Instance`](instance/struct.Instance.html) object is the API entry point. It is the //! first object you must create before starting to use Vulkan. //! //! - The [`PhysicalDevice`](instance/struct.PhysicalDevice.html) object represents an //! implementation of Vulkan available on the system (eg. a graphics card, a software //! implementation, etc.). Physical devices can be enumerated from an instance with //! [`PhysicalDevice::enumerate()`](instance/struct.PhysicalDevice.html#method.enumerate). //! //! - Once you have chosen a physical device to use, you can create a //! [`Device`](device/index.html) object from it. The `Device` is the most important //! object of Vulkan, as it represents an open channel of communication with a physical device. //! You always need to have one before you can do interesting things with Vulkan. //! //! - [*Buffers*](buffer/index.html) and [*images*](image/index.html) can be used to store data on //! memory accessible by the GPU (or more generally by the Vulkan implementation). Buffers are //! usually used to store information about vertices, lights, etc. or arbitrary data, while //! images are used to store textures or multi-dimensional data. //! //! - In order to show something on the screen, you need a [`Swapchain`](swapchain/index.html). //! A `Swapchain` contains special `Image`s that correspond to the content of the window or the //! monitor. When you *present* a swapchain, the content of one of these special images is shown //! on the screen. //! //! - In order to ask the GPU to do something, you must create a //! [*command buffer*](command_buffer/index.html). A command buffer contains a list of commands //! that the GPU must perform. This can include copies between buffers and images, compute //! operations, or graphics operations. For the work to start, the command buffer must then be //! submitted to a [`Queue`](device/struct.Queue.html), which is obtained when you create the //! `Device`. //! //! - In order to be able to add a compute operation or a graphics operation to a command buffer, //! you need to have created a [`ComputePipeline` or a `GraphicsPipeline` //! object](pipeline/index.html) that describes the operation you want. These objects are usually //! created during your program's initialization. `Shader`s are programs that the GPU will //! execute as part of a pipeline. [*Descriptors*](descriptor/index.html) can be used to access //! the content of buffers or images from within shaders. //! //! - For graphical operations, [`RenderPass`es and `Framebuffer`s](framebuffer/index.html) //! describe on which images the implementation must draw upon. //! //! - Once you have built a *command buffer* that contains a list of commands, submitting it to the //! GPU will return an object that implements [the `GpuFuture` trait](sync/index.html). //! `GpuFuture`s allow you to chain multiple submissions together and are essential to performing //! multiple operations on multiple different GPU queues. //! //#![warn(missing_docs)] // TODO: activate #![allow(dead_code)] // TODO: remove #![allow(unused_variables)] // TODO: remove pub use ash::vk::Handle; pub use half; use std::error; use std::fmt; use std::ops::Deref; use std::sync::Arc; use std::sync::MutexGuard; pub use version::Version; #[macro_use] mod tests; #[macro_use] mod extensions; pub mod buffer; pub mod command_buffer; pub mod descriptor_set; pub mod device; pub mod format; mod version; #[macro_use] pub mod render_pass; mod fns; pub mod image; pub mod instance; pub mod memory; pub mod pipeline; pub mod query; pub mod sampler; pub mod swapchain; pub mod sync; mod autogen { // Generated by build.rs include!(concat!(env!("OUT_DIR"), "/autogen.rs")); } /// Represents memory size and offset values on a Vulkan device. /// Analogous to the Rust `usize` type on the host. pub use ash::vk::DeviceSize; /// Alternative to the `Deref` trait. Contrary to `Deref`, must always return the same object. pub unsafe trait SafeDeref: Deref {} unsafe impl<'a, T: ?Sized> SafeDeref for &'a T {} unsafe impl SafeDeref for Arc {} unsafe impl SafeDeref for Box {} /// Gives access to the internal identifier of an object. pub unsafe trait VulkanObject { /// The type of the object. type Object: ash::vk::Handle; /// Returns a reference to the object. fn internal_object(&self) -> Self::Object; } /// Gives access to the internal identifier of an object. // TODO: remove ; crappy design pub unsafe trait SynchronizedVulkanObject { /// The type of the object. type Object: ash::vk::Handle; /// Returns a reference to the object. fn internal_object_guard(&self) -> MutexGuard; } /// Error type returned by most Vulkan functions. #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum OomError { /// There is no memory available on the host (ie. the CPU, RAM, etc.). OutOfHostMemory, /// There is no memory available on the device (ie. video memory). OutOfDeviceMemory, } impl error::Error for OomError {} impl fmt::Display for OomError { #[inline] fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { write!( fmt, "{}", match *self { OomError::OutOfHostMemory => "no memory available on the host", OomError::OutOfDeviceMemory => "no memory available on the graphical device", } ) } } impl From for OomError { #[inline] fn from(err: Error) -> OomError { match err { Error::OutOfHostMemory => OomError::OutOfHostMemory, Error::OutOfDeviceMemory => OomError::OutOfDeviceMemory, _ => panic!("unexpected error: {:?}", err), } } } /// All possible success codes returned by any Vulkan function. #[derive(Debug, Copy, Clone)] #[repr(i32)] enum Success { Success = ash::vk::Result::SUCCESS.as_raw(), NotReady = ash::vk::Result::NOT_READY.as_raw(), Timeout = ash::vk::Result::TIMEOUT.as_raw(), EventSet = ash::vk::Result::EVENT_SET.as_raw(), EventReset = ash::vk::Result::EVENT_RESET.as_raw(), Incomplete = ash::vk::Result::INCOMPLETE.as_raw(), Suboptimal = ash::vk::Result::SUBOPTIMAL_KHR.as_raw(), } /// All possible errors returned by any Vulkan function. /// /// This type is not public. Instead all public error types should implement `From` and /// panic for error code that aren't supposed to happen. #[derive(Debug, Copy, Clone)] #[repr(i32)] // TODO: being pub is necessary because of the weird visibility rules in rustc pub(crate) enum Error { OutOfHostMemory = ash::vk::Result::ERROR_OUT_OF_HOST_MEMORY.as_raw(), OutOfDeviceMemory = ash::vk::Result::ERROR_OUT_OF_DEVICE_MEMORY.as_raw(), InitializationFailed = ash::vk::Result::ERROR_INITIALIZATION_FAILED.as_raw(), DeviceLost = ash::vk::Result::ERROR_DEVICE_LOST.as_raw(), MemoryMapFailed = ash::vk::Result::ERROR_MEMORY_MAP_FAILED.as_raw(), LayerNotPresent = ash::vk::Result::ERROR_LAYER_NOT_PRESENT.as_raw(), ExtensionNotPresent = ash::vk::Result::ERROR_EXTENSION_NOT_PRESENT.as_raw(), FeatureNotPresent = ash::vk::Result::ERROR_FEATURE_NOT_PRESENT.as_raw(), IncompatibleDriver = ash::vk::Result::ERROR_INCOMPATIBLE_DRIVER.as_raw(), TooManyObjects = ash::vk::Result::ERROR_TOO_MANY_OBJECTS.as_raw(), FormatNotSupported = ash::vk::Result::ERROR_FORMAT_NOT_SUPPORTED.as_raw(), SurfaceLost = ash::vk::Result::ERROR_SURFACE_LOST_KHR.as_raw(), NativeWindowInUse = ash::vk::Result::ERROR_NATIVE_WINDOW_IN_USE_KHR.as_raw(), OutOfDate = ash::vk::Result::ERROR_OUT_OF_DATE_KHR.as_raw(), IncompatibleDisplay = ash::vk::Result::ERROR_INCOMPATIBLE_DISPLAY_KHR.as_raw(), ValidationFailed = ash::vk::Result::ERROR_VALIDATION_FAILED_EXT.as_raw(), OutOfPoolMemory = ash::vk::Result::ERROR_OUT_OF_POOL_MEMORY_KHR.as_raw(), FullscreenExclusiveLost = ash::vk::Result::ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT.as_raw(), } /// Checks whether the result returned correctly. fn check_errors(result: ash::vk::Result) -> Result { match result { ash::vk::Result::SUCCESS => Ok(Success::Success), ash::vk::Result::NOT_READY => Ok(Success::NotReady), ash::vk::Result::TIMEOUT => Ok(Success::Timeout), ash::vk::Result::EVENT_SET => Ok(Success::EventSet), ash::vk::Result::EVENT_RESET => Ok(Success::EventReset), ash::vk::Result::INCOMPLETE => Ok(Success::Incomplete), ash::vk::Result::ERROR_OUT_OF_HOST_MEMORY => Err(Error::OutOfHostMemory), ash::vk::Result::ERROR_OUT_OF_DEVICE_MEMORY => Err(Error::OutOfDeviceMemory), ash::vk::Result::ERROR_INITIALIZATION_FAILED => Err(Error::InitializationFailed), ash::vk::Result::ERROR_DEVICE_LOST => Err(Error::DeviceLost), ash::vk::Result::ERROR_MEMORY_MAP_FAILED => Err(Error::MemoryMapFailed), ash::vk::Result::ERROR_LAYER_NOT_PRESENT => Err(Error::LayerNotPresent), ash::vk::Result::ERROR_EXTENSION_NOT_PRESENT => Err(Error::ExtensionNotPresent), ash::vk::Result::ERROR_FEATURE_NOT_PRESENT => Err(Error::FeatureNotPresent), ash::vk::Result::ERROR_INCOMPATIBLE_DRIVER => Err(Error::IncompatibleDriver), ash::vk::Result::ERROR_TOO_MANY_OBJECTS => Err(Error::TooManyObjects), ash::vk::Result::ERROR_FORMAT_NOT_SUPPORTED => Err(Error::FormatNotSupported), ash::vk::Result::ERROR_SURFACE_LOST_KHR => Err(Error::SurfaceLost), ash::vk::Result::ERROR_NATIVE_WINDOW_IN_USE_KHR => Err(Error::NativeWindowInUse), ash::vk::Result::SUBOPTIMAL_KHR => Ok(Success::Suboptimal), ash::vk::Result::ERROR_OUT_OF_DATE_KHR => Err(Error::OutOfDate), ash::vk::Result::ERROR_INCOMPATIBLE_DISPLAY_KHR => Err(Error::IncompatibleDisplay), ash::vk::Result::ERROR_VALIDATION_FAILED_EXT => Err(Error::ValidationFailed), ash::vk::Result::ERROR_OUT_OF_POOL_MEMORY_KHR => Err(Error::OutOfPoolMemory), ash::vk::Result::ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT => { Err(Error::FullscreenExclusiveLost) } ash::vk::Result::ERROR_INVALID_SHADER_NV => panic!( "Vulkan function returned \ VK_ERROR_INVALID_SHADER_NV" ), c => unreachable!("Unexpected error code returned by Vulkan: {}", c), } }