// Copyright (c) 2017 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. //! A simple, immutable descriptor set that is expected to be long-lived. //! //! Creating a persistent descriptor set allocates from a pool, and can't be modified once created. //! You are therefore encouraged to create them at initialization and not the during //! performance-critical paths. //! //! > **Note**: You can control of the pool that is used to create the descriptor set, if you wish //! > so. By creating a implementation of the `DescriptorPool` trait that doesn't perform any //! > actual allocation, you can skip this allocation and make it acceptable to use a persistent //! > descriptor set in performance-critical paths.. //! //! The template parameter of the `PersistentDescriptorSet` is complex, and you shouldn't try to //! express it explicitly. If you want to store your descriptor set in a struct or in a `Vec` for //! example, you are encouraged to turn the `PersistentDescriptorSet` into a `Box` //! or a `Arc`. //! //! # Example //! TODO: use crate::buffer::BufferAccess; use crate::buffer::BufferViewRef; use crate::descriptor_set::layout::DescriptorDesc; use crate::descriptor_set::layout::DescriptorDescTy; use crate::descriptor_set::layout::DescriptorImageDesc; use crate::descriptor_set::layout::DescriptorImageDescArray; use crate::descriptor_set::layout::DescriptorImageDescDimensions; use crate::descriptor_set::layout::DescriptorSetLayout; use crate::descriptor_set::layout::DescriptorType; use crate::descriptor_set::pool::standard::StdDescriptorPoolAlloc; use crate::descriptor_set::pool::DescriptorPool; use crate::descriptor_set::pool::DescriptorPoolAlloc; use crate::descriptor_set::sys::DescriptorWrite; use crate::descriptor_set::DescriptorSet; use crate::descriptor_set::UnsafeDescriptorSet; use crate::device::Device; use crate::device::DeviceOwned; use crate::format::Format; use crate::image::view::ImageViewAbstract; use crate::image::SampleCount; use crate::sampler::Sampler; use crate::OomError; use crate::VulkanObject; use std::error; use std::fmt; use std::hash::Hash; use std::hash::Hasher; use std::sync::Arc; /// A simple, immutable descriptor set that is expected to be long-lived. pub struct PersistentDescriptorSet { inner: P, resources: R, layout: Arc, } impl PersistentDescriptorSet<()> { /// Starts the process of building a `PersistentDescriptorSet`. Returns a builder. /// /// # Panic /// /// - Panics if the set id is out of range. /// pub fn start(layout: Arc) -> PersistentDescriptorSetBuilder<()> { let cap = layout.num_bindings(); PersistentDescriptorSetBuilder { layout, binding_id: 0, writes: Vec::with_capacity(cap), resources: (), } } } unsafe impl DescriptorSet for PersistentDescriptorSet where P: DescriptorPoolAlloc, R: PersistentDescriptorSetResources, { #[inline] fn inner(&self) -> &UnsafeDescriptorSet { self.inner.inner() } #[inline] fn layout(&self) -> &Arc { &self.layout } #[inline] fn num_buffers(&self) -> usize { self.resources.num_buffers() } #[inline] fn buffer(&self, index: usize) -> Option<(&dyn BufferAccess, u32)> { self.resources.buffer(index) } #[inline] fn num_images(&self) -> usize { self.resources.num_images() } #[inline] fn image(&self, index: usize) -> Option<(&dyn ImageViewAbstract, u32)> { self.resources.image(index) } } unsafe impl DeviceOwned for PersistentDescriptorSet { #[inline] fn device(&self) -> &Arc { self.layout.device() } } impl PartialEq for PersistentDescriptorSet where P: DescriptorPoolAlloc, R: PersistentDescriptorSetResources, { #[inline] fn eq(&self, other: &Self) -> bool { self.inner().internal_object() == other.inner().internal_object() && self.device() == other.device() } } impl Eq for PersistentDescriptorSet where P: DescriptorPoolAlloc, R: PersistentDescriptorSetResources, { } impl Hash for PersistentDescriptorSet where P: DescriptorPoolAlloc, R: PersistentDescriptorSetResources, { #[inline] fn hash(&self, state: &mut H) { self.inner().internal_object().hash(state); self.device().hash(state); } } /// Prototype of a `PersistentDescriptorSet`. /// /// The template parameter `R` is an unspecified type that represents the list of resources. /// /// See the docs of `PersistentDescriptorSet` for an example. pub struct PersistentDescriptorSetBuilder { // The descriptor set layout. layout: Arc, // Binding currently being filled. binding_id: usize, // The writes to perform on a descriptor set in order to put the resources in it. writes: Vec, // Holds the resources alive. resources: R, } // TODO: lots of checks are still missing, see the docs of // VkDescriptorImageInfo and VkWriteDescriptorSet impl PersistentDescriptorSetBuilder { /// Builds a `PersistentDescriptorSet` from the builder. #[inline] pub fn build( self, ) -> Result, PersistentDescriptorSetBuildError> { let mut pool = Device::standard_descriptor_pool(self.layout.device()); self.build_with_pool(&mut pool) } /// Builds a `PersistentDescriptorSet` from the builder. /// /// # Panic /// /// Panics if the pool doesn't have the same device as the descriptor set layout. /// pub fn build_with_pool

