mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2025-02-16 09:02:25 +00:00
Merge branch 'master' into incoming
This commit is contained in:
commit
1ca3ef8231
@ -1,7 +1,9 @@
|
||||
[package]
|
||||
name = "vk-sys"
|
||||
version = "0.2.0"
|
||||
version = "0.2.1"
|
||||
authors = ["Pierre Krieger <pierre.krieger1708@gmail.com>"]
|
||||
repository = "https://github.com/tomaka/vulkano"
|
||||
description = "Bindings for the Vulkan graphics API"
|
||||
license = "MIT/Apache-2.0"
|
||||
documentation = "https://docs.rs/vk-sys"
|
||||
keywords = ["vulkan", "bindings", "graphics", "gpu"]
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "vulkano-shaders"
|
||||
version = "0.3.0"
|
||||
version = "0.3.1"
|
||||
authors = ["Pierre Krieger <pierre.krieger1708@gmail.com>"]
|
||||
repository = "https://github.com/tomaka/vulkano"
|
||||
description = "Shaders "
|
||||
|
@ -47,7 +47,10 @@ pub fn build_glsl_shaders<'a, I>(shaders: I)
|
||||
let mut file_output = File::create(&dest.join("shaders").join(shader))
|
||||
.expect("failed to open shader output");
|
||||
|
||||
let content = glsl_to_spirv::compile(&shader_content, ty).unwrap();
|
||||
let content = match glsl_to_spirv::compile(&shader_content, ty) {
|
||||
Ok(compiled) => compiled,
|
||||
Err(message) => panic!("{}\nfailed to compile shader", message),
|
||||
};
|
||||
let output = reflect("Shader", content).unwrap();
|
||||
write!(file_output, "{}", output).unwrap();
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "vulkano-win"
|
||||
version = "0.3.0"
|
||||
version = "0.3.1"
|
||||
authors = ["Pierre Krieger <pierre.krieger1708@gmail.com>"]
|
||||
repository = "https://github.com/tomaka/vulkano"
|
||||
description = "Link between vulkano and winit"
|
||||
|
@ -1,11 +1,11 @@
|
||||
[package]
|
||||
name = "vulkano"
|
||||
version = "0.3.0"
|
||||
version = "0.3.1"
|
||||
authors = ["Pierre Krieger <pierre.krieger1708@gmail.com>"]
|
||||
repository = "https://github.com/tomaka/vulkano"
|
||||
description = "Safe wrapper for the Vulkan graphics API"
|
||||
license = "MIT/Apache-2.0"
|
||||
documentation = "http://tomaka.github.io/vulkano/vulkano/index.html"
|
||||
documentation = "https://docs.rs/vulkano"
|
||||
|
||||
[dependencies]
|
||||
crossbeam = "0.2.5"
|
||||
|
@ -126,7 +126,7 @@ pub struct Device {
|
||||
physical_device: usize,
|
||||
device: vk::Device,
|
||||
vk: vk::DevicePointers,
|
||||
standard_pool: Mutex<Option<Weak<StdMemoryPool>>>, // TODO: use Weak::new() instead
|
||||
standard_pool: Mutex<Weak<StdMemoryPool>>,
|
||||
standard_command_pools: Mutex<HashMap<u32, Weak<StandardCommandPool>, BuildHasherDefault<FnvHasher>>>,
|
||||
features: Features,
|
||||
extensions: DeviceExtensions,
|
||||
@ -154,10 +154,7 @@ impl Device {
|
||||
///
|
||||
/// # Panic
|
||||
///
|
||||
/// - Panics if one of the requested features is not supported by the physical device.
|
||||
/// - Panics if one of the queue families doesn't belong to the given device.
|
||||
/// - Panics if you request more queues from a family than available.
|
||||
/// - Panics if one of the priorities is outside of the `[0.0 ; 1.0]` range.
|
||||
///
|
||||
// TODO: return Arc<Queue> and handle synchronization in the Queue
|
||||
// TODO: should take the PhysicalDevice by value
|
||||
@ -168,7 +165,9 @@ impl Device {
|
||||
{
|
||||
let queue_families = queue_families.into_iter();
|
||||
|
||||
assert!(phys.supported_features().superset_of(&requested_features));
|
||||
if !phys.supported_features().superset_of(&requested_features) {
|
||||
return Err(DeviceCreationError::UnsupportedFeatures);
|
||||
}
|
||||
|
||||
let vk_i = phys.instance().pointers();
|
||||
|
||||
@ -203,13 +202,17 @@ impl Device {
|
||||
// checking the parameters
|
||||
assert_eq!(queue_family.physical_device().internal_object(),
|
||||
phys.internal_object());
|
||||
assert!(priority >= 0.0 && priority <= 1.0);
|
||||
if priority < 0.0 || priority > 1.0 {
|
||||
return Err(DeviceCreationError::PriorityOutOfRange);
|
||||
}
|
||||
|
||||
// adding to `queues` and `output_queues`
|
||||
if let Some(q) = queues.iter_mut().find(|q| q.0 == queue_family.id()) {
|
||||
output_queues.push((queue_family.id(), q.1.len() as u32));
|
||||
q.1.push(priority);
|
||||
assert!(q.1.len() < queue_family.queues_count());
|
||||
if q.1.len() >= queue_family.queues_count() {
|
||||
return Err(DeviceCreationError::TooManyQueuesForFamily);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
queues.push((queue_family.id(), vec![priority]));
|
||||
@ -276,7 +279,7 @@ impl Device {
|
||||
physical_device: phys.index(),
|
||||
device: device,
|
||||
vk: vk,
|
||||
standard_pool: Mutex::new(None),
|
||||
standard_pool: Mutex::new(Weak::new()),
|
||||
standard_command_pools: Mutex::new(Default::default()),
|
||||
features: requested_features.clone(),
|
||||
extensions: extensions.clone(),
|
||||
@ -345,13 +348,13 @@ impl Device {
|
||||
pub fn standard_pool(me: &Arc<Self>) -> Arc<StdMemoryPool> {
|
||||
let mut pool = me.standard_pool.lock().unwrap();
|
||||
|
||||
if let Some(p) = pool.as_ref().and_then(|w| w.upgrade()) {
|
||||
if let Some(p) = pool.upgrade() {
|
||||
return p;
|
||||
}
|
||||
|
||||
// The weak pointer is empty, so we create the pool.
|
||||
let new_pool = StdMemoryPool::new(me);
|
||||
*pool = Some(Arc::downgrade(&new_pool));
|
||||
*pool = Arc::downgrade(&new_pool);
|
||||
new_pool
|
||||
}
|
||||
|
||||
@ -466,7 +469,12 @@ pub enum DeviceCreationError {
|
||||
OutOfHostMemory,
|
||||
/// There is no memory available on the device (ie. video memory).
|
||||
OutOfDeviceMemory,
|
||||
// FIXME: other values
|
||||
/// Tried to create too many queues for a given family.
|
||||
TooManyQueuesForFamily,
|
||||
/// Some of the requested features are unsupported by the physical device.
|
||||
UnsupportedFeatures,
|
||||
/// The priority of one of the queues is out of the [0.0; 1.0] range.
|
||||
PriorityOutOfRange,
|
||||
}
|
||||
|
||||
impl error::Error for DeviceCreationError {
|
||||
@ -474,7 +482,18 @@ impl error::Error for DeviceCreationError {
|
||||
fn description(&self) -> &str {
|
||||
match *self {
|
||||
DeviceCreationError::OutOfHostMemory => "no memory available on the host",
|
||||
DeviceCreationError::OutOfDeviceMemory => "no memory available on the graphical device",
|
||||
DeviceCreationError::OutOfDeviceMemory => {
|
||||
"no memory available on the graphical device"
|
||||
},
|
||||
DeviceCreationError::TooManyQueuesForFamily => {
|
||||
"tried to create too many queues for a given family"
|
||||
},
|
||||
DeviceCreationError::UnsupportedFeatures => {
|
||||
"some of the requested features are unsupported by the physical device"
|
||||
},
|
||||
DeviceCreationError::PriorityOutOfRange => {
|
||||
"the priority of one of the queues is out of the [0.0; 1.0] range"
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -563,10 +582,79 @@ unsafe impl SynchronizedVulkanObject for Queue {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::sync::Arc;
|
||||
use device::Device;
|
||||
use device::DeviceCreationError;
|
||||
use device::DeviceExtensions;
|
||||
use features::Features;
|
||||
use instance;
|
||||
|
||||
#[test]
|
||||
fn one_ref() {
|
||||
let (mut device, _) = gfx_dev_and_queue!();
|
||||
assert!(Arc::get_mut(&mut device).is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn too_many_queues() {
|
||||
let instance = instance!();
|
||||
let physical = match instance::PhysicalDevice::enumerate(&instance).next() {
|
||||
Some(p) => p,
|
||||
None => return
|
||||
};
|
||||
|
||||
let family = physical.queue_families().next().unwrap();
|
||||
let queues = (0 .. family.queues_count() + 1).map(|_| (family, 1.0));
|
||||
|
||||
match Device::new(&physical, &Features::none(), &DeviceExtensions::none(), queues) {
|
||||
Err(DeviceCreationError::TooManyQueuesForFamily) => return, // Success
|
||||
_ => panic!()
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unsupposed_features() {
|
||||
let instance = instance!();
|
||||
let physical = match instance::PhysicalDevice::enumerate(&instance).next() {
|
||||
Some(p) => p,
|
||||
None => return
|
||||
};
|
||||
|
||||
let family = physical.queue_families().next().unwrap();
|
||||
|
||||
let features = Features::all();
|
||||
// In the unlikely situation where the device supports everything, we ignore the test.
|
||||
if physical.supported_features().superset_of(&features) {
|
||||
return;
|
||||
}
|
||||
|
||||
match Device::new(&physical, &features, &DeviceExtensions::none(), Some((family, 1.0))) {
|
||||
Err(DeviceCreationError::UnsupportedFeatures) => return, // Success
|
||||
_ => panic!()
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn priority_out_of_range() {
|
||||
let instance = instance!();
|
||||
let physical = match instance::PhysicalDevice::enumerate(&instance).next() {
|
||||
Some(p) => p,
|
||||
None => return
|
||||
};
|
||||
|
||||
let family = physical.queue_families().next().unwrap();
|
||||
|
||||
match Device::new(&physical, &Features::none(),
|
||||
&DeviceExtensions::none(), Some((family, 1.4)))
|
||||
{
|
||||
Err(DeviceCreationError::PriorityOutOfRange) => (), // Success
|
||||
_ => panic!()
|
||||
};
|
||||
|
||||
match Device::new(&physical, &Features::none(),
|
||||
&DeviceExtensions::none(), Some((family, -0.2)))
|
||||
{
|
||||
Err(DeviceCreationError::PriorityOutOfRange) => (), // Success
|
||||
_ => panic!()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -58,6 +58,18 @@ macro_rules! features {
|
||||
}
|
||||
}
|
||||
|
||||
/// Builds a `Features` object with all values to true.
|
||||
///
|
||||
/// > **Note**: This function is used for testing purposes, and is probably useless in
|
||||
/// > a real code.
|
||||
pub fn all() -> Features {
|
||||
Features {
|
||||
$(
|
||||
$name: true,
|
||||
)+
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if `self` is a superset of the parameter.
|
||||
///
|
||||
/// That is, for each feature of the parameter that is true, the corresponding value
|
||||
|
@ -33,6 +33,53 @@ use instance::InstanceExtensions;
|
||||
|
||||
/// An instance of a Vulkan context. This is the main object that should be created by an
|
||||
/// application before everything else.
|
||||
///
|
||||
/// See the documentation of [the `instance` module](index.html) for an introduction about
|
||||
/// Vulkan instances.
|
||||
///
|
||||
/// # Extensions and application infos
|
||||
///
|
||||
/// Please check the documentation of [the `instance` module](index.html).
|
||||
///
|
||||
/// # Layers
|
||||
///
|
||||
/// When creating an `Instance`, you have the possibility to pass a list of **layers** that will
|
||||
/// be activated on the newly-created instance. The list of available layers can be retrieved by
|
||||
/// calling [the `layers_list` function](fn.layers_list.html).
|
||||
///
|
||||
/// A layer is a component that will hook and potentially modify the Vulkan function calls.
|
||||
/// For example, activating a layer could add a frames-per-second counter on the screen, or it
|
||||
/// could send informations to a debugger that will debug your application.
|
||||
///
|
||||
/// > **Note**: From an application's point of view, layers "just exist". In practice, on Windows
|
||||
/// > and Linux layers can be installed by third party installers or by package managers and can
|
||||
/// > also be activated by setting the value of the `VK_INSTANCE_LAYERS` environment variable
|
||||
/// > before starting the program. See the documentation of the official Vulkan loader for these
|
||||
/// > platforms.
|
||||
///
|
||||
/// > **Note**: In practice, the most common use of layers right now is for debugging purposes.
|
||||
/// > To do so, you are encouraged to set the `VK_INSTANCE_LAYERS` environment variable on Windows
|
||||
/// > or Linux instead of modifying the source code of your program. For example:
|
||||
/// > `export VK_INSTANCE_LAYERS=VK_LAYER_LUNARG_api_dump` on Linux if you installed the Vulkan SDK
|
||||
/// > will print the list of raw Vulkan function calls.
|
||||
///
|
||||
/// ## Example
|
||||
///
|
||||
/// ```ignore
|
||||
/// // FIXME: this example doesn't run because of ownership problems ; Instance::new() needs a tweak
|
||||
/// use vulkano::instance;
|
||||
/// use vulkano::instance::Instance;
|
||||
/// use vulkano::instance::InstanceExtensions;
|
||||
///
|
||||
/// // For the sake of the example, we activate all the layers that contain the word "foo" in their
|
||||
/// // description.
|
||||
/// let layers = instance::layers_list().unwrap()
|
||||
/// .filter(|l| l.description().contains("foo"))
|
||||
/// .map(|l| l.name());
|
||||
///
|
||||
/// let instance = Instance::new(None, &InstanceExtensions::none(), layers).unwrap();
|
||||
/// ```
|
||||
// TODO: mention that extensions must be supported by layers as well
|
||||
pub struct Instance {
|
||||
instance: vk::Instance,
|
||||
//alloc: Option<Box<Alloc + Send + Sync>>,
|
||||
@ -45,6 +92,21 @@ pub struct Instance {
|
||||
impl Instance {
|
||||
/// Initializes a new instance of Vulkan.
|
||||
///
|
||||
/// See the documentation of `Instance` or of [the `instance` module](index.html) for more
|
||||
/// details.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```no_run
|
||||
/// use vulkano::instance::Instance;
|
||||
/// use vulkano::instance::InstanceExtensions;
|
||||
///
|
||||
/// let instance = match Instance::new(None, &InstanceExtensions::none(), None) {
|
||||
/// Ok(i) => i,
|
||||
/// Err(err) => panic!("Couldn't build instance: {:?}", err)
|
||||
/// };
|
||||
/// ```
|
||||
///
|
||||
/// # Panic
|
||||
///
|
||||
/// - Panics if the version numbers passed in `ApplicationInfo` are too large can't be
|
||||
@ -220,6 +282,19 @@ impl Instance {
|
||||
}*/
|
||||
|
||||
/// Returns the list of extensions that have been loaded.
|
||||
///
|
||||
/// This list is equal to what was passed to `Instance::new()`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```no_run
|
||||
/// use vulkano::instance::Instance;
|
||||
/// use vulkano::instance::InstanceExtensions;
|
||||
///
|
||||
/// let extensions = InstanceExtensions::supported_by_core().unwrap();
|
||||
/// let instance = Instance::new(None, &extensions, None).unwrap();
|
||||
/// assert_eq!(instance.loaded_extensions(), &extensions);
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn loaded_extensions(&self) -> &InstanceExtensions {
|
||||
&self.extensions
|
||||
@ -268,6 +343,7 @@ impl Drop for Instance {
|
||||
}
|
||||
|
||||
/// Information that can be given to the Vulkan driver so that it can identify your application.
|
||||
// TODO: better documentation for struct and methods
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ApplicationInfo<'a> {
|
||||
/// Name of the application.
|
||||
@ -401,6 +477,23 @@ struct PhysicalDeviceInfos {
|
||||
///
|
||||
/// This struct simply contains a pointer to an instance and a number representing the physical
|
||||
/// device. You are therefore encouraged to pass this around by value instead of by reference.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use vulkano::instance::Instance;
|
||||
/// # use vulkano::instance::InstanceExtensions;
|
||||
/// use vulkano::instance::PhysicalDevice;
|
||||
///
|
||||
/// # let instance = Instance::new(None, &InstanceExtensions::none(), None).unwrap();
|
||||
/// for physical_device in PhysicalDevice::enumerate(&instance) {
|
||||
/// print_infos(physical_device);
|
||||
/// }
|
||||
///
|
||||
/// fn print_infos(dev: PhysicalDevice) {
|
||||
/// println!("Name: {}", dev.name());
|
||||
/// }
|
||||
/// ```
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct PhysicalDevice<'a> {
|
||||
instance: &'a Arc<Instance>,
|
||||
@ -409,6 +502,19 @@ pub struct PhysicalDevice<'a> {
|
||||
|
||||
impl<'a> PhysicalDevice<'a> {
|
||||
/// Returns an iterator that enumerates the physical devices available.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use vulkano::instance::Instance;
|
||||
/// # use vulkano::instance::InstanceExtensions;
|
||||
/// use vulkano::instance::PhysicalDevice;
|
||||
///
|
||||
/// # let instance = Instance::new(None, &InstanceExtensions::none(), None).unwrap();
|
||||
/// for physical_device in PhysicalDevice::enumerate(&instance) {
|
||||
/// println!("Available device: {}", physical_device.name());
|
||||
/// }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn enumerate(instance: &'a Arc<Instance>) -> PhysicalDevicesIter<'a> {
|
||||
PhysicalDevicesIter {
|
||||
@ -420,6 +526,17 @@ impl<'a> PhysicalDevice<'a> {
|
||||
/// Returns a physical device from its index. Returns `None` if out of range.
|
||||
///
|
||||
/// Indices range from 0 to the number of devices.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```no_run
|
||||
/// use vulkano::instance::Instance;
|
||||
/// use vulkano::instance::InstanceExtensions;
|
||||
/// use vulkano::instance::PhysicalDevice;
|
||||
///
|
||||
/// let instance = Instance::new(None, &InstanceExtensions::none(), None).unwrap();
|
||||
/// let first_physical_device = PhysicalDevice::from_index(&instance, 0).unwrap();
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn from_index(instance: &'a Arc<Instance>, index: usize) -> Option<PhysicalDevice<'a>> {
|
||||
if instance.physical_devices.len() > index {
|
||||
@ -433,6 +550,17 @@ impl<'a> PhysicalDevice<'a> {
|
||||
}
|
||||
|
||||
/// Returns the instance corresponding to this physical device.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```no_run
|
||||
/// use vulkano::instance::PhysicalDevice;
|
||||
///
|
||||
/// fn do_something(physical_device: PhysicalDevice) {
|
||||
/// let _loaded_extensions = physical_device.instance().loaded_extensions();
|
||||
/// // ...
|
||||
/// }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn instance(&self) -> &'a Arc<Instance> {
|
||||
&self.instance
|
||||
@ -458,6 +586,20 @@ impl<'a> PhysicalDevice<'a> {
|
||||
}
|
||||
|
||||
/// Returns the type of the device.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use vulkano::instance::Instance;
|
||||
/// # use vulkano::instance::InstanceExtensions;
|
||||
/// use vulkano::instance::PhysicalDevice;
|
||||
///
|
||||
/// # let instance = Instance::new(None, &InstanceExtensions::none(), None).unwrap();
|
||||
/// for physical_device in PhysicalDevice::enumerate(&instance) {
|
||||
/// println!("Available device: {} (type: {:?})",
|
||||
/// physical_device.name(), physical_device.ty());
|
||||
/// }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn ty(&self) -> PhysicalDeviceType {
|
||||
match self.instance.physical_devices[self.device].properties.deviceType {
|
||||
|
@ -22,16 +22,41 @@ use instance::loader::LoadingError;
|
||||
use version::Version;
|
||||
|
||||
/// Queries the list of layers that are available when creating an instance.
|
||||
///
|
||||
/// On success, this function returns an iterator that produces
|
||||
/// [`LayerProperties`](struct.LayerProperties.html) objects. In order to enable a layer, you need
|
||||
/// to pass its name (returned by `LayerProperties::name()`) when creating the
|
||||
/// [`Instance`](struct.Instance.html).
|
||||
///
|
||||
/// This function returns an error if it failed to load the Vulkan library.
|
||||
///
|
||||
/// > **Note**: It is possible that one of the layers enumerated here is no longer available when
|
||||
/// > you create the `Instance`. This will lead to an error when calling `Instance::new`. The
|
||||
/// > author isn't aware of any situation where this would happen, but it is theoretically possible
|
||||
/// > according to the specifications.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```no_run
|
||||
/// use vulkano::instance;
|
||||
///
|
||||
/// for layer in instance::layers_list().unwrap() {
|
||||
/// println!("Available layer: {}", layer.name());
|
||||
/// }
|
||||
/// ```
|
||||
pub fn layers_list() -> Result<LayersIterator, LayersListError> {
|
||||
unsafe {
|
||||
let entry_points = try!(loader::entry_points());
|
||||
|
||||
let mut num = 0;
|
||||
try!(check_errors(entry_points.EnumerateInstanceLayerProperties(&mut num, ptr::null_mut())));
|
||||
try!(check_errors({
|
||||
entry_points.EnumerateInstanceLayerProperties(&mut num, ptr::null_mut())
|
||||
}));
|
||||
|
||||
let mut layers: Vec<vk::LayerProperties> = Vec::with_capacity(num as usize);
|
||||
try!(check_errors(entry_points.EnumerateInstanceLayerProperties(&mut num,
|
||||
layers.as_mut_ptr())));
|
||||
try!(check_errors({
|
||||
entry_points.EnumerateInstanceLayerProperties(&mut num, layers.as_mut_ptr())
|
||||
}));
|
||||
layers.set_len(num as usize);
|
||||
|
||||
Ok(LayersIterator {
|
||||
@ -40,31 +65,81 @@ pub fn layers_list() -> Result<LayersIterator, LayersListError> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Properties of an available layer.
|
||||
/// Properties of a layer.
|
||||
pub struct LayerProperties {
|
||||
props: vk::LayerProperties,
|
||||
}
|
||||
|
||||
impl LayerProperties {
|
||||
/// Returns the name of the layer.
|
||||
///
|
||||
/// If you want to enable this layer on an instance, you need to pass this value to
|
||||
/// `Instance::new`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```no_run
|
||||
/// use vulkano::instance;
|
||||
///
|
||||
/// for layer in instance::layers_list().unwrap() {
|
||||
/// println!("Layer name: {}", layer.name());
|
||||
/// }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn name(&self) -> &str {
|
||||
unsafe { CStr::from_ptr(self.props.layerName.as_ptr()).to_str().unwrap() }
|
||||
}
|
||||
|
||||
/// Returns a description of the layer.
|
||||
///
|
||||
/// This description is chosen by the layer itself.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```no_run
|
||||
/// use vulkano::instance;
|
||||
///
|
||||
/// for layer in instance::layers_list().unwrap() {
|
||||
/// println!("Layer description: {}", layer.description());
|
||||
/// }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn description(&self) -> &str {
|
||||
unsafe { CStr::from_ptr(self.props.description.as_ptr()).to_str().unwrap() }
|
||||
}
|
||||
|
||||
/// Returns the version of Vulkan supported by this layer.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```no_run
|
||||
/// use vulkano::instance;
|
||||
/// use vulkano::instance::Version;
|
||||
///
|
||||
/// for layer in instance::layers_list().unwrap() {
|
||||
/// if layer.vulkan_version() >= (Version { major: 2, minor: 0, patch: 0 }) {
|
||||
/// println!("Layer {} requires Vulkan 2.0", layer.name());
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn vulkan_version(&self) -> Version {
|
||||
Version::from_vulkan_version(self.props.specVersion)
|
||||
}
|
||||
|
||||
/// Returns an implementation-specific version number for this layer.
|
||||
///
|
||||
/// The number is chosen by the layer itself. It can be used for bug reports for example.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```no_run
|
||||
/// use vulkano::instance;
|
||||
///
|
||||
/// for layer in instance::layers_list().unwrap() {
|
||||
/// println!("Layer {} - Version: {}", layer.name(), layer.implementation_version());
|
||||
/// }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn implementation_version(&self) -> u32 {
|
||||
self.props.implementationVersion
|
||||
@ -159,7 +234,11 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn layers_list() {
|
||||
let mut list = instance::layers_list().unwrap();
|
||||
let mut list = match instance::layers_list() {
|
||||
Ok(l) => l,
|
||||
Err(_) => return
|
||||
};
|
||||
|
||||
while let Some(_) = list.next() {}
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
//! use vulkano::instance::Instance;
|
||||
//! use vulkano::instance::InstanceExtensions;
|
||||
//!
|
||||
//! let _instance = match Instance::new(None, &InstanceExtensions::none(), None) {
|
||||
//! let instance = match Instance::new(None, &InstanceExtensions::none(), None) {
|
||||
//! Ok(i) => i,
|
||||
//! Err(err) => panic!("Couldn't build instance: {:?}", err)
|
||||
//! };
|
||||
@ -33,7 +33,7 @@
|
||||
//!
|
||||
//! # let instance = Instance::new(None, &InstanceExtensions::none(), None).unwrap();
|
||||
//! for physical_device in PhysicalDevice::enumerate(&instance) {
|
||||
//! println!("Available device: {}", physical_device.name())
|
||||
//! println!("Available device: {}", physical_device.name());
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
@ -65,7 +65,7 @@
|
||||
//! .. InstanceExtensions::none()
|
||||
//! };
|
||||
//!
|
||||
//! let _instance = match Instance::new(None, &extensions, None) {
|
||||
//! let instance = match Instance::new(None, &extensions, None) {
|
||||
//! Ok(i) => i,
|
||||
//! Err(err) => panic!("Couldn't build instance: {:?}", err)
|
||||
//! };
|
||||
@ -124,6 +124,7 @@ pub use self::layers::layers_list;
|
||||
pub use self::layers::LayerProperties;
|
||||
pub use self::layers::LayersIterator;
|
||||
pub use self::loader::LoadingError;
|
||||
pub use version::Version;
|
||||
|
||||
pub mod debug;
|
||||
|
||||
|
@ -26,6 +26,20 @@ use check_errors;
|
||||
use vk;
|
||||
|
||||
/// Represents memory that has been allocated.
|
||||
///
|
||||
/// The destructor of `DeviceMemory` automatically frees the memory.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```no_run
|
||||
/// use vulkano::memory::DeviceMemory;
|
||||
///
|
||||
/// # let device: std::sync::Arc<vulkano::device::Device> = unsafe { ::std::mem::uninitialized() };
|
||||
/// let mem_ty = device.physical_device().memory_types().next().unwrap();
|
||||
///
|
||||
/// // Allocates 1kB of memory.
|
||||
/// let memory = DeviceMemory::alloc(&device, mem_ty, 1024).unwrap();
|
||||
/// ```
|
||||
#[derive(Debug)]
|
||||
pub struct DeviceMemory<D = Arc<Device>> where D: SafeDeref<Target = Device> {
|
||||
memory: vk::DeviceMemory,
|
||||
@ -46,8 +60,9 @@ impl<D> DeviceMemory<D> where D: SafeDeref<Target = Device> {
|
||||
/// - Panics if `memory_type` doesn't belong to the same physical device as `device`.
|
||||
///
|
||||
// TODO: VK_ERROR_TOO_MANY_OBJECTS error
|
||||
// TODO: remove that `D` generic and use `Arc<Device>`
|
||||
#[inline]
|
||||
pub fn alloc(device: &D, memory_type: &MemoryType, size: usize)
|
||||
pub fn alloc(device: &D, memory_type: MemoryType, size: usize)
|
||||
-> Result<DeviceMemory<D>, OomError>
|
||||
where D: Clone
|
||||
{
|
||||
@ -90,7 +105,7 @@ impl<D> DeviceMemory<D> where D: SafeDeref<Target = Device> {
|
||||
/// - Panics if `memory_type` doesn't belong to the same physical device as `device`.
|
||||
/// - Panics if the memory type is not host-visible.
|
||||
///
|
||||
pub fn alloc_and_map(device: &D, memory_type: &MemoryType, size: usize)
|
||||
pub fn alloc_and_map(device: &D, memory_type: MemoryType, size: usize)
|
||||
-> Result<MappedDeviceMemory<D>, OomError>
|
||||
where D: Clone
|
||||
{
|
||||
@ -156,6 +171,34 @@ impl<D> Drop for DeviceMemory<D> where D: SafeDeref<Target = Device> {
|
||||
}
|
||||
|
||||
/// Represents memory that has been allocated and mapped in CPU accessible space.
|
||||
///
|
||||
/// Can be obtained with `DeviceMemory::alloc_and_map`. The function will panic if the memory type
|
||||
/// is not host-accessible.
|
||||
///
|
||||
/// In order to access the content of the allocated memory, you can use the `read_write` method.
|
||||
/// This method returns a guard object that derefs to the content.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```no_run
|
||||
/// use vulkano::memory::DeviceMemory;
|
||||
///
|
||||
/// # let device: std::sync::Arc<vulkano::device::Device> = unsafe { ::std::mem::uninitialized() };
|
||||
/// // The memory type must be mappable.
|
||||
/// let mem_ty = device.physical_device().memory_types()
|
||||
/// .filter(|t| t.is_host_visible())
|
||||
/// .next().unwrap(); // Vk specs guarantee that this can't fail
|
||||
///
|
||||
/// // Allocates 1kB of memory.
|
||||
/// let memory = DeviceMemory::alloc_and_map(&device, mem_ty, 1024).unwrap();
|
||||
///
|
||||
/// // Get access to the content. Note that this is very unsafe for two reasons: 1) the content is
|
||||
/// // uninitialized, and 2) the access is unsynchronized.
|
||||
/// unsafe {
|
||||
/// let mut content = memory.read_write::<[u8]>(0 .. 1024);
|
||||
/// content[12] = 54; // `content` derefs to a `&[u8]` or a `&mut [u8]`
|
||||
/// }
|
||||
/// ```
|
||||
#[derive(Debug)]
|
||||
pub struct MappedDeviceMemory<D = Arc<Device>> where D: SafeDeref<Target = Device> {
|
||||
memory: DeviceMemory<D>,
|
||||
@ -165,7 +208,7 @@ pub struct MappedDeviceMemory<D = Arc<Device>> where D: SafeDeref<Target = Devic
|
||||
|
||||
impl<D> MappedDeviceMemory<D> where D: SafeDeref<Target = Device> {
|
||||
/// Returns the underlying `DeviceMemory`.
|
||||
// TODO: impl AsRef instead
|
||||
// TODO: impl AsRef instead?
|
||||
#[inline]
|
||||
pub fn memory(&self) -> &DeviceMemory<D> {
|
||||
&self.memory
|
||||
@ -173,6 +216,11 @@ impl<D> MappedDeviceMemory<D> where D: SafeDeref<Target = Device> {
|
||||
|
||||
/// Gives access to the content of the memory.
|
||||
///
|
||||
/// This function takes care of calling `vkInvalidateMappedMemoryRanges` and
|
||||
/// `vkFlushMappedMemoryRanges` on the given range. You are therefore encouraged to use the
|
||||
/// smallest range as possible, and to not call this function multiple times in a row for
|
||||
/// several small changes.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// - Type safety is not checked. You must ensure that `T` corresponds to the content of the
|
||||
@ -225,6 +273,8 @@ impl<D> Drop for MappedDeviceMemory<D> where D: SafeDeref<Target = Device> {
|
||||
}
|
||||
|
||||
/// Object that can be used to read or write the content of a `MappedDeviceMemory`.
|
||||
///
|
||||
/// This object derefs to the content, just like a `MutexGuard` for example.
|
||||
pub struct CpuAccess<'a, T: ?Sized + 'a, D = Arc<Device>> where D: SafeDeref<Target = Device> + 'a {
|
||||
pointer: *mut T,
|
||||
mem: &'a MappedDeviceMemory<D>,
|
||||
@ -233,7 +283,12 @@ pub struct CpuAccess<'a, T: ?Sized + 'a, D = Arc<Device>> where D: SafeDeref<Tar
|
||||
}
|
||||
|
||||
impl<'a, T: ?Sized + 'a, D: 'a> CpuAccess<'a, T, D> where D: SafeDeref<Target = Device> {
|
||||
/// Makes a new `CpuAccess` to access a sub-part of the current `CpuAccess`.
|
||||
/// Builds a new `CpuAccess` to access a sub-part of the current `CpuAccess`.
|
||||
///
|
||||
/// This function is unstable. Don't use it directly.
|
||||
// TODO: unsafe?
|
||||
// TODO: decide what to do with this
|
||||
#[doc(hidden)]
|
||||
#[inline]
|
||||
pub fn map<U: ?Sized + 'a, F>(self, f: F) -> CpuAccess<'a, U, D>
|
||||
where F: FnOnce(*mut T) -> *mut U
|
||||
@ -247,8 +302,10 @@ impl<'a, T: ?Sized + 'a, D: 'a> CpuAccess<'a, T, D> where D: SafeDeref<Target =
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'a, T: ?Sized + 'a, D: 'a> Send for CpuAccess<'a, T, D> where D: SafeDeref<Target = Device> {}
|
||||
unsafe impl<'a, T: ?Sized + 'a, D: 'a> Sync for CpuAccess<'a, T, D> where D: SafeDeref<Target = Device> {}
|
||||
unsafe impl<'a, T: ?Sized + 'a, D: 'a> Send for CpuAccess<'a, T, D>
|
||||
where D: SafeDeref<Target = Device> {}
|
||||
unsafe impl<'a, T: ?Sized + 'a, D: 'a> Sync for CpuAccess<'a, T, D>
|
||||
where D: SafeDeref<Target = Device> {}
|
||||
|
||||
impl<'a, T: ?Sized + 'a, D: 'a> Deref for CpuAccess<'a, T, D> where D: SafeDeref<Target = Device> {
|
||||
type Target = T;
|
||||
@ -259,7 +316,9 @@ impl<'a, T: ?Sized + 'a, D: 'a> Deref for CpuAccess<'a, T, D> where D: SafeDeref
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: ?Sized + 'a, D: 'a> DerefMut for CpuAccess<'a, T, D> where D: SafeDeref<Target = Device> {
|
||||
impl<'a, T: ?Sized + 'a, D: 'a> DerefMut for CpuAccess<'a, T, D>
|
||||
where D: SafeDeref<Target = Device>
|
||||
{
|
||||
#[inline]
|
||||
fn deref_mut(&mut self) -> &mut T {
|
||||
unsafe { &mut *self.pointer }
|
||||
@ -299,7 +358,7 @@ mod tests {
|
||||
fn create() {
|
||||
let (device, _) = gfx_dev_and_queue!();
|
||||
let mem_ty = device.physical_device().memory_types().next().unwrap();
|
||||
let _ = DeviceMemory::alloc(&device, &mem_ty, 256).unwrap();
|
||||
let _ = DeviceMemory::alloc(&device, mem_ty, 256).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -307,7 +366,7 @@ mod tests {
|
||||
fn zero_size() {
|
||||
let (device, _) = gfx_dev_and_queue!();
|
||||
let mem_ty = device.physical_device().memory_types().next().unwrap();
|
||||
let _ = DeviceMemory::alloc(&device, &mem_ty, 0);
|
||||
let _ = DeviceMemory::alloc(&device, mem_ty, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -317,7 +376,7 @@ mod tests {
|
||||
let mem_ty = device.physical_device().memory_types().filter(|m| !m.is_lazily_allocated())
|
||||
.next().unwrap();
|
||||
|
||||
match DeviceMemory::alloc(&device, &mem_ty, 0xffffffffffffffff) {
|
||||
match DeviceMemory::alloc(&device, mem_ty, 0xffffffffffffffff) {
|
||||
Err(OomError::OutOfDeviceMemory) => (),
|
||||
_ => panic!()
|
||||
}
|
||||
@ -333,7 +392,7 @@ mod tests {
|
||||
let mut allocs = Vec::new();
|
||||
|
||||
for _ in 0 .. 4 {
|
||||
match DeviceMemory::alloc(&device, &mem_ty, heap_size / 3) {
|
||||
match DeviceMemory::alloc(&device, mem_ty, heap_size / 3) {
|
||||
Err(OomError::OutOfDeviceMemory) => return, // test succeeded
|
||||
Ok(a) => allocs.push(a),
|
||||
_ => ()
|
||||
|
@ -71,7 +71,7 @@
|
||||
//! // Taking the first memory type for the sake of this example.
|
||||
//! let ty = device.physical_device().memory_types().next().unwrap();
|
||||
//!
|
||||
//! let alloc = DeviceMemory::alloc(&device, &ty, 1024).expect("Failed to allocate memory");
|
||||
//! let alloc = DeviceMemory::alloc(&device, ty, 1024).expect("Failed to allocate memory");
|
||||
//!
|
||||
//! // The memory is automatically free'd when `alloc` is destroyed.
|
||||
//! ```
|
||||
|
@ -103,7 +103,7 @@ impl StdHostVisibleMemoryTypePool {
|
||||
let new_block = {
|
||||
const MIN_BLOCK_SIZE: usize = 8 * 1024 * 1024; // 8 MB
|
||||
let to_alloc = cmp::max(MIN_BLOCK_SIZE, size.next_power_of_two());
|
||||
let new_block = try!(DeviceMemory::alloc_and_map(&me.device, &me.memory_type(), to_alloc));
|
||||
let new_block = try!(DeviceMemory::alloc_and_map(&me.device, me.memory_type(), to_alloc));
|
||||
Arc::new(new_block)
|
||||
};
|
||||
|
||||
|
@ -24,6 +24,7 @@ mod non_host_visible;
|
||||
mod pool;
|
||||
|
||||
/// Pool of GPU-visible memory that can be allocated from.
|
||||
// TODO: remove 'static + Send + Sync
|
||||
pub unsafe trait MemoryPool: 'static + Send + Sync {
|
||||
/// Object that represents a single allocation. Its destructor should free the chunk.
|
||||
type Alloc: MemoryPoolAlloc;
|
||||
@ -48,6 +49,7 @@ pub unsafe trait MemoryPool: 'static + Send + Sync {
|
||||
}
|
||||
|
||||
/// Object that represents a single allocation. Its destructor should free the chunk.
|
||||
// TODO: remove 'static + Send + Sync
|
||||
pub unsafe trait MemoryPoolAlloc: 'static + Send + Sync {
|
||||
/// Returns the memory object from which this is allocated. Returns `None` if the memory is
|
||||
/// not mapped.
|
||||
|
@ -102,7 +102,7 @@ impl StdNonHostVisibleMemoryTypePool {
|
||||
let new_block = {
|
||||
const MIN_BLOCK_SIZE: usize = 8 * 1024 * 1024; // 8 MB
|
||||
let to_alloc = cmp::max(MIN_BLOCK_SIZE, size.next_power_of_two());
|
||||
let new_block = try!(DeviceMemory::alloc(&me.device, &me.memory_type(), to_alloc));
|
||||
let new_block = try!(DeviceMemory::alloc(&me.device, me.memory_type(), to_alloc));
|
||||
Arc::new(new_block)
|
||||
};
|
||||
|
||||
|
@ -14,10 +14,13 @@
|
||||
//!
|
||||
//! You can create either an empty cache or a cache from some initial data. Whenever you create a
|
||||
//! graphics or compute pipeline, you have the possibility to pass a reference to that cache.
|
||||
//! TODO: ^ that's not the case yet
|
||||
//! The Vulkan implementation will then look in the cache for an existing entry, or add one if it
|
||||
//! doesn't exist.
|
||||
//!
|
||||
//! Once that is done, you can extract the data from the cache and store it.
|
||||
//! Once that is done, you can extract the data from the cache and store it. See the documentation
|
||||
//! of [`get_data`](struct.PipelineCache.html#method.get_data) for example of how to store the data
|
||||
//! on the disk, and [`with_data`](struct.PipelineCache.html#method.with_data) for how to reload it.
|
||||
//!
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
@ -32,16 +35,53 @@ use check_errors;
|
||||
use vk;
|
||||
|
||||
/// Opaque cache that contains pipeline objects.
|
||||
///
|
||||
/// See [the documentation of the module](index.html) for more info.
|
||||
pub struct PipelineCache {
|
||||
device: Arc<Device>,
|
||||
cache: vk::PipelineCache,
|
||||
}
|
||||
|
||||
impl PipelineCache {
|
||||
/// Builds a new pipeline cache from existing data.
|
||||
/// Builds a new pipeline cache from existing data. The data must have been previously obtained
|
||||
/// with [`get_data`](#method.get_data).
|
||||
///
|
||||
/// The data must have been previously obtained with `get_data`.
|
||||
// TODO: is that unsafe? is it safe to pass garbage data?
|
||||
/// The data passed to this function will most likely be blindly trusted by the Vulkan
|
||||
/// implementation. Therefore you can easily crash your application or the system by passing
|
||||
/// wrong data. Hence why this function is unsafe.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// This example loads a cache from a file, if it exists.
|
||||
/// See [`get_data`](#method.get_data) for how to store the data in a file.
|
||||
/// TODO: there's a header in the cached data that must be checked ; talk about this
|
||||
///
|
||||
/// ```
|
||||
/// # use std::sync::Arc;
|
||||
/// # use vulkano::device::Device;
|
||||
/// use std::fs::File;
|
||||
/// use std::io::Read;
|
||||
/// use vulkano::pipeline::cache::PipelineCache;
|
||||
/// # let device: Arc<Device> = return;
|
||||
///
|
||||
/// let data = {
|
||||
/// let file = File::open("pipeline_cache.bin");
|
||||
/// if let Ok(mut file) = file {
|
||||
/// let mut data = Vec::new();
|
||||
/// if let Ok(_) = file.read_to_end(&mut data) {
|
||||
/// Some(data)
|
||||
/// } else { None }
|
||||
/// } else { None }
|
||||
/// };
|
||||
///
|
||||
/// let cache = if let Some(data) = data {
|
||||
/// // This is unsafe because there is no way to be sure that the file contains valid data.
|
||||
/// unsafe { PipelineCache::with_data(&device, &data).unwrap() }
|
||||
/// } else {
|
||||
/// PipelineCache::empty(&device).unwrap()
|
||||
/// };
|
||||
/// ```
|
||||
#[inline]
|
||||
pub unsafe fn with_data(device: &Arc<Device>, initial_data: &[u8])
|
||||
-> Result<Arc<PipelineCache>, OomError>
|
||||
{
|
||||
@ -49,10 +89,22 @@ impl PipelineCache {
|
||||
}
|
||||
|
||||
/// Builds a new empty pipeline cache.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # use std::sync::Arc;
|
||||
/// # use vulkano::device::Device;
|
||||
/// use vulkano::pipeline::cache::PipelineCache;
|
||||
/// # let device: Arc<Device> = return;
|
||||
/// let cache = PipelineCache::empty(&device).unwrap();
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn empty(device: &Arc<Device>) -> Result<Arc<PipelineCache>, OomError> {
|
||||
unsafe { PipelineCache::new_impl(device, None) }
|
||||
}
|
||||
|
||||
// Actual implementation of the constructor.
|
||||
unsafe fn new_impl(device: &Arc<Device>, initial_data: Option<&[u8]>)
|
||||
-> Result<Arc<PipelineCache>, OomError>
|
||||
{
|
||||
@ -81,11 +133,14 @@ impl PipelineCache {
|
||||
|
||||
/// Merges other pipeline caches into this one.
|
||||
///
|
||||
/// It is `self` that is modified here. The pipeline caches passed as parameter are untouched.
|
||||
///
|
||||
/// # Panic
|
||||
///
|
||||
/// - Panics if `self` is included in the list of other pipelines.
|
||||
///
|
||||
// FIXME: vkMergePipelineCaches is not thread safe for the destination cache
|
||||
// TODO: write example
|
||||
pub fn merge<'a, I>(&self, pipelines: I) -> Result<(), OomError>
|
||||
where I: IntoIterator<Item = &'a &'a Arc<PipelineCache>>
|
||||
{
|
||||
@ -106,7 +161,32 @@ impl PipelineCache {
|
||||
|
||||
/// Obtains the data from the cache.
|
||||
///
|
||||
/// This data can be stored and then reloaded and passed to `PipelineCache::new`.
|
||||
/// This data can be stored and then reloaded and passed to `PipelineCache::with_data`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// This example stores the data of a pipeline cache on the disk.
|
||||
/// See [`with_data`](#method.with_data) for how to reload it.
|
||||
///
|
||||
/// ```
|
||||
/// use std::fs;
|
||||
/// use std::fs::File;
|
||||
/// use std::io::Write;
|
||||
/// # use std::sync::Arc;
|
||||
/// # use vulkano::pipeline::cache::PipelineCache;
|
||||
///
|
||||
/// # let cache: Arc<PipelineCache> = return;
|
||||
/// // If an error happens (eg. no permission for the file) we simply skip storing the cache.
|
||||
/// if let Ok(data) = cache.get_data() {
|
||||
/// if let Ok(mut file) = File::create("pipeline_cache.bin.tmp") {
|
||||
/// if let Ok(_) = file.write_all(&data) {
|
||||
/// let _ = fs::rename("pipeline_cache.bin.tmp", "pipeline_cache.bin");
|
||||
/// } else {
|
||||
/// let _ = fs::remove_file("pipeline_cache.bin.tmp");
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
pub fn get_data(&self) -> Result<Vec<u8>, OomError> {
|
||||
unsafe {
|
||||
let vk = self.device.pointers();
|
||||
|
@ -52,7 +52,7 @@ pub enum PrimitiveTopology {
|
||||
TriangleFan,
|
||||
LineListWithAdjacency,
|
||||
LineStripWithAdjacency,
|
||||
TriangleListWithAdjancecy,
|
||||
TriangleListWithAdjacency,
|
||||
TriangleStripWithAdjacency,
|
||||
PatchList { vertices_per_patch: u32 },
|
||||
}
|
||||
@ -69,7 +69,7 @@ impl Into<vk::PrimitiveTopology> for PrimitiveTopology {
|
||||
PrimitiveTopology::TriangleFan => vk::PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,
|
||||
PrimitiveTopology::LineListWithAdjacency => vk::PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY,
|
||||
PrimitiveTopology::LineStripWithAdjacency => vk::PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY,
|
||||
PrimitiveTopology::TriangleListWithAdjancecy => vk::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY,
|
||||
PrimitiveTopology::TriangleListWithAdjacency => vk::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY,
|
||||
PrimitiveTopology::TriangleStripWithAdjacency => vk::PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY,
|
||||
PrimitiveTopology::PatchList { .. } => vk::PRIMITIVE_TOPOLOGY_PATCH_LIST,
|
||||
}
|
||||
|
@ -491,7 +491,7 @@ impl GeometryShaderExecutionMode {
|
||||
(GeometryShaderExecutionMode::Triangles, PrimitiveTopology::TriangleStrip) => true,
|
||||
(GeometryShaderExecutionMode::Triangles, PrimitiveTopology::TriangleFan) => true,
|
||||
(GeometryShaderExecutionMode::TrianglesWithAdjacency,
|
||||
PrimitiveTopology::TriangleListWithAdjancecy) => true,
|
||||
PrimitiveTopology::TriangleListWithAdjacency) => true,
|
||||
(GeometryShaderExecutionMode::TrianglesWithAdjacency,
|
||||
PrimitiveTopology::TriangleStripWithAdjacency) => true,
|
||||
_ => false,
|
||||
|
@ -7,6 +7,8 @@
|
||||
// notice may not be copied, modified, or distributed except
|
||||
// according to those terms.
|
||||
|
||||
// The `Version` object is reexported from the `instance` module.
|
||||
|
||||
use std::cmp::Ordering;
|
||||
|
||||
/// Represents an API version of Vulkan.
|
||||
|
Loading…
Reference in New Issue
Block a user