aboutsummaryrefslogtreecommitdiff
path: root/src/descriptor_set/pool/sys.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/descriptor_set/pool/sys.rs')
-rw-r--r--src/descriptor_set/pool/sys.rs503
1 files changed, 0 insertions, 503 deletions
diff --git a/src/descriptor_set/pool/sys.rs b/src/descriptor_set/pool/sys.rs
deleted file mode 100644
index 134ddc7..0000000
--- a/src/descriptor_set/pool/sys.rs
+++ /dev/null
@@ -1,503 +0,0 @@
-// Copyright (c) 2021 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.
-
-use crate::check_errors;
-use crate::descriptor_set::layout::DescriptorSetLayout;
-use crate::descriptor_set::pool::DescriptorsCount;
-use crate::descriptor_set::UnsafeDescriptorSet;
-use crate::device::Device;
-use crate::device::DeviceOwned;
-use crate::OomError;
-use crate::VulkanObject;
-use smallvec::SmallVec;
-use std::error;
-use std::fmt;
-use std::mem::MaybeUninit;
-use std::ptr;
-use std::sync::Arc;
-use std::vec::IntoIter as VecIntoIter;
-
-/// Pool from which descriptor sets are allocated from.
-///
-/// A pool has a maximum number of descriptor sets and a maximum number of descriptors (one value
-/// per descriptor type) it can allocate.
-pub struct UnsafeDescriptorPool {
- pool: ash::vk::DescriptorPool,
- device: Arc<Device>,
-}
-
-impl UnsafeDescriptorPool {
- /// Initializes a new pool.
- ///
- /// Initializes a pool whose capacity is given by `count` and `max_sets`. At most `count`
- /// descriptors or `max_sets` descriptor sets can be allocated at once with this pool.
- ///
- /// If `free_descriptor_set_bit` is `true`, then individual descriptor sets can be free'd from
- /// the pool. Otherwise you must reset or destroy the whole pool at once.
- ///
- /// # Panic
- ///
- /// - Panics if all the descriptors count are 0.
- /// - Panics if `max_sets` is 0.
- ///
- pub fn new(
- device: Arc<Device>,
- count: &DescriptorsCount,
- max_sets: u32,
- free_descriptor_set_bit: bool,
- ) -> Result<UnsafeDescriptorPool, OomError> {
- let fns = device.fns();
-
- assert_ne!(max_sets, 0, "The maximum number of sets can't be 0");
-
- let mut pool_sizes: SmallVec<[_; 10]> = SmallVec::new();
-
- macro_rules! elem {
- ($field:ident, $ty:expr) => {
- if count.$field >= 1 {
- pool_sizes.push(ash::vk::DescriptorPoolSize {
- ty: $ty,
- descriptor_count: count.$field,
- });
- }
- };
- }
-
- elem!(uniform_buffer, ash::vk::DescriptorType::UNIFORM_BUFFER);
- elem!(storage_buffer, ash::vk::DescriptorType::STORAGE_BUFFER);
- elem!(
- uniform_buffer_dynamic,
- ash::vk::DescriptorType::UNIFORM_BUFFER_DYNAMIC
- );
- elem!(
- storage_buffer_dynamic,
- ash::vk::DescriptorType::STORAGE_BUFFER_DYNAMIC
- );
- elem!(
- uniform_texel_buffer,
- ash::vk::DescriptorType::UNIFORM_TEXEL_BUFFER
- );
- elem!(
- storage_texel_buffer,
- ash::vk::DescriptorType::STORAGE_TEXEL_BUFFER
- );
- elem!(sampled_image, ash::vk::DescriptorType::SAMPLED_IMAGE);
- elem!(storage_image, ash::vk::DescriptorType::STORAGE_IMAGE);
- elem!(sampler, ash::vk::DescriptorType::SAMPLER);
- elem!(
- combined_image_sampler,
- ash::vk::DescriptorType::COMBINED_IMAGE_SAMPLER
- );
- elem!(input_attachment, ash::vk::DescriptorType::INPUT_ATTACHMENT);
-
- assert!(
- !pool_sizes.is_empty(),
- "All the descriptors count of a pool are 0"
- );
-
- let pool = unsafe {
- let infos = ash::vk::DescriptorPoolCreateInfo {
- flags: if free_descriptor_set_bit {
- ash::vk::DescriptorPoolCreateFlags::FREE_DESCRIPTOR_SET
- } else {
- ash::vk::DescriptorPoolCreateFlags::empty()
- },
- max_sets: max_sets,
- pool_size_count: pool_sizes.len() as u32,
- p_pool_sizes: pool_sizes.as_ptr(),
- ..Default::default()
- };
-
- let mut output = MaybeUninit::uninit();
- check_errors(fns.v1_0.create_descriptor_pool(
- device.internal_object(),
- &infos,
- ptr::null(),
- output.as_mut_ptr(),
- ))?;
- output.assume_init()
- };
-
- Ok(UnsafeDescriptorPool {
- pool,
- device: device.clone(),
- })
- }
-
- /// Allocates descriptor sets from the pool, one for each layout.
- /// Returns an iterator to the allocated sets, or an error.
- ///
- /// The `FragmentedPool` errors often can't be prevented. If the function returns this error,
- /// you should just create a new pool.
- ///
- /// # Panic
- ///
- /// - Panics if one of the layouts wasn't created with the same device as the pool.
- ///
- /// # Safety
- ///
- /// See also the `new` function.
- ///
- /// - The total descriptors of the layouts must fit in the pool.
- /// - The total number of descriptor sets allocated from the pool must not overflow the pool.
- /// - You must ensure that the allocated descriptor sets are no longer in use when the pool
- /// is destroyed, as destroying the pool is equivalent to freeing all the sets.
- ///
- #[inline]
- pub unsafe fn alloc<'l, I>(
- &mut self,
- layouts: I,
- ) -> Result<UnsafeDescriptorPoolAllocIter, DescriptorPoolAllocError>
- where
- I: IntoIterator<Item = &'l DescriptorSetLayout>,
- {
- let layouts: SmallVec<[_; 8]> = layouts
- .into_iter()
- .map(|l| {
- assert_eq!(
- self.device.internal_object(),
- l.device().internal_object(),
- "Tried to allocate from a pool with a set layout of a different \
- device"
- );
- l.internal_object()
- })
- .collect();
-
- self.alloc_impl(&layouts)
- }
-
- // Actual implementation of `alloc`. Separated so that it is not inlined.
- unsafe fn alloc_impl(
- &mut self,
- layouts: &SmallVec<[ash::vk::DescriptorSetLayout; 8]>,
- ) -> Result<UnsafeDescriptorPoolAllocIter, DescriptorPoolAllocError> {
- let num = layouts.len();
-
- if num == 0 {
- return Ok(UnsafeDescriptorPoolAllocIter {
- sets: vec![].into_iter(),
- });
- }
-
- let infos = ash::vk::DescriptorSetAllocateInfo {
- descriptor_pool: self.pool,
- descriptor_set_count: layouts.len() as u32,
- p_set_layouts: layouts.as_ptr(),
- ..Default::default()
- };
-
- let mut output = Vec::with_capacity(num);
-
- let fns = self.device.fns();
- let ret = fns.v1_0.allocate_descriptor_sets(
- self.device.internal_object(),
- &infos,
- output.as_mut_ptr(),
- );
-
- // According to the specs, because `VK_ERROR_FRAGMENTED_POOL` was added after version
- // 1.0 of Vulkan, any negative return value except out-of-memory errors must be
- // considered as a fragmented pool error.
- match ret {
- ash::vk::Result::ERROR_OUT_OF_HOST_MEMORY => {
- return Err(DescriptorPoolAllocError::OutOfHostMemory);
- }
- ash::vk::Result::ERROR_OUT_OF_DEVICE_MEMORY => {
- return Err(DescriptorPoolAllocError::OutOfDeviceMemory);
- }
- ash::vk::Result::ERROR_OUT_OF_POOL_MEMORY_KHR => {
- return Err(DescriptorPoolAllocError::OutOfPoolMemory);
- }
- c if c.as_raw() < 0 => {
- return Err(DescriptorPoolAllocError::FragmentedPool);
- }
- _ => (),
- };
-
- output.set_len(num);
-
- Ok(UnsafeDescriptorPoolAllocIter {
- sets: output.into_iter(),
- })
- }
-
- /// Frees some descriptor sets.
- ///
- /// Note that it is not mandatory to free sets. Destroying or resetting the pool destroys all
- /// the descriptor sets.
- ///
- /// # Safety
- ///
- /// - The pool must have been created with `free_descriptor_set_bit` set to `true`.
- /// - The descriptor sets must have been allocated from the pool.
- /// - The descriptor sets must not be free'd twice.
- /// - The descriptor sets must not be in use by the GPU.
- ///
- #[inline]
- pub unsafe fn free<I>(&mut self, descriptor_sets: I) -> Result<(), OomError>
- where
- I: IntoIterator<Item = UnsafeDescriptorSet>,
- {
- let sets: SmallVec<[_; 8]> = descriptor_sets
- .into_iter()
- .map(|s| s.internal_object())
- .collect();
- if !sets.is_empty() {
- self.free_impl(&sets)
- } else {
- Ok(())
- }
- }
-
- // Actual implementation of `free`. Separated so that it is not inlined.
- unsafe fn free_impl(
- &mut self,
- sets: &SmallVec<[ash::vk::DescriptorSet; 8]>,
- ) -> Result<(), OomError> {
- let fns = self.device.fns();
- check_errors(fns.v1_0.free_descriptor_sets(
- self.device.internal_object(),
- self.pool,
- sets.len() as u32,
- sets.as_ptr(),
- ))?;
- Ok(())
- }
-
- /// Resets the pool.
- ///
- /// This destroys all descriptor sets and empties the pool.
- pub unsafe fn reset(&mut self) -> Result<(), OomError> {
- let fns = self.device.fns();
- check_errors(fns.v1_0.reset_descriptor_pool(
- self.device.internal_object(),
- self.pool,
- ash::vk::DescriptorPoolResetFlags::empty(),
- ))?;
- Ok(())
- }
-}
-
-unsafe impl DeviceOwned for UnsafeDescriptorPool {
- #[inline]
- fn device(&self) -> &Arc<Device> {
- &self.device
- }
-}
-
-impl fmt::Debug for UnsafeDescriptorPool {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
- fmt.debug_struct("UnsafeDescriptorPool")
- .field("raw", &self.pool)
- .field("device", &self.device)
- .finish()
- }
-}
-
-impl Drop for UnsafeDescriptorPool {
- #[inline]
- fn drop(&mut self) {
- unsafe {
- let fns = self.device.fns();
- fns.v1_0
- .destroy_descriptor_pool(self.device.internal_object(), self.pool, ptr::null());
- }
- }
-}
-
-/// Error that can be returned when creating a device.
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub enum DescriptorPoolAllocError {
- /// 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,
- /// Allocation has failed because the pool is too fragmented.
- FragmentedPool,
- /// There is no more space available in the descriptor pool.
- OutOfPoolMemory,
-}
-
-impl error::Error for DescriptorPoolAllocError {}
-
-impl fmt::Display for DescriptorPoolAllocError {
- #[inline]
- fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
- write!(
- fmt,
- "{}",
- match *self {
- DescriptorPoolAllocError::OutOfHostMemory => "no memory available on the host",
- DescriptorPoolAllocError::OutOfDeviceMemory => {
- "no memory available on the graphical device"
- }
- DescriptorPoolAllocError::FragmentedPool => {
- "allocation has failed because the pool is too fragmented"
- }
- DescriptorPoolAllocError::OutOfPoolMemory => {
- "there is no more space available in the descriptor pool"
- }
- }
- )
- }
-}
-
-/// Iterator to the descriptor sets allocated from an unsafe descriptor pool.
-#[derive(Debug)]
-pub struct UnsafeDescriptorPoolAllocIter {
- sets: VecIntoIter<ash::vk::DescriptorSet>,
-}
-
-impl Iterator for UnsafeDescriptorPoolAllocIter {
- type Item = UnsafeDescriptorSet;
-
- #[inline]
- fn next(&mut self) -> Option<UnsafeDescriptorSet> {
- self.sets.next().map(|s| UnsafeDescriptorSet { set: s })
- }
-
- #[inline]
- fn size_hint(&self) -> (usize, Option<usize>) {
- self.sets.size_hint()
- }
-}
-
-impl ExactSizeIterator for UnsafeDescriptorPoolAllocIter {}
-
-#[cfg(test)]
-mod tests {
- use crate::descriptor_set::layout::DescriptorBufferDesc;
- use crate::descriptor_set::layout::DescriptorDesc;
- use crate::descriptor_set::layout::DescriptorDescTy;
- use crate::descriptor_set::layout::DescriptorSetDesc;
- use crate::descriptor_set::layout::DescriptorSetLayout;
- use crate::descriptor_set::pool::DescriptorsCount;
- use crate::descriptor_set::pool::UnsafeDescriptorPool;
- use crate::pipeline::shader::ShaderStages;
- use std::iter;
-
- #[test]
- fn pool_create() {
- let (device, _) = gfx_dev_and_queue!();
- let desc = DescriptorsCount {
- uniform_buffer: 1,
- ..DescriptorsCount::zero()
- };
-
- let _ = UnsafeDescriptorPool::new(device, &desc, 10, false).unwrap();
- }
-
- #[test]
- fn zero_max_set() {
- let (device, _) = gfx_dev_and_queue!();
- let desc = DescriptorsCount {
- uniform_buffer: 1,
- ..DescriptorsCount::zero()
- };
-
- assert_should_panic!("The maximum number of sets can't be 0", {
- let _ = UnsafeDescriptorPool::new(device, &desc, 0, false);
- });
- }
-
- #[test]
- fn zero_descriptors() {
- let (device, _) = gfx_dev_and_queue!();
-
- assert_should_panic!("All the descriptors count of a pool are 0", {
- let _ = UnsafeDescriptorPool::new(device, &DescriptorsCount::zero(), 10, false);
- });
- }
-
- #[test]
- fn basic_alloc() {
- let (device, _) = gfx_dev_and_queue!();
-
- let layout = DescriptorDesc {
- ty: DescriptorDescTy::Buffer(DescriptorBufferDesc {
- dynamic: Some(false),
- storage: false,
- }),
- array_count: 1,
- stages: ShaderStages::all_graphics(),
- readonly: true,
- };
-
- let set_layout = DescriptorSetLayout::new(
- device.clone(),
- DescriptorSetDesc::new(iter::once(Some(layout))),
- )
- .unwrap();
-
- let desc = DescriptorsCount {
- uniform_buffer: 10,
- ..DescriptorsCount::zero()
- };
-
- let mut pool = UnsafeDescriptorPool::new(device, &desc, 10, false).unwrap();
- unsafe {
- let sets = pool.alloc(iter::once(&set_layout)).unwrap();
- assert_eq!(sets.count(), 1);
- }
- }
-
- #[test]
- fn alloc_diff_device() {
- let (device1, _) = gfx_dev_and_queue!();
- let (device2, _) = gfx_dev_and_queue!();
-
- let layout = DescriptorDesc {
- ty: DescriptorDescTy::Buffer(DescriptorBufferDesc {
- dynamic: Some(false),
- storage: false,
- }),
- array_count: 1,
- stages: ShaderStages::all_graphics(),
- readonly: true,
- };
-
- let set_layout =
- DescriptorSetLayout::new(device1, DescriptorSetDesc::new(iter::once(Some(layout))))
- .unwrap();
-
- let desc = DescriptorsCount {
- uniform_buffer: 10,
- ..DescriptorsCount::zero()
- };
-
- assert_should_panic!(
- "Tried to allocate from a pool with a set layout \
- of a different device",
- {
- let mut pool = UnsafeDescriptorPool::new(device2, &desc, 10, false).unwrap();
-
- unsafe {
- let _ = pool.alloc(iter::once(&set_layout));
- }
- }
- );
- }
-
- #[test]
- fn alloc_zero() {
- let (device, _) = gfx_dev_and_queue!();
-
- let desc = DescriptorsCount {
- uniform_buffer: 1,
- ..DescriptorsCount::zero()
- };
-
- let mut pool = UnsafeDescriptorPool::new(device, &desc, 1, false).unwrap();
- unsafe {
- let sets = pool.alloc(iter::empty()).unwrap();
- assert_eq!(sets.count(), 0);
- }
- }
-}