( self, pool: &mut P, ) -> Result, PersistentDescriptorSetBuildError> where P: ?Sized + DescriptorPool, { assert_eq!( self.layout.device().internal_object(), pool.device().internal_object() ); let expected_desc = self.layout.num_bindings(); if expected_desc > self.binding_id { return Err(PersistentDescriptorSetBuildError::MissingDescriptors { expected: expected_desc as u32, obtained: self.binding_id as u32, }); } debug_assert_eq!(expected_desc, self.binding_id); let set = unsafe { let mut set = pool.alloc(&self.layout)?; set.inner_mut() .write(pool.device(), self.writes.into_iter()); set }; Ok(PersistentDescriptorSet { inner: set, resources: self.resources, layout: self.layout, }) } /// 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, PersistentDescriptorSetError> { let desc = match self.layout.descriptor(self.binding_id) { Some(d) => d, None => return Err(PersistentDescriptorSetError::EmptyExpected), }; Ok(PersistentDescriptorSetBuilderArray { builder: self, desc, array_element: 0, }) } /// Skips the current descriptor if it is empty. #[inline] pub fn add_empty( mut self, ) -> Result, PersistentDescriptorSetError> { match self.layout.descriptor(self.binding_id) { None => (), Some(desc) => { return Err(PersistentDescriptorSetError::WrongDescriptorTy { expected: desc.ty.ty(), }) } } self.binding_id += 1; Ok(self) } /// 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( self, buffer: T, ) -> Result< PersistentDescriptorSetBuilder<(R, PersistentDescriptorSetBuf)>, PersistentDescriptorSetError, > where T: BufferAccess, { self.enter_array()?.add_buffer(buffer)?.leave_array() } /// 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( self, view: T, ) -> Result< PersistentDescriptorSetBuilder<(R, PersistentDescriptorSetBufView)>, PersistentDescriptorSetError, > where T: BufferViewRef, { self.enter_array()?.add_buffer_view(view)?.leave_array() } /// 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( self, image_view: T, ) -> Result< PersistentDescriptorSetBuilder<(R, PersistentDescriptorSetImg)>, PersistentDescriptorSetError, > where T: ImageViewAbstract, { self.enter_array()?.add_image(image_view)?.leave_array() } /// 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( self, image_view: T, sampler: Arc, ) -> Result< PersistentDescriptorSetBuilder<( (R, PersistentDescriptorSetImg), PersistentDescriptorSetSampler, )>, PersistentDescriptorSetError, > where T: ImageViewAbstract, { self.enter_array()? .add_sampled_image(image_view, sampler)? .leave_array() } /// 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, ) -> Result< PersistentDescriptorSetBuilder<(R, PersistentDescriptorSetSampler)>, PersistentDescriptorSetError, > { self.enter_array()?.add_sampler(sampler)?.leave_array() } } /// Same as `PersistentDescriptorSetBuilder`, but we're in an array. pub struct PersistentDescriptorSetBuilderArray { // The original builder. builder: PersistentDescriptorSetBuilder, // Current array elements. array_element: usize, // Description of the descriptor. desc: DescriptorDesc, } impl PersistentDescriptorSetBuilderArray { /// Leaves the array. Call this once you added all the elements of the array. pub fn leave_array( mut self, ) -> Result, PersistentDescriptorSetError> { if self.desc.array_count > self.array_element as u32 { return Err(PersistentDescriptorSetError::MissingArrayElements { expected: self.desc.array_count, obtained: self.array_element as u32, }); } debug_assert_eq!(self.desc.array_count, self.array_element as u32); self.builder.binding_id += 1; Ok(self.builder) } /// 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( mut self, buffer: T, ) -> Result< PersistentDescriptorSetBuilderArray<(R, PersistentDescriptorSetBuf)>, PersistentDescriptorSetError, > where T: BufferAccess, { assert_eq!( self.builder.layout.device().internal_object(), buffer.inner().buffer.device().internal_object() ); if self.array_element as u32 >= self.desc.array_count { return Err(PersistentDescriptorSetError::ArrayOutOfBounds); } self.builder.writes.push(match self.desc.ty { DescriptorDescTy::Buffer(ref buffer_desc) => { // Note that the buffer content is not checked. This is technically not unsafe as // long as the data in the buffer has no invalid memory representation (ie. no // bool, no enum, no pointer, no str) and as long as the robust buffer access // feature is enabled. // TODO: this is not checked ^ // TODO: eventually shouldn't be an assert ; for now robust_buffer_access is always // enabled so this assert should never fail in practice, but we put it anyway // in case we forget to adjust this code assert!( self.builder .layout .device() .enabled_features() .robust_buffer_access ); if buffer_desc.storage { if !buffer.inner().buffer.usage().storage_buffer { return Err(PersistentDescriptorSetError::MissingBufferUsage( MissingBufferUsage::StorageBuffer, )); } unsafe { DescriptorWrite::storage_buffer( self.builder.binding_id as u32, self.array_element as u32, &buffer, ) } } else { if !buffer.inner().buffer.usage().uniform_buffer { return Err(PersistentDescriptorSetError::MissingBufferUsage( MissingBufferUsage::UniformBuffer, )); } if buffer_desc.dynamic.unwrap_or(false) { unsafe { DescriptorWrite::dynamic_uniform_buffer( self.builder.binding_id as u32, self.array_element as u32, &buffer, ) } } else { unsafe { DescriptorWrite::uniform_buffer( self.builder.binding_id as u32, self.array_element as u32, &buffer, ) } } } } ref d => { return Err(PersistentDescriptorSetError::WrongDescriptorTy { expected: d.ty() }); } }); Ok(PersistentDescriptorSetBuilderArray { builder: PersistentDescriptorSetBuilder { layout: self.builder.layout, binding_id: self.builder.binding_id, writes: self.builder.writes, resources: ( self.builder.resources, PersistentDescriptorSetBuf { buffer, descriptor_num: self.builder.binding_id as u32, }, ), }, desc: self.desc, array_element: self.array_element + 1, }) } /// 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( mut self, view: T, ) -> Result< PersistentDescriptorSetBuilderArray<(R, PersistentDescriptorSetBufView)>, PersistentDescriptorSetError, > where T: BufferViewRef, { assert_eq!( self.builder.layout.device().internal_object(), view.view().device().internal_object() ); if self.array_element as u32 >= self.desc.array_count { return Err(PersistentDescriptorSetError::ArrayOutOfBounds); } self.builder.writes.push(match self.desc.ty { DescriptorDescTy::TexelBuffer { storage, .. } => { if storage { // TODO: storage_texel_buffer_atomic if !view.view().storage_texel_buffer() { return Err(PersistentDescriptorSetError::MissingBufferUsage( MissingBufferUsage::StorageTexelBuffer, )); } DescriptorWrite::storage_texel_buffer( self.builder.binding_id as u32, self.array_element as u32, view.view(), ) } else { if !view.view().uniform_texel_buffer() { return Err(PersistentDescriptorSetError::MissingBufferUsage( MissingBufferUsage::UniformTexelBuffer, )); } DescriptorWrite::uniform_texel_buffer( self.builder.binding_id as u32, self.array_element as u32, view.view(), ) } } ref d => { return Err(PersistentDescriptorSetError::WrongDescriptorTy { expected: d.ty() }); } }); Ok(PersistentDescriptorSetBuilderArray { builder: PersistentDescriptorSetBuilder { layout: self.builder.layout, binding_id: self.builder.binding_id, writes: self.builder.writes, resources: ( self.builder.resources, PersistentDescriptorSetBufView { view, descriptor_num: self.builder.binding_id as u32, }, ), }, desc: self.desc, array_element: self.array_element + 1, }) } /// 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( mut self, image_view: T, ) -> Result< PersistentDescriptorSetBuilderArray<(R, PersistentDescriptorSetImg)>, PersistentDescriptorSetError, > where T: ImageViewAbstract, { assert_eq!( self.builder.layout.device().internal_object(), image_view.image().inner().image.device().internal_object() ); if self.array_element as u32 >= self.desc.array_count { return Err(PersistentDescriptorSetError::ArrayOutOfBounds); } let desc = match self.builder.layout.descriptor(self.builder.binding_id) { Some(d) => d, None => return Err(PersistentDescriptorSetError::EmptyExpected), }; self.builder.writes.push(match desc.ty { DescriptorDescTy::Image(ref desc) => { image_match_desc(&image_view, &desc)?; if desc.sampled { DescriptorWrite::sampled_image( self.builder.binding_id as u32, self.array_element as u32, &image_view, ) } else { if !image_view.component_mapping().is_identity() { return Err(PersistentDescriptorSetError::NotIdentitySwizzled); } DescriptorWrite::storage_image( self.builder.binding_id as u32, self.array_element as u32, &image_view, ) } } DescriptorDescTy::InputAttachment { multisampled, array_layers, } => { if !image_view.image().inner().image.usage().input_attachment { return Err(PersistentDescriptorSetError::MissingImageUsage( MissingImageUsage::InputAttachment, )); } if !image_view.component_mapping().is_identity() { return Err(PersistentDescriptorSetError::NotIdentitySwizzled); } if multisampled && image_view.image().samples() == SampleCount::Sample1 { return Err(PersistentDescriptorSetError::ExpectedMultisampled); } else if !multisampled && image_view.image().samples() != SampleCount::Sample1 { return Err(PersistentDescriptorSetError::UnexpectedMultisampled); } let image_layers = image_view.array_layers(); let num_layers = image_layers.end - image_layers.start; match array_layers { DescriptorImageDescArray::NonArrayed => { if num_layers != 1 { return Err(PersistentDescriptorSetError::ArrayLayersMismatch { expected: 1, obtained: num_layers, }); } } DescriptorImageDescArray::Arrayed { max_layers: Some(max_layers), } => { if num_layers > max_layers { // TODO: is this correct? "max" layers? or is it in fact min layers? return Err(PersistentDescriptorSetError::ArrayLayersMismatch { expected: max_layers, obtained: num_layers, }); } } DescriptorImageDescArray::Arrayed { max_layers: None } => {} }; DescriptorWrite::input_attachment( self.builder.binding_id as u32, self.array_element as u32, &image_view, ) } ty => { return Err(PersistentDescriptorSetError::WrongDescriptorTy { expected: ty.ty() }); } }); Ok(PersistentDescriptorSetBuilderArray { builder: PersistentDescriptorSetBuilder { layout: self.builder.layout, binding_id: self.builder.binding_id, writes: self.builder.writes, resources: ( self.builder.resources, PersistentDescriptorSetImg { image: image_view, descriptor_num: self.builder.binding_id as u32, }, ), }, desc: self.desc, array_element: self.array_element + 1, }) } /// 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( mut self, image_view: T, sampler: Arc, ) -> Result< PersistentDescriptorSetBuilderArray<( (R, PersistentDescriptorSetImg), PersistentDescriptorSetSampler, )>, PersistentDescriptorSetError, > where T: ImageViewAbstract, { assert_eq!( self.builder.layout.device().internal_object(), image_view.image().inner().image.device().internal_object() ); assert_eq!( self.builder.layout.device().internal_object(), sampler.device().internal_object() ); if self.array_element as u32 >= self.desc.array_count { return Err(PersistentDescriptorSetError::ArrayOutOfBounds); } let desc = match self.builder.layout.descriptor(self.builder.binding_id) { Some(d) => d, None => return Err(PersistentDescriptorSetError::EmptyExpected), }; if !image_view.can_be_sampled(&sampler) { return Err(PersistentDescriptorSetError::IncompatibleImageViewSampler); } self.builder.writes.push(match desc.ty { DescriptorDescTy::CombinedImageSampler(ref desc) => { image_match_desc(&image_view, &desc)?; DescriptorWrite::combined_image_sampler( self.builder.binding_id as u32, self.array_element as u32, &sampler, &image_view, ) } ty => { return Err(PersistentDescriptorSetError::WrongDescriptorTy { expected: ty.ty() }); } }); Ok(PersistentDescriptorSetBuilderArray { builder: PersistentDescriptorSetBuilder { layout: self.builder.layout, binding_id: self.builder.binding_id, writes: self.builder.writes, resources: ( ( self.builder.resources, PersistentDescriptorSetImg { image: image_view, descriptor_num: self.builder.binding_id as u32, }, ), PersistentDescriptorSetSampler { sampler }, ), }, desc: self.desc, array_element: self.array_element + 1, }) } /// 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( mut self, sampler: Arc, ) -> Result< PersistentDescriptorSetBuilderArray<(R, PersistentDescriptorSetSampler)>, PersistentDescriptorSetError, > { assert_eq!( self.builder.layout.device().internal_object(), sampler.device().internal_object() ); if self.array_element as u32 >= self.desc.array_count { return Err(PersistentDescriptorSetError::ArrayOutOfBounds); } let desc = match self.builder.layout.descriptor(self.builder.binding_id) { Some(d) => d, None => return Err(PersistentDescriptorSetError::EmptyExpected), }; self.builder.writes.push(match desc.ty { DescriptorDescTy::Sampler => DescriptorWrite::sampler( self.builder.binding_id as u32, self.array_element as u32, &sampler, ), ty => { return Err(PersistentDescriptorSetError::WrongDescriptorTy { expected: ty.ty() }); } }); Ok(PersistentDescriptorSetBuilderArray { builder: PersistentDescriptorSetBuilder { layout: self.builder.layout, binding_id: self.builder.binding_id, writes: self.builder.writes, resources: ( self.builder.resources, PersistentDescriptorSetSampler { sampler }, ), }, desc: self.desc, array_element: self.array_element + 1, }) } } // Checks whether an image view matches the descriptor. fn image_match_desc( image_view: &I, desc: &DescriptorImageDesc, ) -> Result<(), PersistentDescriptorSetError> where I: ?Sized + ImageViewAbstract, { if desc.sampled && !image_view.image().inner().image.usage().sampled { return Err(PersistentDescriptorSetError::MissingImageUsage( MissingImageUsage::Sampled, )); } else if !desc.sampled && !image_view.image().inner().image.usage().storage { return Err(PersistentDescriptorSetError::MissingImageUsage( MissingImageUsage::Storage, )); } let image_view_ty = DescriptorImageDescDimensions::from_image_view_type(image_view.ty()); if image_view_ty != desc.dimensions { return Err(PersistentDescriptorSetError::ImageViewTypeMismatch { expected: desc.dimensions, obtained: image_view_ty, }); } if let Some(format) = desc.format { if image_view.format() != format { return Err(PersistentDescriptorSetError::ImageViewFormatMismatch { expected: format, obtained: image_view.format(), }); } } if desc.multisampled && image_view.image().samples() == SampleCount::Sample1 { return Err(PersistentDescriptorSetError::ExpectedMultisampled); } else if !desc.multisampled && image_view.image().samples() != SampleCount::Sample1 { return Err(PersistentDescriptorSetError::UnexpectedMultisampled); } let image_layers = image_view.array_layers(); let num_layers = image_layers.end - image_layers.start; match desc.array_layers { DescriptorImageDescArray::NonArrayed => { // TODO: when a non-array is expected, can we pass an image view that is in fact an // array with one layer? need to check let required_layers = if desc.dimensions == DescriptorImageDescDimensions::Cube { 6 } else { 1 }; if num_layers != required_layers { return Err(PersistentDescriptorSetError::ArrayLayersMismatch { expected: 1, obtained: num_layers, }); } } DescriptorImageDescArray::Arrayed { max_layers: Some(max_layers), } => { let required_layers = if desc.dimensions == DescriptorImageDescDimensions::Cube { max_layers * 6 } else { max_layers }; // TODO: is this correct? "max" layers? or is it in fact min layers? if num_layers > required_layers { return Err(PersistentDescriptorSetError::ArrayLayersMismatch { expected: max_layers, obtained: num_layers, }); } } DescriptorImageDescArray::Arrayed { max_layers: None } => {} }; Ok(()) } pub unsafe trait PersistentDescriptorSetResources { fn num_buffers(&self) -> usize; fn buffer(&self, index: usize) -> Option<(&dyn BufferAccess, u32)>; fn num_images(&self) -> usize; fn image(&self, index: usize) -> Option<(&dyn ImageViewAbstract, u32)>; } unsafe impl PersistentDescriptorSetResources for () { #[inline] fn num_buffers(&self) -> usize { 0 } #[inline] fn buffer(&self, _: usize) -> Option<(&dyn BufferAccess, u32)> { None } #[inline] fn num_images(&self) -> usize { 0 } #[inline] fn image(&self, _: usize) -> Option<(&dyn ImageViewAbstract, u32)> { None } } /// Internal object related to the `PersistentDescriptorSet` system. pub struct PersistentDescriptorSetBuf { buffer: B, descriptor_num: u32, } unsafe impl PersistentDescriptorSetResources for (R, PersistentDescriptorSetBuf) where R: PersistentDescriptorSetResources, B: BufferAccess, { #[inline] fn num_buffers(&self) -> usize { self.0.num_buffers() + 1 } #[inline] fn buffer(&self, index: usize) -> Option<(&dyn BufferAccess, u32)> { if let Some(buf) = self.0.buffer(index) { Some(buf) } else if index == self.0.num_buffers() { Some((&self.1.buffer, self.1.descriptor_num)) } else { None } } #[inline] fn num_images(&self) -> usize { self.0.num_images() } #[inline] fn image(&self, index: usize) -> Option<(&dyn ImageViewAbstract, u32)> { self.0.image(index) } } /// Internal object related to the `PersistentDescriptorSet` system. pub struct PersistentDescriptorSetBufView where V: BufferViewRef, { view: V, descriptor_num: u32, } unsafe impl PersistentDescriptorSetResources for (R, PersistentDescriptorSetBufView) where R: PersistentDescriptorSetResources, V: BufferViewRef, { #[inline] fn num_buffers(&self) -> usize { self.0.num_buffers() + 1 } #[inline] fn buffer(&self, index: usize) -> Option<(&dyn BufferAccess, u32)> { if let Some(buf) = self.0.buffer(index) { Some(buf) } else if index == self.0.num_buffers() { Some((self.1.view.view().buffer(), self.1.descriptor_num)) } else { None } } #[inline] fn num_images(&self) -> usize { self.0.num_images() } #[inline] fn image(&self, index: usize) -> Option<(&dyn ImageViewAbstract, u32)> { self.0.image(index) } } /// Internal object related to the `PersistentDescriptorSet` system. pub struct PersistentDescriptorSetImg { image: I, descriptor_num: u32, } unsafe impl PersistentDescriptorSetResources for (R, PersistentDescriptorSetImg) where R: PersistentDescriptorSetResources, I: ImageViewAbstract, { #[inline] fn num_buffers(&self) -> usize { self.0.num_buffers() } #[inline] fn buffer(&self, index: usize) -> Option<(&dyn BufferAccess, u32)> { self.0.buffer(index) } #[inline] fn num_images(&self) -> usize { self.0.num_images() + 1 } #[inline] fn image(&self, index: usize) -> Option<(&dyn ImageViewAbstract, u32)> { if let Some(img) = self.0.image(index) { Some(img) } else if index == self.0.num_images() { Some((&self.1.image, self.1.descriptor_num)) } else { None } } } /// Internal object related to the `PersistentDescriptorSet` system. pub struct PersistentDescriptorSetSampler { sampler: Arc, } unsafe impl PersistentDescriptorSetResources for (R, PersistentDescriptorSetSampler) where R: PersistentDescriptorSetResources, { #[inline] fn num_buffers(&self) -> usize { self.0.num_buffers() } #[inline] fn buffer(&self, index: usize) -> Option<(&dyn BufferAccess, u32)> { self.0.buffer(index) } #[inline] fn num_images(&self) -> usize { self.0.num_images() } #[inline] fn image(&self, index: usize) -> Option<(&dyn ImageViewAbstract, u32)> { self.0.image(index) } } // Part of the PersistentDescriptorSetError for the case // of missing usage on a buffer. #[derive(Debug, Clone)] pub enum MissingBufferUsage { StorageBuffer, UniformBuffer, StorageTexelBuffer, UniformTexelBuffer, } // Part of the PersistentDescriptorSetError for the case // of missing usage on an image. #[derive(Debug, Clone)] pub enum MissingImageUsage { InputAttachment, Sampled, Storage, } /// Error related to the persistent descriptor set. #[derive(Debug, Clone)] pub enum PersistentDescriptorSetError { /// The number of array layers of an image doesn't match what was expected. ArrayLayersMismatch { /// Number of expected array layers for the image. expected: u32, /// Number of array layers of the image that was added. obtained: u32, }, /// Tried to add too many elements to an array. ArrayOutOfBounds, /// Expected nothing. EmptyExpected, /// Expected a multisampled image, but got a single-sampled image. ExpectedMultisampled, /// The format of an image view doesn't match what was expected. ImageViewFormatMismatch { /// Expected format. expected: Format, /// Format of the image view that was passed. obtained: Format, }, /// The type of an image view doesn't match what was expected. ImageViewTypeMismatch { /// Expected type. expected: DescriptorImageDescDimensions, /// Type of the image view that was passed. obtained: DescriptorImageDescDimensions, }, /// The image view isn't compatible with the sampler. IncompatibleImageViewSampler, /// Didn't fill all the elements of an array before leaving. MissingArrayElements { /// Number of expected elements. expected: u32, /// Number of elements that were added. obtained: u32, }, /// The buffer is missing the correct usage. MissingBufferUsage(MissingBufferUsage), /// The image is missing the correct usage. MissingImageUsage(MissingImageUsage), /// The image view has a component swizzle that is different from identity. NotIdentitySwizzled, /// Expected a single-sampled image, but got a multisampled image. UnexpectedMultisampled, /// Expected one type of resource but got another. WrongDescriptorTy { /// The expected descriptor type. expected: DescriptorType, }, } impl error::Error for PersistentDescriptorSetError {} impl fmt::Display for PersistentDescriptorSetError { #[inline] fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { write!( fmt, "{}", match *self { PersistentDescriptorSetError::ArrayLayersMismatch { .. } => { "the number of array layers of an image doesn't match what was expected" } PersistentDescriptorSetError::ArrayOutOfBounds => { "tried to add too many elements to an array" } PersistentDescriptorSetError::EmptyExpected => { "expected an empty descriptor but got something" } PersistentDescriptorSetError::ExpectedMultisampled => { "expected a multisampled image, but got a single-sampled image" } PersistentDescriptorSetError::ImageViewFormatMismatch { .. } => { "the format of an image view doesn't match what was expected" } PersistentDescriptorSetError::ImageViewTypeMismatch { .. } => { "the type of an image view doesn't match what was expected" } PersistentDescriptorSetError::IncompatibleImageViewSampler => { "the image view isn't compatible with the sampler" } PersistentDescriptorSetError::MissingArrayElements { .. } => { "didn't fill all the elements of an array before leaving" } PersistentDescriptorSetError::MissingBufferUsage { .. } => { "the buffer is missing the correct usage" } PersistentDescriptorSetError::MissingImageUsage { .. } => { "the image is missing the correct usage" } PersistentDescriptorSetError::NotIdentitySwizzled => { "the image view's component mapping is not identity swizzled" } PersistentDescriptorSetError::UnexpectedMultisampled => { "expected a single-sampled image, but got a multisampled image" } PersistentDescriptorSetError::WrongDescriptorTy { .. } => { "expected one type of resource but got another" } } ) } } /// Error when building a persistent descriptor set. #[derive(Debug, Clone)] pub enum PersistentDescriptorSetBuildError { /// Out of memory. OomError(OomError), /// Didn't fill all the descriptors before building. MissingDescriptors { /// Number of expected descriptors. expected: u32, /// Number of descriptors that were added. obtained: u32, }, } impl error::Error for PersistentDescriptorSetBuildError {} impl From for PersistentDescriptorSetBuildError { #[inline] fn from(err: OomError) -> PersistentDescriptorSetBuildError { PersistentDescriptorSetBuildError::OomError(err) } } impl fmt::Display for PersistentDescriptorSetBuildError { #[inline] fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { write!( fmt, "{}", match *self { PersistentDescriptorSetBuildError::MissingDescriptors { .. } => { "didn't fill all the descriptors before building" } PersistentDescriptorSetBuildError::OomError(_) => "not enough memory available", } ) } }