1 // Copyright (c) 2017 The vulkano developers
2 // Licensed under the Apache License, Version 2.0
3 // <LICENSE-APACHE or
4 // https://www.apache.org/licenses/LICENSE-2.0> or the MIT
5 // license <LICENSE-MIT or https://opensource.org/licenses/MIT>,
6 // at your option. All files in the project carrying such
7 // notice may not be copied, modified, or distributed except
8 // according to those terms.
9 
10 use super::layout::{DescriptorSetLayout, DescriptorSetLayoutBinding, DescriptorType};
11 use crate::{
12     buffer::{view::BufferView, BufferUsage, Subbuffer},
13     device::DeviceOwned,
14     image::{view::ImageViewType, ImageAspects, ImageType, ImageUsage, ImageViewAbstract},
15     sampler::{Sampler, SamplerImageViewIncompatibleError},
16     DeviceSize, RequiresOneOf, VulkanObject,
17 };
18 use smallvec::SmallVec;
19 use std::{
20     error::Error,
21     fmt::{Display, Error as FmtError, Formatter},
22     ops::Range,
23     ptr,
24     sync::Arc,
25 };
26 
27 /// Represents a single write operation to the binding of a descriptor set.
28 ///
29 /// `WriteDescriptorSet` specifies the binding number and target array index, and includes one or
30 /// more resources of a given type that need to be written to that location. Two constructors are
31 /// provided for each resource type:
32 /// - The basic constructor variant writes a single element to array index 0. It is intended for
33 ///   non-arrayed bindings, where `descriptor_count` in the descriptor set layout is 1.
34 /// - The `_array` variant writes several elements and allows specifying the target array index.
35 ///   At least one element must be provided; a panic results if the provided iterator is empty.
36 pub struct WriteDescriptorSet {
37     binding: u32,
38     first_array_element: u32,
39     elements: WriteDescriptorSetElements,
40 }
41 
42 impl WriteDescriptorSet {
43     /// Write an empty element to array element 0.
44     ///
45     /// This is used for push descriptors in combination with `Sampler` descriptors that have
46     /// immutable samplers in the layout. The Vulkan spec requires these elements to be explicitly
47     /// written, but since there is no data to write, a dummy write is provided instead.
48     ///
49     /// For regular descriptor sets, the data for such descriptors is automatically valid, and dummy
50     /// writes are not allowed.
51     #[inline]
none(binding: u32) -> Self52     pub fn none(binding: u32) -> Self {
53         Self::none_array(binding, 0, 1)
54     }
55 
56     /// Write a number of consecutive empty elements.
57     ///
58     /// See [`none`](Self::none) for more information.
59     #[inline]
none_array(binding: u32, first_array_element: u32, num_elements: u32) -> Self60     pub fn none_array(binding: u32, first_array_element: u32, num_elements: u32) -> Self {
61         assert!(num_elements != 0);
62         Self {
63             binding,
64             first_array_element,
65             elements: WriteDescriptorSetElements::None(num_elements),
66         }
67     }
68 
69     /// Write a single buffer to array element 0, with the bound range covering the whole buffer.
70     ///
71     /// For dynamic buffer bindings, this will bind the whole buffer, and only a dynamic offset
72     /// of zero will be valid, which is probably not what you want.
73     /// Use [`buffer_with_range`](Self::buffer_with_range) instead.
74     #[inline]
buffer(binding: u32, buffer: Subbuffer<impl ?Sized>) -> Self75     pub fn buffer(binding: u32, buffer: Subbuffer<impl ?Sized>) -> Self {
76         let range = 0..buffer.size();
77         Self::buffer_with_range_array(binding, 0, [(buffer, range)])
78     }
79 
80     /// Write a number of consecutive buffer elements.
81     ///
82     /// See [`buffer`](Self::buffer) for more information.
83     #[inline]
buffer_array( binding: u32, first_array_element: u32, elements: impl IntoIterator<Item = Subbuffer<impl ?Sized>>, ) -> Self84     pub fn buffer_array(
85         binding: u32,
86         first_array_element: u32,
87         elements: impl IntoIterator<Item = Subbuffer<impl ?Sized>>,
88     ) -> Self {
89         Self::buffer_with_range_array(
90             binding,
91             first_array_element,
92             elements.into_iter().map(|buffer| {
93                 let range = 0..buffer.size();
94                 (buffer, range)
95             }),
96         )
97     }
98 
99     /// Write a single buffer to array element 0, specifying the range of the buffer to be bound.
100     ///
101     /// `range` is the slice of bytes in `buffer` that will be made available to the shader.
102     /// `range` must not be outside the range `buffer`.
103     ///
104     /// For dynamic buffer bindings, `range` specifies the slice that is to be bound if the
105     /// dynamic offset were zero. When binding the descriptor set, the effective value of `range`
106     /// shifts forward by the offset that was provided. For example, if `range` is specified as
107     /// `0..8` when writing the descriptor set, and then when binding the descriptor set the
108     /// offset `16` is used, then the range of `buffer` that will actually be bound is `16..24`.
109     #[inline]
buffer_with_range( binding: u32, buffer: Subbuffer<impl ?Sized>, range: Range<DeviceSize>, ) -> Self110     pub fn buffer_with_range(
111         binding: u32,
112         buffer: Subbuffer<impl ?Sized>,
113         range: Range<DeviceSize>,
114     ) -> Self {
115         Self::buffer_with_range_array(binding, 0, [(buffer, range)])
116     }
117 
118     /// Write a number of consecutive buffer elements, specifying the ranges of the buffers to be
119     /// bound.
120     ///
121     /// See [`buffer_with_range`](Self::buffer_with_range) for more information.
buffer_with_range_array( binding: u32, first_array_element: u32, elements: impl IntoIterator<Item = (Subbuffer<impl ?Sized>, Range<DeviceSize>)>, ) -> Self122     pub fn buffer_with_range_array(
123         binding: u32,
124         first_array_element: u32,
125         elements: impl IntoIterator<Item = (Subbuffer<impl ?Sized>, Range<DeviceSize>)>,
126     ) -> Self {
127         let elements: SmallVec<_> = elements
128             .into_iter()
129             .map(|(buffer, range)| (buffer.into_bytes(), range))
130             .collect();
131         assert!(!elements.is_empty());
132 
133         Self {
134             binding,
135             first_array_element,
136             elements: WriteDescriptorSetElements::Buffer(elements),
137         }
138     }
139 
140     /// Write a single buffer view to array element 0.
141     #[inline]
buffer_view(binding: u32, buffer_view: Arc<BufferView>) -> Self142     pub fn buffer_view(binding: u32, buffer_view: Arc<BufferView>) -> Self {
143         Self::buffer_view_array(binding, 0, [buffer_view])
144     }
145 
146     /// Write a number of consecutive buffer view elements.
buffer_view_array( binding: u32, first_array_element: u32, elements: impl IntoIterator<Item = Arc<BufferView>>, ) -> Self147     pub fn buffer_view_array(
148         binding: u32,
149         first_array_element: u32,
150         elements: impl IntoIterator<Item = Arc<BufferView>>,
151     ) -> Self {
152         let elements: SmallVec<_> = elements.into_iter().collect();
153         assert!(!elements.is_empty());
154         Self {
155             binding,
156             first_array_element,
157             elements: WriteDescriptorSetElements::BufferView(elements),
158         }
159     }
160 
161     /// Write a single image view to array element 0.
162     #[inline]
image_view(binding: u32, image_view: Arc<dyn ImageViewAbstract>) -> Self163     pub fn image_view(binding: u32, image_view: Arc<dyn ImageViewAbstract>) -> Self {
164         Self::image_view_array(binding, 0, [image_view])
165     }
166 
167     /// Write a number of consecutive image view elements.
image_view_array( binding: u32, first_array_element: u32, elements: impl IntoIterator<Item = Arc<dyn ImageViewAbstract>>, ) -> Self168     pub fn image_view_array(
169         binding: u32,
170         first_array_element: u32,
171         elements: impl IntoIterator<Item = Arc<dyn ImageViewAbstract>>,
172     ) -> Self {
173         let elements: SmallVec<_> = elements.into_iter().collect();
174         assert!(!elements.is_empty());
175         Self {
176             binding,
177             first_array_element,
178             elements: WriteDescriptorSetElements::ImageView(elements),
179         }
180     }
181 
182     /// Write a single image view and sampler to array element 0.
183     #[inline]
image_view_sampler( binding: u32, image_view: Arc<dyn ImageViewAbstract>, sampler: Arc<Sampler>, ) -> Self184     pub fn image_view_sampler(
185         binding: u32,
186         image_view: Arc<dyn ImageViewAbstract>,
187         sampler: Arc<Sampler>,
188     ) -> Self {
189         Self::image_view_sampler_array(binding, 0, [(image_view, sampler)])
190     }
191 
192     /// Write a number of consecutive image view and sampler elements.
image_view_sampler_array( binding: u32, first_array_element: u32, elements: impl IntoIterator<Item = (Arc<dyn ImageViewAbstract>, Arc<Sampler>)>, ) -> Self193     pub fn image_view_sampler_array(
194         binding: u32,
195         first_array_element: u32,
196         elements: impl IntoIterator<Item = (Arc<dyn ImageViewAbstract>, Arc<Sampler>)>,
197     ) -> Self {
198         let elements: SmallVec<_> = elements.into_iter().collect();
199         assert!(!elements.is_empty());
200         Self {
201             binding,
202             first_array_element,
203             elements: WriteDescriptorSetElements::ImageViewSampler(elements),
204         }
205     }
206 
207     /// Write a single sampler to array element 0.
208     #[inline]
sampler(binding: u32, sampler: Arc<Sampler>) -> Self209     pub fn sampler(binding: u32, sampler: Arc<Sampler>) -> Self {
210         Self::sampler_array(binding, 0, [sampler])
211     }
212 
213     /// Write a number of consecutive sampler elements.
sampler_array( binding: u32, first_array_element: u32, elements: impl IntoIterator<Item = Arc<Sampler>>, ) -> Self214     pub fn sampler_array(
215         binding: u32,
216         first_array_element: u32,
217         elements: impl IntoIterator<Item = Arc<Sampler>>,
218     ) -> Self {
219         let elements: SmallVec<_> = elements.into_iter().collect();
220         assert!(!elements.is_empty());
221         Self {
222             binding,
223             first_array_element,
224             elements: WriteDescriptorSetElements::Sampler(elements),
225         }
226     }
227 
228     /// Returns the binding number that is updated by this descriptor write.
229     #[inline]
binding(&self) -> u32230     pub fn binding(&self) -> u32 {
231         self.binding
232     }
233 
234     /// Returns the first array element in the binding that is updated by this descriptor write.
235     #[inline]
first_array_element(&self) -> u32236     pub fn first_array_element(&self) -> u32 {
237         self.first_array_element
238     }
239 
240     /// Returns a reference to the elements held by this descriptor write.
241     #[inline]
elements(&self) -> &WriteDescriptorSetElements242     pub fn elements(&self) -> &WriteDescriptorSetElements {
243         &self.elements
244     }
245 
to_vulkan_info(&self, descriptor_type: DescriptorType) -> DescriptorWriteInfo246     pub(crate) fn to_vulkan_info(&self, descriptor_type: DescriptorType) -> DescriptorWriteInfo {
247         match &self.elements {
248             WriteDescriptorSetElements::None(num_elements) => {
249                 debug_assert!(matches!(descriptor_type, DescriptorType::Sampler));
250                 DescriptorWriteInfo::Image(
251                     std::iter::repeat_with(|| ash::vk::DescriptorImageInfo {
252                         sampler: ash::vk::Sampler::null(),
253                         image_view: ash::vk::ImageView::null(),
254                         image_layout: ash::vk::ImageLayout::UNDEFINED,
255                     })
256                     .take(*num_elements as usize)
257                     .collect(),
258                 )
259             }
260             WriteDescriptorSetElements::Buffer(elements) => {
261                 debug_assert!(matches!(
262                     descriptor_type,
263                     DescriptorType::UniformBuffer
264                         | DescriptorType::StorageBuffer
265                         | DescriptorType::UniformBufferDynamic
266                         | DescriptorType::StorageBufferDynamic
267                 ));
268                 DescriptorWriteInfo::Buffer(
269                     elements
270                         .iter()
271                         .map(|(buffer, range)| {
272                             debug_assert!(!range.is_empty());
273                             debug_assert!(range.end <= buffer.buffer().size());
274 
275                             ash::vk::DescriptorBufferInfo {
276                                 buffer: buffer.buffer().handle(),
277                                 offset: buffer.offset() + range.start,
278                                 range: range.end - range.start,
279                             }
280                         })
281                         .collect(),
282                 )
283             }
284             WriteDescriptorSetElements::BufferView(elements) => {
285                 debug_assert!(matches!(
286                     descriptor_type,
287                     DescriptorType::UniformTexelBuffer | DescriptorType::StorageTexelBuffer
288                 ));
289                 DescriptorWriteInfo::BufferView(
290                     elements
291                         .iter()
292                         .map(|buffer_view| buffer_view.handle())
293                         .collect(),
294                 )
295             }
296             WriteDescriptorSetElements::ImageView(elements) => {
297                 // Note: combined image sampler can occur with immutable samplers
298                 debug_assert!(matches!(
299                     descriptor_type,
300                     DescriptorType::CombinedImageSampler
301                         | DescriptorType::SampledImage
302                         | DescriptorType::StorageImage
303                         | DescriptorType::InputAttachment
304                 ));
305                 DescriptorWriteInfo::Image(
306                     elements
307                         .iter()
308                         .map(|image_view| {
309                             let layouts = image_view.image().descriptor_layouts().expect(
310                                 "descriptor_layouts must return Some when used in an image view",
311                             );
312                             ash::vk::DescriptorImageInfo {
313                                 sampler: ash::vk::Sampler::null(),
314                                 image_view: image_view.handle(),
315                                 image_layout: layouts.layout_for(descriptor_type).into(),
316                             }
317                         })
318                         .collect(),
319                 )
320             }
321             WriteDescriptorSetElements::ImageViewSampler(elements) => {
322                 debug_assert!(matches!(
323                     descriptor_type,
324                     DescriptorType::CombinedImageSampler
325                 ));
326                 DescriptorWriteInfo::Image(
327                     elements
328                         .iter()
329                         .map(|(image_view, sampler)| {
330                             let layouts = image_view.image().descriptor_layouts().expect(
331                                 "descriptor_layouts must return Some when used in an image view",
332                             );
333                             ash::vk::DescriptorImageInfo {
334                                 sampler: sampler.handle(),
335                                 image_view: image_view.handle(),
336                                 image_layout: layouts.layout_for(descriptor_type).into(),
337                             }
338                         })
339                         .collect(),
340                 )
341             }
342             WriteDescriptorSetElements::Sampler(elements) => {
343                 debug_assert!(matches!(descriptor_type, DescriptorType::Sampler));
344                 DescriptorWriteInfo::Image(
345                     elements
346                         .iter()
347                         .map(|sampler| ash::vk::DescriptorImageInfo {
348                             sampler: sampler.handle(),
349                             image_view: ash::vk::ImageView::null(),
350                             image_layout: ash::vk::ImageLayout::UNDEFINED,
351                         })
352                         .collect(),
353                 )
354             }
355         }
356     }
357 
to_vulkan( &self, dst_set: ash::vk::DescriptorSet, descriptor_type: DescriptorType, ) -> ash::vk::WriteDescriptorSet358     pub(crate) fn to_vulkan(
359         &self,
360         dst_set: ash::vk::DescriptorSet,
361         descriptor_type: DescriptorType,
362     ) -> ash::vk::WriteDescriptorSet {
363         ash::vk::WriteDescriptorSet {
364             dst_set,
365             dst_binding: self.binding,
366             dst_array_element: self.first_array_element,
367             descriptor_count: 0,
368             descriptor_type: descriptor_type.into(),
369             p_image_info: ptr::null(),
370             p_buffer_info: ptr::null(),
371             p_texel_buffer_view: ptr::null(),
372             ..Default::default()
373         }
374     }
375 }
376 
377 /// The elements held by a `WriteDescriptorSet`.
378 pub enum WriteDescriptorSetElements {
379     None(u32),
380     Buffer(SmallVec<[(Subbuffer<[u8]>, Range<DeviceSize>); 1]>),
381     BufferView(SmallVec<[Arc<BufferView>; 1]>),
382     ImageView(SmallVec<[Arc<dyn ImageViewAbstract>; 1]>),
383     ImageViewSampler(SmallVec<[(Arc<dyn ImageViewAbstract>, Arc<Sampler>); 1]>),
384     Sampler(SmallVec<[Arc<Sampler>; 1]>),
385 }
386 
387 impl WriteDescriptorSetElements {
388     /// Returns the number of elements.
389     #[inline]
len(&self) -> u32390     pub fn len(&self) -> u32 {
391         match self {
392             Self::None(num_elements) => *num_elements,
393             Self::Buffer(elements) => elements.len() as u32,
394             Self::BufferView(elements) => elements.len() as u32,
395             Self::ImageView(elements) => elements.len() as u32,
396             Self::ImageViewSampler(elements) => elements.len() as u32,
397             Self::Sampler(elements) => elements.len() as u32,
398         }
399     }
400 }
401 
402 #[derive(Clone, Debug)]
403 pub(crate) enum DescriptorWriteInfo {
404     Image(SmallVec<[ash::vk::DescriptorImageInfo; 1]>),
405     Buffer(SmallVec<[ash::vk::DescriptorBufferInfo; 1]>),
406     BufferView(SmallVec<[ash::vk::BufferView; 1]>),
407 }
408 
check_descriptor_write<'a>( write: &WriteDescriptorSet, layout: &'a DescriptorSetLayout, variable_descriptor_count: u32, ) -> Result<&'a DescriptorSetLayoutBinding, DescriptorSetUpdateError>409 pub(crate) fn check_descriptor_write<'a>(
410     write: &WriteDescriptorSet,
411     layout: &'a DescriptorSetLayout,
412     variable_descriptor_count: u32,
413 ) -> Result<&'a DescriptorSetLayoutBinding, DescriptorSetUpdateError> {
414     fn provided_element_type(elements: &WriteDescriptorSetElements) -> &'static str {
415         match elements {
416             WriteDescriptorSetElements::None(_) => "none",
417             WriteDescriptorSetElements::Buffer(_) => "buffer",
418             WriteDescriptorSetElements::BufferView(_) => "buffer_view",
419             WriteDescriptorSetElements::ImageView(_) => "image_view",
420             WriteDescriptorSetElements::ImageViewSampler(_) => "image_view_sampler",
421             WriteDescriptorSetElements::Sampler(_) => "sampler",
422         }
423     }
424 
425     let device = layout.device();
426 
427     let layout_binding = match layout.bindings().get(&write.binding()) {
428         Some(binding) => binding,
429         None => {
430             return Err(DescriptorSetUpdateError::InvalidBinding {
431                 binding: write.binding(),
432             })
433         }
434     };
435 
436     let max_descriptor_count = if layout_binding.variable_descriptor_count {
437         variable_descriptor_count
438     } else {
439         layout_binding.descriptor_count
440     };
441 
442     let binding = write.binding();
443     let elements = write.elements();
444     let num_elements = elements.len();
445     debug_assert!(num_elements != 0);
446 
447     let descriptor_range_start = write.first_array_element();
448     let descriptor_range_end = descriptor_range_start + num_elements;
449 
450     if descriptor_range_end > max_descriptor_count {
451         return Err(DescriptorSetUpdateError::ArrayIndexOutOfBounds {
452             binding,
453             available_count: max_descriptor_count,
454             written_count: descriptor_range_end,
455         });
456     }
457 
458     match layout_binding.descriptor_type {
459         DescriptorType::Sampler => {
460             if layout_binding.immutable_samplers.is_empty() {
461                 let elements = if let WriteDescriptorSetElements::Sampler(elements) = elements {
462                     elements
463                 } else {
464                     return Err(DescriptorSetUpdateError::IncompatibleElementType {
465                         binding,
466                         provided_element_type: provided_element_type(elements),
467                         allowed_element_types: &["sampler"],
468                     });
469                 };
470 
471                 for (index, sampler) in elements.iter().enumerate() {
472                     assert_eq!(device, sampler.device());
473 
474                     if sampler.sampler_ycbcr_conversion().is_some() {
475                         return Err(DescriptorSetUpdateError::SamplerHasSamplerYcbcrConversion {
476                             binding: write.binding(),
477                             index: descriptor_range_start + index as u32,
478                         });
479                     }
480                 }
481             } else if layout.push_descriptor() {
482                 // For push descriptors, we must write a dummy element.
483                 if let WriteDescriptorSetElements::None(_) = elements {
484                     // Do nothing
485                 } else {
486                     return Err(DescriptorSetUpdateError::IncompatibleElementType {
487                         binding,
488                         provided_element_type: provided_element_type(elements),
489                         allowed_element_types: &["none"],
490                     });
491                 }
492             } else {
493                 // For regular descriptors, no element must be written.
494                 return Err(DescriptorSetUpdateError::IncompatibleElementType {
495                     binding,
496                     provided_element_type: provided_element_type(elements),
497                     allowed_element_types: &[],
498                 });
499             }
500         }
501 
502         DescriptorType::CombinedImageSampler => {
503             if layout_binding.immutable_samplers.is_empty() {
504                 let elements =
505                     if let WriteDescriptorSetElements::ImageViewSampler(elements) = elements {
506                         elements
507                     } else {
508                         return Err(DescriptorSetUpdateError::IncompatibleElementType {
509                             binding,
510                             provided_element_type: provided_element_type(elements),
511                             allowed_element_types: &["image_view_sampler"],
512                         });
513                     };
514 
515                 for (index, (image_view, sampler)) in elements.iter().enumerate() {
516                     assert_eq!(device, image_view.device());
517                     assert_eq!(device, sampler.device());
518 
519                     // VUID-VkWriteDescriptorSet-descriptorType-00337
520                     if !image_view.usage().intersects(ImageUsage::SAMPLED) {
521                         return Err(DescriptorSetUpdateError::MissingUsage {
522                             binding: write.binding(),
523                             index: descriptor_range_start + index as u32,
524                             usage: "sampled",
525                         });
526                     }
527 
528                     // VUID-VkDescriptorImageInfo-imageView-00343
529                     if matches!(
530                         image_view.view_type(),
531                         ImageViewType::Dim2d | ImageViewType::Dim2dArray
532                     ) && image_view.image().inner().image.dimensions().image_type()
533                         == ImageType::Dim3d
534                     {
535                         return Err(DescriptorSetUpdateError::ImageView2dFrom3d {
536                             binding: write.binding(),
537                             index: descriptor_range_start + index as u32,
538                         });
539                     }
540 
541                     // VUID-VkDescriptorImageInfo-imageView-01976
542                     if image_view
543                         .subresource_range()
544                         .aspects
545                         .contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
546                     {
547                         return Err(DescriptorSetUpdateError::ImageViewDepthAndStencil {
548                             binding: write.binding(),
549                             index: descriptor_range_start + index as u32,
550                         });
551                     }
552 
553                     // VUID-VkDescriptorImageInfo-mutableComparisonSamplers-04450
554                     if device.enabled_extensions().khr_portability_subset
555                         && !device.enabled_features().mutable_comparison_samplers
556                         && sampler.compare().is_some()
557                     {
558                         return Err(DescriptorSetUpdateError::RequirementNotMet {
559                             binding: write.binding(),
560                             index: descriptor_range_start + index as u32,
561                             required_for: "this device is a portability subset device, and \
562                                 `sampler.compare()` is `Some`",
563                             requires_one_of: RequiresOneOf {
564                                 features: &["mutable_comparison_samplers"],
565                                 ..Default::default()
566                             },
567                         });
568                     }
569 
570                     if image_view.sampler_ycbcr_conversion().is_some() {
571                         return Err(
572                             DescriptorSetUpdateError::ImageViewHasSamplerYcbcrConversion {
573                                 binding: write.binding(),
574                                 index: descriptor_range_start + index as u32,
575                             },
576                         );
577                     }
578 
579                     if sampler.sampler_ycbcr_conversion().is_some() {
580                         return Err(DescriptorSetUpdateError::SamplerHasSamplerYcbcrConversion {
581                             binding: write.binding(),
582                             index: descriptor_range_start + index as u32,
583                         });
584                     }
585 
586                     if let Err(error) = sampler.check_can_sample(image_view.as_ref()) {
587                         return Err(DescriptorSetUpdateError::ImageViewIncompatibleSampler {
588                             binding: write.binding(),
589                             index: descriptor_range_start + index as u32,
590                             error,
591                         });
592                     }
593                 }
594             } else {
595                 let elements = if let WriteDescriptorSetElements::ImageView(elements) = elements {
596                     elements
597                 } else {
598                     return Err(DescriptorSetUpdateError::IncompatibleElementType {
599                         binding,
600                         provided_element_type: provided_element_type(elements),
601                         allowed_element_types: &["image_view"],
602                     });
603                 };
604 
605                 let immutable_samplers = &layout_binding.immutable_samplers
606                     [descriptor_range_start as usize..descriptor_range_end as usize];
607 
608                 for (index, (image_view, sampler)) in
609                     elements.iter().zip(immutable_samplers).enumerate()
610                 {
611                     assert_eq!(device, image_view.device());
612 
613                     // VUID-VkWriteDescriptorSet-descriptorType-00337
614                     if !image_view.usage().intersects(ImageUsage::SAMPLED) {
615                         return Err(DescriptorSetUpdateError::MissingUsage {
616                             binding: write.binding(),
617                             index: descriptor_range_start + index as u32,
618                             usage: "sampled",
619                         });
620                     }
621 
622                     // VUID-VkDescriptorImageInfo-imageView-00343
623                     if matches!(
624                         image_view.view_type(),
625                         ImageViewType::Dim2d | ImageViewType::Dim2dArray
626                     ) && image_view.image().inner().image.dimensions().image_type()
627                         == ImageType::Dim3d
628                     {
629                         return Err(DescriptorSetUpdateError::ImageView2dFrom3d {
630                             binding: write.binding(),
631                             index: descriptor_range_start + index as u32,
632                         });
633                     }
634 
635                     // VUID-VkDescriptorImageInfo-imageView-01976
636                     if image_view
637                         .subresource_range()
638                         .aspects
639                         .contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
640                     {
641                         return Err(DescriptorSetUpdateError::ImageViewDepthAndStencil {
642                             binding: write.binding(),
643                             index: descriptor_range_start + index as u32,
644                         });
645                     }
646 
647                     if let Err(error) = sampler.check_can_sample(image_view.as_ref()) {
648                         return Err(DescriptorSetUpdateError::ImageViewIncompatibleSampler {
649                             binding: write.binding(),
650                             index: descriptor_range_start + index as u32,
651                             error,
652                         });
653                     }
654                 }
655             }
656         }
657 
658         DescriptorType::SampledImage => {
659             let elements = if let WriteDescriptorSetElements::ImageView(elements) = elements {
660                 elements
661             } else {
662                 return Err(DescriptorSetUpdateError::IncompatibleElementType {
663                     binding,
664                     provided_element_type: provided_element_type(elements),
665                     allowed_element_types: &["image_view"],
666                 });
667             };
668 
669             for (index, image_view) in elements.iter().enumerate() {
670                 assert_eq!(device, image_view.device());
671 
672                 // VUID-VkWriteDescriptorSet-descriptorType-00337
673                 if !image_view.usage().intersects(ImageUsage::SAMPLED) {
674                     return Err(DescriptorSetUpdateError::MissingUsage {
675                         binding: write.binding(),
676                         index: descriptor_range_start + index as u32,
677                         usage: "sampled",
678                     });
679                 }
680 
681                 // VUID-VkDescriptorImageInfo-imageView-00343
682                 if matches!(
683                     image_view.view_type(),
684                     ImageViewType::Dim2d | ImageViewType::Dim2dArray
685                 ) && image_view.image().inner().image.dimensions().image_type()
686                     == ImageType::Dim3d
687                 {
688                     return Err(DescriptorSetUpdateError::ImageView2dFrom3d {
689                         binding: write.binding(),
690                         index: descriptor_range_start + index as u32,
691                     });
692                 }
693 
694                 // VUID-VkDescriptorImageInfo-imageView-01976
695                 if image_view
696                     .subresource_range()
697                     .aspects
698                     .contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
699                 {
700                     return Err(DescriptorSetUpdateError::ImageViewDepthAndStencil {
701                         binding: write.binding(),
702                         index: descriptor_range_start + index as u32,
703                     });
704                 }
705 
706                 // VUID-VkWriteDescriptorSet-descriptorType-01946
707                 if image_view.sampler_ycbcr_conversion().is_some() {
708                     return Err(
709                         DescriptorSetUpdateError::ImageViewHasSamplerYcbcrConversion {
710                             binding: write.binding(),
711                             index: descriptor_range_start + index as u32,
712                         },
713                     );
714                 }
715             }
716         }
717 
718         DescriptorType::StorageImage => {
719             let elements = if let WriteDescriptorSetElements::ImageView(elements) = elements {
720                 elements
721             } else {
722                 return Err(DescriptorSetUpdateError::IncompatibleElementType {
723                     binding,
724                     provided_element_type: provided_element_type(elements),
725                     allowed_element_types: &["image_view"],
726                 });
727             };
728 
729             for (index, image_view) in elements.iter().enumerate() {
730                 assert_eq!(device, image_view.device());
731 
732                 // VUID-VkWriteDescriptorSet-descriptorType-00339
733                 if !image_view.usage().intersects(ImageUsage::STORAGE) {
734                     return Err(DescriptorSetUpdateError::MissingUsage {
735                         binding: write.binding(),
736                         index: descriptor_range_start + index as u32,
737                         usage: "storage",
738                     });
739                 }
740 
741                 // VUID-VkDescriptorImageInfo-imageView-00343
742                 if matches!(
743                     image_view.view_type(),
744                     ImageViewType::Dim2d | ImageViewType::Dim2dArray
745                 ) && image_view.image().inner().image.dimensions().image_type()
746                     == ImageType::Dim3d
747                 {
748                     return Err(DescriptorSetUpdateError::ImageView2dFrom3d {
749                         binding: write.binding(),
750                         index: descriptor_range_start + index as u32,
751                     });
752                 }
753 
754                 // VUID-VkDescriptorImageInfo-imageView-01976
755                 if image_view
756                     .subresource_range()
757                     .aspects
758                     .contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
759                 {
760                     return Err(DescriptorSetUpdateError::ImageViewDepthAndStencil {
761                         binding: write.binding(),
762                         index: descriptor_range_start + index as u32,
763                     });
764                 }
765 
766                 // VUID-VkWriteDescriptorSet-descriptorType-00336
767                 if !image_view.component_mapping().is_identity() {
768                     return Err(DescriptorSetUpdateError::ImageViewNotIdentitySwizzled {
769                         binding: write.binding(),
770                         index: descriptor_range_start + index as u32,
771                     });
772                 }
773 
774                 // VUID??
775                 if image_view.sampler_ycbcr_conversion().is_some() {
776                     return Err(
777                         DescriptorSetUpdateError::ImageViewHasSamplerYcbcrConversion {
778                             binding: write.binding(),
779                             index: descriptor_range_start + index as u32,
780                         },
781                     );
782                 }
783             }
784         }
785 
786         DescriptorType::UniformTexelBuffer => {
787             let elements = if let WriteDescriptorSetElements::BufferView(elements) = elements {
788                 elements
789             } else {
790                 return Err(DescriptorSetUpdateError::IncompatibleElementType {
791                     binding,
792                     provided_element_type: provided_element_type(elements),
793                     allowed_element_types: &["buffer_view"],
794                 });
795             };
796 
797             for (index, buffer_view) in elements.iter().enumerate() {
798                 assert_eq!(device, buffer_view.device());
799 
800                 if !buffer_view
801                     .buffer()
802                     .buffer()
803                     .usage()
804                     .intersects(BufferUsage::UNIFORM_TEXEL_BUFFER)
805                 {
806                     return Err(DescriptorSetUpdateError::MissingUsage {
807                         binding: write.binding(),
808                         index: descriptor_range_start + index as u32,
809                         usage: "uniform_texel_buffer",
810                     });
811                 }
812             }
813         }
814 
815         DescriptorType::StorageTexelBuffer => {
816             let elements = if let WriteDescriptorSetElements::BufferView(elements) = elements {
817                 elements
818             } else {
819                 return Err(DescriptorSetUpdateError::IncompatibleElementType {
820                     binding,
821                     provided_element_type: provided_element_type(elements),
822                     allowed_element_types: &["buffer_view"],
823                 });
824             };
825 
826             for (index, buffer_view) in elements.iter().enumerate() {
827                 assert_eq!(device, buffer_view.device());
828 
829                 // TODO: storage_texel_buffer_atomic
830                 if !buffer_view
831                     .buffer()
832                     .buffer()
833                     .usage()
834                     .intersects(BufferUsage::STORAGE_TEXEL_BUFFER)
835                 {
836                     return Err(DescriptorSetUpdateError::MissingUsage {
837                         binding: write.binding(),
838                         index: descriptor_range_start + index as u32,
839                         usage: "storage_texel_buffer",
840                     });
841                 }
842             }
843         }
844 
845         DescriptorType::UniformBuffer | DescriptorType::UniformBufferDynamic => {
846             let elements = if let WriteDescriptorSetElements::Buffer(elements) = elements {
847                 elements
848             } else {
849                 return Err(DescriptorSetUpdateError::IncompatibleElementType {
850                     binding,
851                     provided_element_type: provided_element_type(elements),
852                     allowed_element_types: &["buffer"],
853                 });
854             };
855 
856             for (index, (buffer, range)) in elements.iter().enumerate() {
857                 assert_eq!(device, buffer.device());
858 
859                 if !buffer
860                     .buffer()
861                     .usage()
862                     .intersects(BufferUsage::UNIFORM_BUFFER)
863                 {
864                     return Err(DescriptorSetUpdateError::MissingUsage {
865                         binding: write.binding(),
866                         index: descriptor_range_start + index as u32,
867                         usage: "uniform_buffer",
868                     });
869                 }
870 
871                 assert!(!range.is_empty());
872 
873                 if range.end > buffer.size() {
874                     return Err(DescriptorSetUpdateError::RangeOutOfBufferBounds {
875                         binding: write.binding(),
876                         index: descriptor_range_start + index as u32,
877                         range_end: range.end,
878                         buffer_size: buffer.size(),
879                     });
880                 }
881             }
882         }
883 
884         DescriptorType::StorageBuffer | DescriptorType::StorageBufferDynamic => {
885             let elements = if let WriteDescriptorSetElements::Buffer(elements) = elements {
886                 elements
887             } else {
888                 return Err(DescriptorSetUpdateError::IncompatibleElementType {
889                     binding,
890                     provided_element_type: provided_element_type(elements),
891                     allowed_element_types: &["buffer"],
892                 });
893             };
894 
895             for (index, (buffer, range)) in elements.iter().enumerate() {
896                 assert_eq!(device, buffer.device());
897 
898                 if !buffer
899                     .buffer()
900                     .usage()
901                     .intersects(BufferUsage::STORAGE_BUFFER)
902                 {
903                     return Err(DescriptorSetUpdateError::MissingUsage {
904                         binding: write.binding(),
905                         index: descriptor_range_start + index as u32,
906                         usage: "storage_buffer",
907                     });
908                 }
909 
910                 assert!(!range.is_empty());
911 
912                 if range.end > buffer.size() {
913                     return Err(DescriptorSetUpdateError::RangeOutOfBufferBounds {
914                         binding: write.binding(),
915                         index: descriptor_range_start + index as u32,
916                         range_end: range.end,
917                         buffer_size: buffer.size(),
918                     });
919                 }
920             }
921         }
922 
923         DescriptorType::InputAttachment => {
924             let elements = if let WriteDescriptorSetElements::ImageView(elements) = elements {
925                 elements
926             } else {
927                 return Err(DescriptorSetUpdateError::IncompatibleElementType {
928                     binding,
929                     provided_element_type: provided_element_type(elements),
930                     allowed_element_types: &["image_view"],
931                 });
932             };
933 
934             for (index, image_view) in elements.iter().enumerate() {
935                 assert_eq!(device, image_view.device());
936 
937                 // VUID-VkWriteDescriptorSet-descriptorType-00338
938                 if !image_view.usage().intersects(ImageUsage::INPUT_ATTACHMENT) {
939                     return Err(DescriptorSetUpdateError::MissingUsage {
940                         binding: write.binding(),
941                         index: descriptor_range_start + index as u32,
942                         usage: "input_attachment",
943                     });
944                 }
945 
946                 // VUID-VkDescriptorImageInfo-imageView-00343
947                 if matches!(
948                     image_view.view_type(),
949                     ImageViewType::Dim2d | ImageViewType::Dim2dArray
950                 ) && image_view.image().inner().image.dimensions().image_type()
951                     == ImageType::Dim3d
952                 {
953                     return Err(DescriptorSetUpdateError::ImageView2dFrom3d {
954                         binding: write.binding(),
955                         index: descriptor_range_start + index as u32,
956                     });
957                 }
958 
959                 // VUID-VkDescriptorImageInfo-imageView-01976
960                 if image_view
961                     .subresource_range()
962                     .aspects
963                     .contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
964                 {
965                     return Err(DescriptorSetUpdateError::ImageViewDepthAndStencil {
966                         binding: write.binding(),
967                         index: descriptor_range_start + index as u32,
968                     });
969                 }
970 
971                 // VUID-VkWriteDescriptorSet-descriptorType-00336
972                 if !image_view.component_mapping().is_identity() {
973                     return Err(DescriptorSetUpdateError::ImageViewNotIdentitySwizzled {
974                         binding: write.binding(),
975                         index: descriptor_range_start + index as u32,
976                     });
977                 }
978 
979                 // VUID??
980                 if image_view.sampler_ycbcr_conversion().is_some() {
981                     return Err(
982                         DescriptorSetUpdateError::ImageViewHasSamplerYcbcrConversion {
983                             binding: write.binding(),
984                             index: descriptor_range_start + index as u32,
985                         },
986                     );
987                 }
988 
989                 // VUID??
990                 if image_view.view_type().is_arrayed() {
991                     return Err(DescriptorSetUpdateError::ImageViewIsArrayed {
992                         binding: write.binding(),
993                         index: descriptor_range_start + index as u32,
994                     });
995                 }
996             }
997         }
998     }
999 
1000     Ok(layout_binding)
1001 }
1002 
1003 #[derive(Clone, Copy, Debug)]
1004 pub enum DescriptorSetUpdateError {
1005     RequirementNotMet {
1006         binding: u32,
1007         index: u32,
1008         required_for: &'static str,
1009         requires_one_of: RequiresOneOf,
1010     },
1011 
1012     /// Tried to write more elements than were available in a binding.
1013     ArrayIndexOutOfBounds {
1014         /// Binding that is affected.
1015         binding: u32,
1016         /// Number of available descriptors in the binding.
1017         available_count: u32,
1018         /// The number of descriptors that were in the update.
1019         written_count: u32,
1020     },
1021 
1022     /// Tried to write an image view with a 2D type and a 3D underlying image.
1023     ImageView2dFrom3d { binding: u32, index: u32 },
1024 
1025     /// Tried to write an image view that has both the `depth` and `stencil` aspects.
1026     ImageViewDepthAndStencil { binding: u32, index: u32 },
1027 
1028     /// Tried to write an image view with an attached sampler YCbCr conversion to a binding that
1029     /// does not support it.
1030     ImageViewHasSamplerYcbcrConversion { binding: u32, index: u32 },
1031 
1032     /// Tried to write an image view of an arrayed type to a descriptor type that does not support
1033     /// it.
1034     ImageViewIsArrayed { binding: u32, index: u32 },
1035 
1036     /// Tried to write an image view that was not compatible with the sampler that was provided as
1037     /// part of the update or immutably in the layout.
1038     ImageViewIncompatibleSampler {
1039         binding: u32,
1040         index: u32,
1041         error: SamplerImageViewIncompatibleError,
1042     },
1043 
1044     /// Tried to write an image view to a descriptor type that requires it to be identity swizzled,
1045     /// but it was not.
1046     ImageViewNotIdentitySwizzled { binding: u32, index: u32 },
1047 
1048     /// Tried to write an element type that was not compatible with the descriptor type in the
1049     /// layout.
1050     IncompatibleElementType {
1051         binding: u32,
1052         provided_element_type: &'static str,
1053         allowed_element_types: &'static [&'static str],
1054     },
1055 
1056     /// Tried to write to a nonexistent binding.
1057     InvalidBinding { binding: u32 },
1058 
1059     /// A resource was missing a usage flag that was required.
1060     MissingUsage {
1061         binding: u32,
1062         index: u32,
1063         usage: &'static str,
1064     },
1065 
1066     /// The end of the provided `range` for a buffer is larger than the size of the buffer.
1067     RangeOutOfBufferBounds {
1068         binding: u32,
1069         index: u32,
1070         range_end: DeviceSize,
1071         buffer_size: DeviceSize,
1072     },
1073 
1074     /// Tried to write a sampler that has an attached sampler YCbCr conversion.
1075     SamplerHasSamplerYcbcrConversion { binding: u32, index: u32 },
1076 }
1077 
1078 impl Error for DescriptorSetUpdateError {
source(&self) -> Option<&(dyn Error + 'static)>1079     fn source(&self) -> Option<&(dyn Error + 'static)> {
1080         match self {
1081             Self::ImageViewIncompatibleSampler { error, .. } => Some(error),
1082             _ => None,
1083         }
1084     }
1085 }
1086 
1087 impl Display for DescriptorSetUpdateError {
fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError>1088     fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
1089         match self {
1090             Self::RequirementNotMet {
1091                 binding,
1092                 index,
1093                 required_for,
1094                 requires_one_of,
1095             } => write!(
1096                 f,
1097                 "a requirement on binding {} index {} was not met for: {}; requires one of: {}",
1098                 binding, index, required_for, requires_one_of,
1099             ),
1100 
1101             Self::ArrayIndexOutOfBounds {
1102                 binding,
1103                 available_count,
1104                 written_count,
1105             } => write!(
1106                 f,
1107                 "tried to write up to element {} to binding {}, but only {} descriptors are \
1108                 available",
1109                 written_count, binding, available_count,
1110             ),
1111             Self::ImageView2dFrom3d { binding, index } => write!(
1112                 f,
1113                 "tried to write an image view to binding {} index {} with a 2D type and a 3D \
1114                 underlying image",
1115                 binding, index,
1116             ),
1117             Self::ImageViewDepthAndStencil { binding, index } => write!(
1118                 f,
1119                 "tried to write an image view to binding {} index {} that has both the `depth` and \
1120                 `stencil` aspects",
1121                 binding, index,
1122             ),
1123             Self::ImageViewHasSamplerYcbcrConversion { binding, index } => write!(
1124                 f,
1125                 "tried to write an image view to binding {} index {} with an attached sampler \
1126                 YCbCr conversion to binding that does not support it",
1127                 binding, index,
1128             ),
1129             Self::ImageViewIsArrayed { binding, index } => write!(
1130                 f,
1131                 "tried to write an image view of an arrayed type to binding {} index {}, but this \
1132                 binding has a descriptor type that does not support arrayed image views",
1133                 binding, index,
1134             ),
1135             Self::ImageViewIncompatibleSampler { binding, index, .. } => write!(
1136                 f,
1137                 "tried to write an image view to binding {} index {}, that was not compatible with \
1138                 the sampler that was provided as part of the update or immutably in the layout",
1139                 binding, index,
1140             ),
1141             Self::ImageViewNotIdentitySwizzled { binding, index } => write!(
1142                 f,
1143                 "tried to write an image view with non-identity swizzling to binding {} index {}, \
1144                 but this binding has a descriptor type that requires it to be identity swizzled",
1145                 binding, index,
1146             ),
1147             Self::IncompatibleElementType {
1148                 binding,
1149                 provided_element_type,
1150                 allowed_element_types,
1151             } => write!(
1152                 f,
1153                 "tried to write a resource to binding {} whose type ({}) was not one of the \
1154                 resource types allowed for the descriptor type (",
1155                 binding, provided_element_type,
1156             )
1157             .and_then(|_| {
1158                 let mut first = true;
1159 
1160                 for elem_type in *allowed_element_types {
1161                     if first {
1162                         write!(f, "{}", elem_type)?;
1163                         first = false;
1164                     } else {
1165                         write!(f, ", {}", elem_type)?;
1166                     }
1167                 }
1168 
1169                 Ok(())
1170             })
1171             .and_then(|_| write!(f, ") that can be bound to this buffer")),
1172             Self::InvalidBinding { binding } => {
1173                 write!(f, "tried to write to a nonexistent binding {}", binding,)
1174             }
1175             Self::MissingUsage {
1176                 binding,
1177                 index,
1178                 usage,
1179             } => write!(
1180                 f,
1181                 "tried to write a resource to binding {} index {} that did not have the required \
1182                 usage {} enabled",
1183                 binding, index, usage,
1184             ),
1185             Self::RangeOutOfBufferBounds {
1186                 binding,
1187                 index,
1188                 range_end,
1189                 buffer_size,
1190             } => write!(
1191                 f,
1192                 "the end of the provided `range` for the buffer at binding {} index {} ({:?}) is
1193                 larger than the size of the buffer ({})",
1194                 binding, index, range_end, buffer_size,
1195             ),
1196             Self::SamplerHasSamplerYcbcrConversion { binding, index } => write!(
1197                 f,
1198                 "tried to write a sampler to binding {} index {} that has an attached sampler \
1199                 YCbCr conversion",
1200                 binding, index,
1201             ),
1202         }
1203     }
1204 }
1205