aboutsummaryrefslogtreecommitdiff
path: root/src/descriptor_set/persistent.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/descriptor_set/persistent.rs')
-rw-r--r--src/descriptor_set/persistent.rs1315
1 files changed, 82 insertions, 1233 deletions
diff --git a/src/descriptor_set/persistent.rs b/src/descriptor_set/persistent.rs
index c949f88..cfa3f07 100644
--- a/src/descriptor_set/persistent.rs
+++ b/src/descriptor_set/persistent.rs
@@ -18,1287 +18,136 @@
//! > 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<DescriptorSet>`
-//! or a `Arc<DescriptorSet>`.
-//!
-//! # Example
+//! # Examples
//! 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;
+use crate::{
+ descriptor_set::{
+ allocator::{DescriptorSetAlloc, DescriptorSetAllocator, StandardDescriptorSetAlloc},
+ update::WriteDescriptorSet,
+ DescriptorSet, DescriptorSetCreationError, DescriptorSetInner, DescriptorSetLayout,
+ DescriptorSetResources, UnsafeDescriptorSet,
+ },
+ device::{Device, DeviceOwned},
+ VulkanObject,
+};
+use std::{
+ hash::{Hash, Hasher},
+ sync::Arc,
+};
/// A simple, immutable descriptor set that is expected to be long-lived.
-pub struct PersistentDescriptorSet<R, P = StdDescriptorPoolAlloc> {
- inner: P,
- resources: R,
- layout: Arc<DescriptorSetLayout>,
-}
-
-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<DescriptorSetLayout>) -> PersistentDescriptorSetBuilder<()> {
- let cap = layout.num_bindings();
-
- PersistentDescriptorSetBuilder {
- layout,
- binding_id: 0,
- writes: Vec::with_capacity(cap),
- resources: (),
- }
- }
-}
-
-unsafe impl<R, P> DescriptorSet for PersistentDescriptorSet<R, P>
-where
- P: DescriptorPoolAlloc,
- R: PersistentDescriptorSetResources,
-{
- #[inline]
- fn inner(&self) -> &UnsafeDescriptorSet {
- self.inner.inner()
- }
-
- #[inline]
- fn layout(&self) -> &Arc<DescriptorSetLayout> {
- &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<R, P> DeviceOwned for PersistentDescriptorSet<R, P> {
- #[inline]
- fn device(&self) -> &Arc<Device> {
- self.layout.device()
- }
+pub struct PersistentDescriptorSet<P = StandardDescriptorSetAlloc> {
+ alloc: P,
+ inner: DescriptorSetInner,
}
-impl<R, P> PartialEq for PersistentDescriptorSet<R, P>
-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<R, P> Eq for PersistentDescriptorSet<R, P>
-where
- P: DescriptorPoolAlloc,
- R: PersistentDescriptorSetResources,
-{
-}
-
-impl<R, P> Hash for PersistentDescriptorSet<R, P>
-where
- P: DescriptorPoolAlloc,
- R: PersistentDescriptorSetResources,
-{
- #[inline]
- fn hash<H: Hasher>(&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<R> {
- // The descriptor set layout.
- layout: Arc<DescriptorSetLayout>,
- // 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<DescriptorWrite>,
- // Holds the resources alive.
- resources: R,
-}
-
-// TODO: lots of checks are still missing, see the docs of
-// VkDescriptorImageInfo and VkWriteDescriptorSet
-
-impl<R> PersistentDescriptorSetBuilder<R> {
- /// Builds a `PersistentDescriptorSet` from the builder.
- #[inline]
- pub fn build(
- self,
- ) -> Result<PersistentDescriptorSet<R, StdDescriptorPoolAlloc>, 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<P>(
- self,
- pool: &mut P,
- ) -> Result<PersistentDescriptorSet<R, P::Alloc>, 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<PersistentDescriptorSetBuilderArray<R>, 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<PersistentDescriptorSetBuilder<R>, 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<T>(
- self,
- buffer: T,
- ) -> Result<
- PersistentDescriptorSetBuilder<(R, PersistentDescriptorSetBuf<T>)>,
- 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<T>(
- self,
- view: T,
- ) -> Result<
- PersistentDescriptorSetBuilder<(R, PersistentDescriptorSetBufView<T>)>,
- 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.
+impl PersistentDescriptorSet {
+ /// Creates and returns a new descriptor set with a variable descriptor count of 0.
///
+ /// See `new_with_pool` for more.
#[inline]
- pub fn add_image<T>(
- self,
- image_view: T,
- ) -> Result<
- PersistentDescriptorSetBuilder<(R, PersistentDescriptorSetImg<T>)>,
- PersistentDescriptorSetError,
- >
+ pub fn new<A>(
+ allocator: &A,
+ layout: Arc<DescriptorSetLayout>,
+ descriptor_writes: impl IntoIterator<Item = WriteDescriptorSet>,
+ ) -> Result<Arc<PersistentDescriptorSet<A::Alloc>>, DescriptorSetCreationError>
where
- T: ImageViewAbstract,
+ A: DescriptorSetAllocator + ?Sized,
{
- self.enter_array()?.add_image(image_view)?.leave_array()
+ Self::new_variable(allocator, layout, 0, descriptor_writes)
}
- /// 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.
+ /// Creates and returns a new descriptor set with the requested variable descriptor count,
+ /// allocating it from the provided pool.
///
- /// # Panic
+ /// # Panics
///
- /// 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<
- PersistentDescriptorSetBuilder<(
- (R, PersistentDescriptorSetImg<T>),
- PersistentDescriptorSetSampler,
- )>,
- PersistentDescriptorSetError,
- >
+ /// - Panics if `layout` was created for push descriptors rather than descriptor sets.
+ /// - Panics if `variable_descriptor_count` is too large for the given `layout`.
+ pub fn new_variable<A>(
+ allocator: &A,
+ layout: Arc<DescriptorSetLayout>,
+ variable_descriptor_count: u32,
+ descriptor_writes: impl IntoIterator<Item = WriteDescriptorSet>,
+ ) -> Result<Arc<PersistentDescriptorSet<A::Alloc>>, DescriptorSetCreationError>
where
- T: ImageViewAbstract,
+ A: DescriptorSetAllocator + ?Sized,
{
- 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<Sampler>,
- ) -> 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<R> {
- // The original builder.
- builder: PersistentDescriptorSetBuilder<R>,
- // Current array elements.
- array_element: usize,
- // Description of the descriptor.
- desc: DescriptorDesc,
-}
-
-impl<R> PersistentDescriptorSetBuilderArray<R> {
- /// Leaves the array. Call this once you added all the elements of the array.
- pub fn leave_array(
- mut self,
- ) -> Result<PersistentDescriptorSetBuilder<R>, 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<T>(
- mut self,
- buffer: T,
- ) -> Result<
- PersistentDescriptorSetBuilderArray<(R, PersistentDescriptorSetBuf<T>)>,
- PersistentDescriptorSetError,
- >
- where
- T: BufferAccess,
- {
- assert_eq!(
- self.builder.layout.device().internal_object(),
- buffer.inner().buffer.device().internal_object()
+ assert!(
+ !layout.push_descriptor(),
+ "the provided descriptor set layout is for push descriptors, and cannot be used to \
+ build a descriptor set 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,
- ));
- }
+ let max_count = layout.variable_descriptor_count();
- 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<T>(
- mut self,
- view: T,
- ) -> Result<
- PersistentDescriptorSetBuilderArray<(R, PersistentDescriptorSetBufView<T>)>,
- PersistentDescriptorSetError,
- >
- where
- T: BufferViewRef,
- {
- assert_eq!(
- self.builder.layout.device().internal_object(),
- view.view().device().internal_object()
+ assert!(
+ variable_descriptor_count <= max_count,
+ "the provided variable_descriptor_count ({}) is greater than the maximum number of \
+ variable count descriptors in the set ({})",
+ variable_descriptor_count,
+ max_count,
);
- 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<T>(
- mut self,
- image_view: T,
- ) -> Result<
- PersistentDescriptorSetBuilderArray<(R, PersistentDescriptorSetImg<T>)>,
- 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<T>(
- mut self,
- image_view: T,
- sampler: Arc<Sampler>,
- ) -> Result<
- PersistentDescriptorSetBuilderArray<(
- (R, PersistentDescriptorSetImg<T>),
- 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<Sampler>,
- ) -> 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<I>(
- 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
- }
+ let alloc = allocator.allocate(&layout, variable_descriptor_count)?;
+ let inner = DescriptorSetInner::new(
+ alloc.inner().handle(),
+ layout,
+ variable_descriptor_count,
+ descriptor_writes,
+ )?;
- #[inline]
- fn image(&self, _: usize) -> Option<(&dyn ImageViewAbstract, u32)> {
- None
+ Ok(Arc::new(PersistentDescriptorSet { alloc, inner }))
}
}
-/// Internal object related to the `PersistentDescriptorSet` system.
-pub struct PersistentDescriptorSetBuf<B> {
- buffer: B,
- descriptor_num: u32,
-}
-
-unsafe impl<R, B> PersistentDescriptorSetResources for (R, PersistentDescriptorSetBuf<B>)
+unsafe impl<P> DescriptorSet for PersistentDescriptorSet<P>
where
- R: PersistentDescriptorSetResources,
- B: BufferAccess,
+ P: DescriptorSetAlloc,
{
- #[inline]
- fn num_buffers(&self) -> usize {
- self.0.num_buffers() + 1
+ fn inner(&self) -> &UnsafeDescriptorSet {
+ self.alloc.inner()
}
- #[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
- }
+ fn layout(&self) -> &Arc<DescriptorSetLayout> {
+ self.inner.layout()
}
- #[inline]
- fn num_images(&self) -> usize {
- self.0.num_images()
+ fn variable_descriptor_count(&self) -> u32 {
+ self.inner.variable_descriptor_count
}
- #[inline]
- fn image(&self, index: usize) -> Option<(&dyn ImageViewAbstract, u32)> {
- self.0.image(index)
+ fn resources(&self) -> &DescriptorSetResources {
+ self.inner.resources()
}
}
-/// Internal object related to the `PersistentDescriptorSet` system.
-pub struct PersistentDescriptorSetBufView<V>
+unsafe impl<P> DeviceOwned for PersistentDescriptorSet<P>
where
- V: BufferViewRef,
+ P: DescriptorSetAlloc,
{
- view: V,
- descriptor_num: u32,
-}
-
-unsafe impl<R, V> PersistentDescriptorSetResources for (R, PersistentDescriptorSetBufView<V>)
-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)
+ fn device(&self) -> &Arc<Device> {
+ self.inner.layout().device()
}
}
-/// Internal object related to the `PersistentDescriptorSet` system.
-pub struct PersistentDescriptorSetImg<I> {
- image: I,
- descriptor_num: u32,
-}
-
-unsafe impl<R, I> PersistentDescriptorSetResources for (R, PersistentDescriptorSetImg<I>)
+impl<P> PartialEq for PersistentDescriptorSet<P>
where
- R: PersistentDescriptorSetResources,
- I: ImageViewAbstract,
+ P: DescriptorSetAlloc,
{
- #[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
- }
+ fn eq(&self, other: &Self) -> bool {
+ self.inner() == other.inner()
}
}
-/// Internal object related to the `PersistentDescriptorSet` system.
-pub struct PersistentDescriptorSetSampler {
- sampler: Arc<Sampler>,
-}
+impl<P> Eq for PersistentDescriptorSet<P> where P: DescriptorSetAlloc {}
-unsafe impl<R> PersistentDescriptorSetResources for (R, PersistentDescriptorSetSampler)
+impl<P> Hash for PersistentDescriptorSet<P>
where
- R: PersistentDescriptorSetResources,
+ P: DescriptorSetAlloc,
{
- #[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<OomError> 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",
- }
- )
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ self.inner().hash(state);
}
}