diff options
Diffstat (limited to 'src/descriptor_set/fixed_size_pool.rs')
-rw-r--r-- | src/descriptor_set/fixed_size_pool.rs | 604 |
1 files changed, 0 insertions, 604 deletions
diff --git a/src/descriptor_set/fixed_size_pool.rs b/src/descriptor_set/fixed_size_pool.rs deleted file mode 100644 index 248f794..0000000 --- a/src/descriptor_set/fixed_size_pool.rs +++ /dev/null @@ -1,604 +0,0 @@ -// Copyright (c) 2017 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. - -//! Pool of descriptor sets of a specific capacity that are automatically reclaimed. -//! -//! You are encouraged to use this type when you need a different descriptor set at each frame, or -//! regularly during the execution. -//! -//! # Example -//! -//! At initialization, create a `FixedSizeDescriptorSetsPool`. -//! -//! ```rust -//! use vulkano::descriptor_set::FixedSizeDescriptorSetsPool; -//! # use vulkano::pipeline::GraphicsPipelineAbstract; -//! # use std::sync::Arc; -//! # let graphics_pipeline: Arc<GraphicsPipelineAbstract> = return; -//! // use vulkano::pipeline::GraphicsPipelineAbstract; -//! // let graphics_pipeline: Arc<GraphicsPipelineAbstract> = ...; -//! -//! let layout = graphics_pipeline.layout().descriptor_set_layouts().get(0).unwrap(); -//! let pool = FixedSizeDescriptorSetsPool::new(layout.clone()); -//! ``` -//! -//! You would then typically store the pool in a struct for later. Then whenever you need a -//! descriptor set, call `pool.next()` to start the process of building it. -//! -//! ```rust -//! # use std::sync::Arc; -//! # use vulkano::descriptor_set::FixedSizeDescriptorSetsPool; -//! # use vulkano::pipeline::GraphicsPipelineAbstract; -//! # let mut pool: FixedSizeDescriptorSetsPool = return; -//! let descriptor_set = pool.next() -//! //.add_buffer(...) -//! //.add_sampled_image(...) -//! .build().unwrap(); -//! ``` -//! -//! Note that `next()` requires exclusive (`mut`) access to the pool. You can use a `Mutex` around -//! the pool if you can't provide this. - -use crate::buffer::BufferAccess; -use crate::buffer::BufferViewRef; -use crate::descriptor_set::layout::DescriptorSetLayout; -use crate::descriptor_set::persistent::*; -use crate::descriptor_set::pool::DescriptorPool; -use crate::descriptor_set::pool::DescriptorPoolAlloc; -use crate::descriptor_set::pool::DescriptorPoolAllocError; -use crate::descriptor_set::pool::UnsafeDescriptorPool; -use crate::descriptor_set::DescriptorSet; -use crate::descriptor_set::UnsafeDescriptorSet; -use crate::device::Device; -use crate::device::DeviceOwned; -use crate::image::view::ImageViewAbstract; -use crate::sampler::Sampler; -use crate::OomError; -use crate::VulkanObject; -use crossbeam_queue::SegQueue; -use std::hash::Hash; -use std::hash::Hasher; -use std::sync::Arc; - -/// Pool of descriptor sets of a specific capacity that are automatically reclaimed. -#[derive(Clone)] -pub struct FixedSizeDescriptorSetsPool { - layout: Arc<DescriptorSetLayout>, - // We hold a local implementation of the `DescriptorPool` trait for our own purpose. Since we - // don't want to expose this trait impl in our API, we use a separate struct. - pool: LocalPool, -} - -impl FixedSizeDescriptorSetsPool { - /// Initializes a new pool. The pool is configured to allocate sets that corresponds to the - /// parameters passed to this function. - pub fn new(layout: Arc<DescriptorSetLayout>) -> FixedSizeDescriptorSetsPool { - let device = layout.device().clone(); - - FixedSizeDescriptorSetsPool { - layout, - pool: LocalPool { - device, - next_capacity: 3, - current_pool: None, - }, - } - } - - /// Starts the process of building a new descriptor set. - /// - /// The set will corresponds to the set layout that was passed to `new`. - #[inline] - pub fn next(&mut self) -> FixedSizeDescriptorSetBuilder<()> { - let inner = PersistentDescriptorSet::start(self.layout.clone()); - - FixedSizeDescriptorSetBuilder { pool: self, inner } - } -} - -/// A descriptor set created from a `FixedSizeDescriptorSetsPool`. -pub struct FixedSizeDescriptorSet<R> { - inner: PersistentDescriptorSet<R, LocalPoolAlloc>, -} - -unsafe impl<R> DescriptorSet for FixedSizeDescriptorSet<R> -where - R: PersistentDescriptorSetResources, -{ - #[inline] - fn inner(&self) -> &UnsafeDescriptorSet { - self.inner.inner() - } - - #[inline] - fn layout(&self) -> &Arc<DescriptorSetLayout> { - self.inner.layout() - } - - #[inline] - fn num_buffers(&self) -> usize { - self.inner.num_buffers() - } - - #[inline] - fn buffer(&self, index: usize) -> Option<(&dyn BufferAccess, u32)> { - self.inner.buffer(index) - } - - #[inline] - fn num_images(&self) -> usize { - self.inner.num_images() - } - - #[inline] - fn image(&self, index: usize) -> Option<(&dyn ImageViewAbstract, u32)> { - self.inner.image(index) - } -} - -unsafe impl<R> DeviceOwned for FixedSizeDescriptorSet<R> { - #[inline] - fn device(&self) -> &Arc<Device> { - self.inner.device() - } -} - -impl<R> PartialEq for FixedSizeDescriptorSet<R> -where - R: PersistentDescriptorSetResources, -{ - #[inline] - fn eq(&self, other: &Self) -> bool { - self.inner().internal_object() == other.inner().internal_object() - && self.device() == other.device() - } -} - -impl<R> Eq for FixedSizeDescriptorSet<R> where R: PersistentDescriptorSetResources {} - -impl<R> Hash for FixedSizeDescriptorSet<R> -where - R: PersistentDescriptorSetResources, -{ - #[inline] - fn hash<H: Hasher>(&self, state: &mut H) { - self.inner().internal_object().hash(state); - self.device().hash(state); - } -} - -// The fields of this struct can be considered as fields of the `FixedSizeDescriptorSet`. They are -// in a separate struct because we don't want to expose the fact that we implement the -// `DescriptorPool` trait. -#[derive(Clone)] -struct LocalPool { - // The `LocalPoolInner` struct contains an actual Vulkan pool. Every time it is full, we create - // a new pool and replace the current one with the new one. - current_pool: Option<Arc<LocalPoolInner>>, - // Capacity to use when we create a new Vulkan pool. - next_capacity: u32, - // The Vulkan device. - device: Arc<Device>, -} - -struct LocalPoolInner { - // The actual Vulkan descriptor pool. This field isn't actually used anywhere, but we need to - // keep the pool alive in order to keep the descriptor sets valid. - actual_pool: UnsafeDescriptorPool, - - // List of descriptor sets. When `alloc` is called, a descriptor will be extracted from this - // list. When a `LocalPoolAlloc` is dropped, its descriptor set is put back in this list. - reserve: SegQueue<UnsafeDescriptorSet>, -} - -struct LocalPoolAlloc { - // The `LocalPoolInner` we were allocated from. We need to keep a copy of it in each allocation - // so that we can put back the allocation in the list in our `Drop` impl. - pool: Arc<LocalPoolInner>, - - // The actual descriptor set, wrapped inside an `Option` so that we can extract it in our - // `Drop` impl. - actual_alloc: Option<UnsafeDescriptorSet>, -} - -unsafe impl DescriptorPool for LocalPool { - type Alloc = LocalPoolAlloc; - - fn alloc(&mut self, layout: &DescriptorSetLayout) -> Result<Self::Alloc, OomError> { - loop { - // Try to extract a descriptor from the current pool if any exist. - // This is the most common case. - if let Some(ref mut current_pool) = self.current_pool { - if let Some(already_existing_set) = current_pool.reserve.pop() { - return Ok(LocalPoolAlloc { - actual_alloc: Some(already_existing_set), - pool: current_pool.clone(), - }); - } - } - - // If we failed to grab an existing set, that means the current pool is full. Create a - // new one of larger capacity. - let count = *layout.descriptors_count() * self.next_capacity; - let mut new_pool = - UnsafeDescriptorPool::new(self.device.clone(), &count, self.next_capacity, false)?; - let alloc = unsafe { - match new_pool.alloc((0..self.next_capacity).map(|_| layout)) { - Ok(iter) => { - let stack = SegQueue::new(); - for elem in iter { - stack.push(elem); - } - stack - } - Err(DescriptorPoolAllocError::OutOfHostMemory) => { - return Err(OomError::OutOfHostMemory); - } - Err(DescriptorPoolAllocError::OutOfDeviceMemory) => { - return Err(OomError::OutOfDeviceMemory); - } - Err(DescriptorPoolAllocError::FragmentedPool) => { - // This can't happen as we don't free individual sets. - unreachable!() - } - Err(DescriptorPoolAllocError::OutOfPoolMemory) => unreachable!(), - } - }; - - self.next_capacity = self.next_capacity.saturating_mul(2); - self.current_pool = Some(Arc::new(LocalPoolInner { - actual_pool: new_pool, - reserve: alloc, - })); - } - } -} - -unsafe impl DeviceOwned for LocalPool { - #[inline] - fn device(&self) -> &Arc<Device> { - &self.device - } -} - -impl DescriptorPoolAlloc for LocalPoolAlloc { - #[inline] - fn inner(&self) -> &UnsafeDescriptorSet { - self.actual_alloc.as_ref().unwrap() - } - - #[inline] - fn inner_mut(&mut self) -> &mut UnsafeDescriptorSet { - self.actual_alloc.as_mut().unwrap() - } -} - -impl Drop for LocalPoolAlloc { - fn drop(&mut self) { - let inner = self.actual_alloc.take().unwrap(); - self.pool.reserve.push(inner); - } -} - -/// Prototype of a `FixedSizeDescriptorSet`. -/// -/// The template parameter `R` is an unspecified type that represents the list of resources. -/// -/// See the docs of `FixedSizeDescriptorSetsPool` for an example. -pub struct FixedSizeDescriptorSetBuilder<'a, R> { - pool: &'a mut FixedSizeDescriptorSetsPool, - inner: PersistentDescriptorSetBuilder<R>, -} - -impl<'a, R> FixedSizeDescriptorSetBuilder<'a, R> { - /// Builds a `FixedSizeDescriptorSet` from the builder. - #[inline] - pub fn build(self) -> Result<FixedSizeDescriptorSet<R>, PersistentDescriptorSetBuildError> { - let inner = self.inner.build_with_pool(&mut self.pool.pool)?; - Ok(FixedSizeDescriptorSet { inner }) - } - - /// Call this function if the next element of the set is an array in order to set the value of - /// each element. - /// - /// Returns an error if the descriptor is empty. - /// - /// This function can be called even if the descriptor isn't an array, and it is valid to enter - /// the "array", add one element, then leave. - #[inline] - pub fn enter_array( - self, - ) -> Result<FixedSizeDescriptorSetBuilderArray<'a, R>, PersistentDescriptorSetError> { - Ok(FixedSizeDescriptorSetBuilderArray { - pool: self.pool, - inner: self.inner.enter_array()?, - }) - } - - /// Skips the current descriptor if it is empty. - #[inline] - pub fn add_empty( - self, - ) -> Result<FixedSizeDescriptorSetBuilder<'a, R>, PersistentDescriptorSetError> { - Ok(FixedSizeDescriptorSetBuilder { - pool: self.pool, - inner: self.inner.add_empty()?, - }) - } - - /// Binds a buffer as the next descriptor. - /// - /// An error is returned if the buffer isn't compatible with the descriptor. - /// - /// # Panic - /// - /// Panics if the buffer doesn't have the same device as the descriptor set layout. - /// - #[inline] - pub fn add_buffer<T>( - self, - buffer: T, - ) -> Result< - FixedSizeDescriptorSetBuilder<'a, (R, PersistentDescriptorSetBuf<T>)>, - PersistentDescriptorSetError, - > - where - T: BufferAccess, - { - Ok(FixedSizeDescriptorSetBuilder { - pool: self.pool, - inner: self.inner.add_buffer(buffer)?, - }) - } - - /// Binds a buffer view as the next descriptor. - /// - /// An error is returned if the buffer isn't compatible with the descriptor. - /// - /// # Panic - /// - /// Panics if the buffer view doesn't have the same device as the descriptor set layout. - /// - pub fn add_buffer_view<T>( - self, - view: T, - ) -> Result< - FixedSizeDescriptorSetBuilder<'a, (R, PersistentDescriptorSetBufView<T>)>, - PersistentDescriptorSetError, - > - where - T: BufferViewRef, - { - Ok(FixedSizeDescriptorSetBuilder { - pool: self.pool, - inner: self.inner.add_buffer_view(view)?, - }) - } - - /// Binds an image view as the next descriptor. - /// - /// An error is returned if the image view isn't compatible with the descriptor. - /// - /// # Panic - /// - /// Panics if the image view doesn't have the same device as the descriptor set layout. - /// - #[inline] - pub fn add_image<T>( - self, - image_view: T, - ) -> Result< - FixedSizeDescriptorSetBuilder<'a, (R, PersistentDescriptorSetImg<T>)>, - PersistentDescriptorSetError, - > - where - T: ImageViewAbstract, - { - Ok(FixedSizeDescriptorSetBuilder { - pool: self.pool, - inner: self.inner.add_image(image_view)?, - }) - } - - /// Binds an image view with a sampler as the next descriptor. - /// - /// An error is returned if the image view isn't compatible with the descriptor. - /// - /// # Panic - /// - /// Panics if the image view or the sampler doesn't have the same device as the descriptor set layout. - /// - #[inline] - pub fn add_sampled_image<T>( - self, - image_view: T, - sampler: Arc<Sampler>, - ) -> Result< - FixedSizeDescriptorSetBuilder< - 'a, - ( - (R, PersistentDescriptorSetImg<T>), - PersistentDescriptorSetSampler, - ), - >, - PersistentDescriptorSetError, - > - where - T: ImageViewAbstract, - { - Ok(FixedSizeDescriptorSetBuilder { - pool: self.pool, - inner: self.inner.add_sampled_image(image_view, sampler)?, - }) - } - - /// Binds a sampler as the next descriptor. - /// - /// An error is returned if the sampler isn't compatible with the descriptor. - /// - /// # Panic - /// - /// Panics if the sampler doesn't have the same device as the descriptor set layout. - /// - #[inline] - pub fn add_sampler( - self, - sampler: Arc<Sampler>, - ) -> Result< - FixedSizeDescriptorSetBuilder<'a, (R, PersistentDescriptorSetSampler)>, - PersistentDescriptorSetError, - > { - Ok(FixedSizeDescriptorSetBuilder { - pool: self.pool, - inner: self.inner.add_sampler(sampler)?, - }) - } -} - -/// Same as `FixedSizeDescriptorSetBuilder`, but we're in an array. -pub struct FixedSizeDescriptorSetBuilderArray<'a, R> { - pool: &'a mut FixedSizeDescriptorSetsPool, - inner: PersistentDescriptorSetBuilderArray<R>, -} - -impl<'a, R> FixedSizeDescriptorSetBuilderArray<'a, R> { - /// Leaves the array. Call this once you added all the elements of the array. - pub fn leave_array( - self, - ) -> Result<FixedSizeDescriptorSetBuilder<'a, R>, PersistentDescriptorSetError> { - Ok(FixedSizeDescriptorSetBuilder { - pool: self.pool, - inner: self.inner.leave_array()?, - }) - } - - /// Binds a buffer as the next element in the array. - /// - /// An error is returned if the buffer isn't compatible with the descriptor. - /// - /// # Panic - /// - /// Panics if the buffer doesn't have the same device as the descriptor set layout. - /// - pub fn add_buffer<T>( - self, - buffer: T, - ) -> Result< - FixedSizeDescriptorSetBuilderArray<'a, (R, PersistentDescriptorSetBuf<T>)>, - PersistentDescriptorSetError, - > - where - T: BufferAccess, - { - Ok(FixedSizeDescriptorSetBuilderArray { - pool: self.pool, - inner: self.inner.add_buffer(buffer)?, - }) - } - - /// Binds a buffer view as the next element in the array. - /// - /// An error is returned if the buffer isn't compatible with the descriptor. - /// - /// # Panic - /// - /// Panics if the buffer view doesn't have the same device as the descriptor set layout. - /// - pub fn add_buffer_view<T>( - self, - view: T, - ) -> Result< - FixedSizeDescriptorSetBuilderArray<'a, (R, PersistentDescriptorSetBufView<T>)>, - PersistentDescriptorSetError, - > - where - T: BufferViewRef, - { - Ok(FixedSizeDescriptorSetBuilderArray { - pool: self.pool, - inner: self.inner.add_buffer_view(view)?, - }) - } - - /// Binds an image view as the next element in the array. - /// - /// An error is returned if the image view isn't compatible with the descriptor. - /// - /// # Panic - /// - /// Panics if the image view doesn't have the same device as the descriptor set layout. - /// - pub fn add_image<T>( - self, - image_view: T, - ) -> Result< - FixedSizeDescriptorSetBuilderArray<'a, (R, PersistentDescriptorSetImg<T>)>, - PersistentDescriptorSetError, - > - where - T: ImageViewAbstract, - { - Ok(FixedSizeDescriptorSetBuilderArray { - pool: self.pool, - inner: self.inner.add_image(image_view)?, - }) - } - - /// Binds an image view with a sampler as the next element in the array. - /// - /// An error is returned if the image view isn't compatible with the descriptor. - /// - /// # Panic - /// - /// Panics if the image or the sampler doesn't have the same device as the descriptor set layout. - /// - pub fn add_sampled_image<T>( - self, - image_view: T, - sampler: Arc<Sampler>, - ) -> Result< - FixedSizeDescriptorSetBuilderArray< - 'a, - ( - (R, PersistentDescriptorSetImg<T>), - PersistentDescriptorSetSampler, - ), - >, - PersistentDescriptorSetError, - > - where - T: ImageViewAbstract, - { - Ok(FixedSizeDescriptorSetBuilderArray { - pool: self.pool, - inner: self.inner.add_sampled_image(image_view, sampler)?, - }) - } - - /// Binds a sampler as the next element in the array. - /// - /// An error is returned if the sampler isn't compatible with the descriptor. - /// - /// # Panic - /// - /// Panics if the sampler doesn't have the same device as the descriptor set layout. - /// - pub fn add_sampler( - self, - sampler: Arc<Sampler>, - ) -> Result< - FixedSizeDescriptorSetBuilderArray<'a, (R, PersistentDescriptorSetSampler)>, - PersistentDescriptorSetError, - > { - Ok(FixedSizeDescriptorSetBuilderArray { - pool: self.pool, - inner: self.inner.add_sampler(sampler)?, - }) - } -} |