• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2016 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 //! Low-level descriptor set.
11 
12 use crate::buffer::BufferAccess;
13 use crate::buffer::BufferInner;
14 use crate::buffer::BufferView;
15 use crate::descriptor_set::layout::DescriptorType;
16 use crate::device::Device;
17 use crate::device::DeviceOwned;
18 use crate::image::view::ImageViewAbstract;
19 use crate::sampler::Sampler;
20 use crate::DeviceSize;
21 use crate::VulkanObject;
22 use smallvec::SmallVec;
23 use std::fmt;
24 use std::ptr;
25 use std::sync::Arc;
26 
27 /// Low-level descriptor set.
28 ///
29 /// Contrary to most other objects in this library, this one doesn't free itself automatically and
30 /// doesn't hold the pool or the device it is associated to.
31 /// Instead it is an object meant to be used with the `UnsafeDescriptorPool`.
32 pub struct UnsafeDescriptorSet {
33     pub(super) set: ash::vk::DescriptorSet,
34 }
35 
36 impl UnsafeDescriptorSet {
37     // TODO: add copying from other descriptor sets
38     //       add a `copy` method that just takes a copy, and an `update` method that takes both
39     //       writes and copies and that actually performs the operation
40 
41     /// Modifies a descriptor set. Doesn't check that the writes or copies are correct, and
42     /// doesn't check whether the descriptor set is in use.
43     ///
44     /// **Important**: You must ensure that the `DescriptorSetLayout` object is alive before
45     /// updating a descriptor set.
46     ///
47     /// # Safety
48     ///
49     /// - The `Device` must be the device the pool of this set was created with.
50     /// - The `DescriptorSetLayout` object this set was created with must be alive.
51     /// - Doesn't verify that the things you write in the descriptor set match its layout.
52     /// - Doesn't keep the resources alive. You have to do that yourself.
53     /// - Updating a descriptor set obeys synchronization rules that aren't checked here. Once a
54     ///   command buffer contains a pointer/reference to a descriptor set, it is illegal to write
55     ///   to it.
56     ///
write<I>(&mut self, device: &Device, writes: I) where I: Iterator<Item = DescriptorWrite>,57     pub unsafe fn write<I>(&mut self, device: &Device, writes: I)
58     where
59         I: Iterator<Item = DescriptorWrite>,
60     {
61         let fns = device.fns();
62 
63         // In this function, we build 4 arrays: one array of image descriptors (image_descriptors),
64         // one for buffer descriptors (buffer_descriptors), one for buffer view descriptors
65         // (buffer_views_descriptors), and one for the final list of writes (raw_writes).
66         // Only the final list is passed to Vulkan, but it will contain pointers to the first three
67         // lists in `pImageInfo`, `pBufferInfo` and `pTexelBufferView`.
68         //
69         // In order to handle that, we start by writing null pointers as placeholders in the final
70         // writes, and we store in `raw_writes_img_infos`, `raw_writes_buf_infos` and
71         // `raw_writes_buf_view_infos` the offsets of the pointers compared to the start of the
72         // list.
73         // Once we have finished iterating all the writes requested by the user, we modify
74         // `raw_writes` to point to the correct locations.
75 
76         let mut buffer_descriptors: SmallVec<[_; 64]> = SmallVec::new();
77         let mut image_descriptors: SmallVec<[_; 64]> = SmallVec::new();
78         let mut buffer_views_descriptors: SmallVec<[_; 64]> = SmallVec::new();
79 
80         let mut raw_writes: SmallVec<[_; 64]> = SmallVec::new();
81         let mut raw_writes_img_infos: SmallVec<[_; 64]> = SmallVec::new();
82         let mut raw_writes_buf_infos: SmallVec<[_; 64]> = SmallVec::new();
83         let mut raw_writes_buf_view_infos: SmallVec<[_; 64]> = SmallVec::new();
84 
85         for indiv_write in writes {
86             // Since the `DescriptorWrite` objects are built only through functions, we know for
87             // sure that it's impossible to have an empty descriptor write.
88             debug_assert!(!indiv_write.inner.is_empty());
89 
90             // The whole struct thats written here is valid, except for pImageInfo, pBufferInfo
91             // and pTexelBufferView which are placeholder values.
92             raw_writes.push(ash::vk::WriteDescriptorSet {
93                 dst_set: self.set,
94                 dst_binding: indiv_write.binding,
95                 dst_array_element: indiv_write.first_array_element,
96                 descriptor_count: indiv_write.inner.len() as u32,
97                 descriptor_type: indiv_write.ty().into(),
98                 p_image_info: ptr::null(),
99                 p_buffer_info: ptr::null(),
100                 p_texel_buffer_view: ptr::null(),
101                 ..Default::default()
102             });
103 
104             match indiv_write.inner[0] {
105                 DescriptorWriteInner::Sampler(_)
106                 | DescriptorWriteInner::CombinedImageSampler(_, _, _)
107                 | DescriptorWriteInner::SampledImage(_, _)
108                 | DescriptorWriteInner::StorageImage(_, _)
109                 | DescriptorWriteInner::InputAttachment(_, _) => {
110                     raw_writes_img_infos.push(Some(image_descriptors.len()));
111                     raw_writes_buf_infos.push(None);
112                     raw_writes_buf_view_infos.push(None);
113                 }
114                 DescriptorWriteInner::UniformBuffer(_, _, _)
115                 | DescriptorWriteInner::StorageBuffer(_, _, _)
116                 | DescriptorWriteInner::DynamicUniformBuffer(_, _, _)
117                 | DescriptorWriteInner::DynamicStorageBuffer(_, _, _) => {
118                     raw_writes_img_infos.push(None);
119                     raw_writes_buf_infos.push(Some(buffer_descriptors.len()));
120                     raw_writes_buf_view_infos.push(None);
121                 }
122                 DescriptorWriteInner::UniformTexelBuffer(_)
123                 | DescriptorWriteInner::StorageTexelBuffer(_) => {
124                     raw_writes_img_infos.push(None);
125                     raw_writes_buf_infos.push(None);
126                     raw_writes_buf_view_infos.push(Some(buffer_views_descriptors.len()));
127                 }
128             }
129 
130             for elem in indiv_write.inner.iter() {
131                 match *elem {
132                     DescriptorWriteInner::UniformBuffer(buffer, offset, size)
133                     | DescriptorWriteInner::DynamicUniformBuffer(buffer, offset, size) => {
134                         buffer_descriptors.push(ash::vk::DescriptorBufferInfo {
135                             buffer,
136                             offset,
137                             range: size,
138                         });
139                     }
140                     DescriptorWriteInner::StorageBuffer(buffer, offset, size)
141                     | DescriptorWriteInner::DynamicStorageBuffer(buffer, offset, size) => {
142                         buffer_descriptors.push(ash::vk::DescriptorBufferInfo {
143                             buffer,
144                             offset,
145                             range: size,
146                         });
147                     }
148                     DescriptorWriteInner::Sampler(sampler) => {
149                         image_descriptors.push(ash::vk::DescriptorImageInfo {
150                             sampler,
151                             image_view: ash::vk::ImageView::null(),
152                             image_layout: ash::vk::ImageLayout::UNDEFINED,
153                         });
154                     }
155                     DescriptorWriteInner::CombinedImageSampler(sampler, view, layout) => {
156                         image_descriptors.push(ash::vk::DescriptorImageInfo {
157                             sampler,
158                             image_view: view,
159                             image_layout: layout,
160                         });
161                     }
162                     DescriptorWriteInner::StorageImage(view, layout) => {
163                         image_descriptors.push(ash::vk::DescriptorImageInfo {
164                             sampler: ash::vk::Sampler::null(),
165                             image_view: view,
166                             image_layout: layout,
167                         });
168                     }
169                     DescriptorWriteInner::SampledImage(view, layout) => {
170                         image_descriptors.push(ash::vk::DescriptorImageInfo {
171                             sampler: ash::vk::Sampler::null(),
172                             image_view: view,
173                             image_layout: layout,
174                         });
175                     }
176                     DescriptorWriteInner::InputAttachment(view, layout) => {
177                         image_descriptors.push(ash::vk::DescriptorImageInfo {
178                             sampler: ash::vk::Sampler::null(),
179                             image_view: view,
180                             image_layout: layout,
181                         });
182                     }
183                     DescriptorWriteInner::UniformTexelBuffer(view)
184                     | DescriptorWriteInner::StorageTexelBuffer(view) => {
185                         buffer_views_descriptors.push(view);
186                     }
187                 }
188             }
189         }
190 
191         // Now that `image_descriptors`, `buffer_descriptors` and `buffer_views_descriptors` are
192         // entirely filled and will never move again, we can fill the pointers in `raw_writes`.
193         for (i, write) in raw_writes.iter_mut().enumerate() {
194             write.p_image_info = match raw_writes_img_infos[i] {
195                 Some(off) => image_descriptors.as_ptr().offset(off as isize),
196                 None => ptr::null(),
197             };
198 
199             write.p_buffer_info = match raw_writes_buf_infos[i] {
200                 Some(off) => buffer_descriptors.as_ptr().offset(off as isize),
201                 None => ptr::null(),
202             };
203 
204             write.p_texel_buffer_view = match raw_writes_buf_view_infos[i] {
205                 Some(off) => buffer_views_descriptors.as_ptr().offset(off as isize),
206                 None => ptr::null(),
207             };
208         }
209 
210         // It is forbidden to call `vkUpdateDescriptorSets` with 0 writes, so we need to perform
211         // this emptiness check.
212         if !raw_writes.is_empty() {
213             fns.v1_0.update_descriptor_sets(
214                 device.internal_object(),
215                 raw_writes.len() as u32,
216                 raw_writes.as_ptr(),
217                 0,
218                 ptr::null(),
219             );
220         }
221     }
222 }
223 
224 unsafe impl VulkanObject for UnsafeDescriptorSet {
225     type Object = ash::vk::DescriptorSet;
226 
227     #[inline]
internal_object(&self) -> ash::vk::DescriptorSet228     fn internal_object(&self) -> ash::vk::DescriptorSet {
229         self.set
230     }
231 }
232 
233 impl fmt::Debug for UnsafeDescriptorSet {
fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error>234     fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
235         write!(fmt, "<Vulkan descriptor set {:?}>", self.set)
236     }
237 }
238 
239 /// Represents a single write entry to a descriptor set.
240 ///
241 /// Use the various constructors to build a `DescriptorWrite`. While it is safe to build a
242 /// `DescriptorWrite`, it is unsafe to actually use it to write to a descriptor set.
243 // TODO: allow binding whole arrays at once
244 pub struct DescriptorWrite {
245     binding: u32,
246     first_array_element: u32,
247     inner: SmallVec<[DescriptorWriteInner; 1]>,
248 }
249 
250 #[derive(Debug, Clone)]
251 enum DescriptorWriteInner {
252     Sampler(ash::vk::Sampler),
253     StorageImage(ash::vk::ImageView, ash::vk::ImageLayout),
254     SampledImage(ash::vk::ImageView, ash::vk::ImageLayout),
255     CombinedImageSampler(ash::vk::Sampler, ash::vk::ImageView, ash::vk::ImageLayout),
256     UniformTexelBuffer(ash::vk::BufferView),
257     StorageTexelBuffer(ash::vk::BufferView),
258     UniformBuffer(ash::vk::Buffer, DeviceSize, DeviceSize),
259     StorageBuffer(ash::vk::Buffer, DeviceSize, DeviceSize),
260     DynamicUniformBuffer(ash::vk::Buffer, DeviceSize, DeviceSize),
261     DynamicStorageBuffer(ash::vk::Buffer, DeviceSize, DeviceSize),
262     InputAttachment(ash::vk::ImageView, ash::vk::ImageLayout),
263 }
264 
265 macro_rules! smallvec {
266     ($elem:expr) => {{
267         let mut s = SmallVec::new();
268         s.push($elem);
269         s
270     }};
271 }
272 
273 impl DescriptorWrite {
274     #[inline]
storage_image<I>(binding: u32, array_element: u32, image_view: &I) -> DescriptorWrite where I: ImageViewAbstract,275     pub fn storage_image<I>(binding: u32, array_element: u32, image_view: &I) -> DescriptorWrite
276     where
277         I: ImageViewAbstract,
278     {
279         let layouts = image_view
280             .image()
281             .descriptor_layouts()
282             .expect("descriptor_layouts must return Some when used in an image view");
283 
284         DescriptorWrite {
285             binding,
286             first_array_element: array_element,
287             inner: smallvec!({
288                 DescriptorWriteInner::StorageImage(
289                     image_view.inner().internal_object(),
290                     layouts.storage_image.into(),
291                 )
292             }),
293         }
294     }
295 
296     #[inline]
sampler(binding: u32, array_element: u32, sampler: &Arc<Sampler>) -> DescriptorWrite297     pub fn sampler(binding: u32, array_element: u32, sampler: &Arc<Sampler>) -> DescriptorWrite {
298         DescriptorWrite {
299             binding,
300             first_array_element: array_element,
301             inner: smallvec!(DescriptorWriteInner::Sampler(sampler.internal_object())),
302         }
303     }
304 
305     #[inline]
sampled_image<I>(binding: u32, array_element: u32, image_view: &I) -> DescriptorWrite where I: ImageViewAbstract,306     pub fn sampled_image<I>(binding: u32, array_element: u32, image_view: &I) -> DescriptorWrite
307     where
308         I: ImageViewAbstract,
309     {
310         let layouts = image_view
311             .image()
312             .descriptor_layouts()
313             .expect("descriptor_layouts must return Some when used in an image view");
314 
315         DescriptorWrite {
316             binding,
317             first_array_element: array_element,
318             inner: smallvec!({
319                 DescriptorWriteInner::SampledImage(
320                     image_view.inner().internal_object(),
321                     layouts.sampled_image.into(),
322                 )
323             }),
324         }
325     }
326 
327     #[inline]
combined_image_sampler<I>( binding: u32, array_element: u32, sampler: &Arc<Sampler>, image_view: &I, ) -> DescriptorWrite where I: ImageViewAbstract,328     pub fn combined_image_sampler<I>(
329         binding: u32,
330         array_element: u32,
331         sampler: &Arc<Sampler>,
332         image_view: &I,
333     ) -> DescriptorWrite
334     where
335         I: ImageViewAbstract,
336     {
337         let layouts = image_view
338             .image()
339             .descriptor_layouts()
340             .expect("descriptor_layouts must return Some when used in an image view");
341 
342         DescriptorWrite {
343             binding,
344             first_array_element: array_element,
345             inner: smallvec!({
346                 DescriptorWriteInner::CombinedImageSampler(
347                     sampler.internal_object(),
348                     image_view.inner().internal_object(),
349                     layouts.combined_image_sampler.into(),
350                 )
351             }),
352         }
353     }
354 
355     #[inline]
uniform_texel_buffer<'a, B>( binding: u32, array_element: u32, view: &BufferView<B>, ) -> DescriptorWrite where B: BufferAccess,356     pub fn uniform_texel_buffer<'a, B>(
357         binding: u32,
358         array_element: u32,
359         view: &BufferView<B>,
360     ) -> DescriptorWrite
361     where
362         B: BufferAccess,
363     {
364         assert!(view.uniform_texel_buffer());
365 
366         DescriptorWrite {
367             binding,
368             first_array_element: array_element,
369             inner: smallvec!(DescriptorWriteInner::UniformTexelBuffer(
370                 view.internal_object()
371             )),
372         }
373     }
374 
375     #[inline]
storage_texel_buffer<'a, B>( binding: u32, array_element: u32, view: &BufferView<B>, ) -> DescriptorWrite where B: BufferAccess,376     pub fn storage_texel_buffer<'a, B>(
377         binding: u32,
378         array_element: u32,
379         view: &BufferView<B>,
380     ) -> DescriptorWrite
381     where
382         B: BufferAccess,
383     {
384         assert!(view.storage_texel_buffer());
385 
386         DescriptorWrite {
387             binding,
388             first_array_element: array_element,
389             inner: smallvec!(DescriptorWriteInner::StorageTexelBuffer(
390                 view.internal_object()
391             )),
392         }
393     }
394 
395     #[inline]
uniform_buffer<B>(binding: u32, array_element: u32, buffer: &B) -> DescriptorWrite where B: BufferAccess,396     pub unsafe fn uniform_buffer<B>(binding: u32, array_element: u32, buffer: &B) -> DescriptorWrite
397     where
398         B: BufferAccess,
399     {
400         let size = buffer.size();
401         let BufferInner { buffer, offset } = buffer.inner();
402 
403         debug_assert_eq!(
404             offset
405                 % buffer
406                     .device()
407                     .physical_device()
408                     .properties()
409                     .min_uniform_buffer_offset_alignment,
410             0
411         );
412         debug_assert!(
413             size <= buffer
414                 .device()
415                 .physical_device()
416                 .properties()
417                 .max_uniform_buffer_range as DeviceSize
418         );
419 
420         DescriptorWrite {
421             binding,
422             first_array_element: array_element,
423             inner: smallvec!({
424                 DescriptorWriteInner::UniformBuffer(buffer.internal_object(), offset, size)
425             }),
426         }
427     }
428 
429     #[inline]
storage_buffer<B>(binding: u32, array_element: u32, buffer: &B) -> DescriptorWrite where B: BufferAccess,430     pub unsafe fn storage_buffer<B>(binding: u32, array_element: u32, buffer: &B) -> DescriptorWrite
431     where
432         B: BufferAccess,
433     {
434         let size = buffer.size();
435         let BufferInner { buffer, offset } = buffer.inner();
436 
437         debug_assert_eq!(
438             offset
439                 % buffer
440                     .device()
441                     .physical_device()
442                     .properties()
443                     .min_storage_buffer_offset_alignment,
444             0
445         );
446         debug_assert!(
447             size <= buffer
448                 .device()
449                 .physical_device()
450                 .properties()
451                 .max_storage_buffer_range as DeviceSize
452         );
453 
454         DescriptorWrite {
455             binding,
456             first_array_element: array_element,
457             inner: smallvec!({
458                 DescriptorWriteInner::StorageBuffer(buffer.internal_object(), offset, size)
459             }),
460         }
461     }
462 
463     #[inline]
dynamic_uniform_buffer<B>( binding: u32, array_element: u32, buffer: &B, ) -> DescriptorWrite where B: BufferAccess,464     pub unsafe fn dynamic_uniform_buffer<B>(
465         binding: u32,
466         array_element: u32,
467         buffer: &B,
468     ) -> DescriptorWrite
469     where
470         B: BufferAccess,
471     {
472         let size = buffer.size();
473         let BufferInner { buffer, offset } = buffer.inner();
474 
475         debug_assert_eq!(
476             offset
477                 % buffer
478                     .device()
479                     .physical_device()
480                     .properties()
481                     .min_uniform_buffer_offset_alignment,
482             0
483         );
484         debug_assert!(
485             size <= buffer
486                 .device()
487                 .physical_device()
488                 .properties()
489                 .max_uniform_buffer_range as DeviceSize
490         );
491 
492         DescriptorWrite {
493             binding,
494             first_array_element: array_element,
495             inner: smallvec!(DescriptorWriteInner::DynamicUniformBuffer(
496                 buffer.internal_object(),
497                 offset,
498                 size
499             )),
500         }
501     }
502 
503     #[inline]
dynamic_storage_buffer<B>( binding: u32, array_element: u32, buffer: &B, ) -> DescriptorWrite where B: BufferAccess,504     pub unsafe fn dynamic_storage_buffer<B>(
505         binding: u32,
506         array_element: u32,
507         buffer: &B,
508     ) -> DescriptorWrite
509     where
510         B: BufferAccess,
511     {
512         let size = buffer.size();
513         let BufferInner { buffer, offset } = buffer.inner();
514 
515         debug_assert_eq!(
516             offset
517                 % buffer
518                     .device()
519                     .physical_device()
520                     .properties()
521                     .min_storage_buffer_offset_alignment,
522             0
523         );
524         debug_assert!(
525             size <= buffer
526                 .device()
527                 .physical_device()
528                 .properties()
529                 .max_storage_buffer_range as DeviceSize
530         );
531 
532         DescriptorWrite {
533             binding,
534             first_array_element: array_element,
535             inner: smallvec!(DescriptorWriteInner::DynamicStorageBuffer(
536                 buffer.internal_object(),
537                 offset,
538                 size
539             )),
540         }
541     }
542 
543     #[inline]
input_attachment<I>(binding: u32, array_element: u32, image_view: &I) -> DescriptorWrite where I: ImageViewAbstract,544     pub fn input_attachment<I>(binding: u32, array_element: u32, image_view: &I) -> DescriptorWrite
545     where
546         I: ImageViewAbstract,
547     {
548         let layouts = image_view
549             .image()
550             .descriptor_layouts()
551             .expect("descriptor_layouts must return Some when used in an image view");
552 
553         DescriptorWrite {
554             binding,
555             first_array_element: array_element,
556             inner: smallvec!({
557                 DescriptorWriteInner::InputAttachment(
558                     image_view.inner().internal_object(),
559                     layouts.input_attachment.into(),
560                 )
561             }),
562         }
563     }
564 
565     /// Returns the type corresponding to this write.
566     #[inline]
ty(&self) -> DescriptorType567     pub fn ty(&self) -> DescriptorType {
568         match self.inner[0] {
569             DescriptorWriteInner::Sampler(_) => DescriptorType::Sampler,
570             DescriptorWriteInner::CombinedImageSampler(_, _, _) => {
571                 DescriptorType::CombinedImageSampler
572             }
573             DescriptorWriteInner::SampledImage(_, _) => DescriptorType::SampledImage,
574             DescriptorWriteInner::StorageImage(_, _) => DescriptorType::StorageImage,
575             DescriptorWriteInner::UniformTexelBuffer(_) => DescriptorType::UniformTexelBuffer,
576             DescriptorWriteInner::StorageTexelBuffer(_) => DescriptorType::StorageTexelBuffer,
577             DescriptorWriteInner::UniformBuffer(_, _, _) => DescriptorType::UniformBuffer,
578             DescriptorWriteInner::StorageBuffer(_, _, _) => DescriptorType::StorageBuffer,
579             DescriptorWriteInner::DynamicUniformBuffer(_, _, _) => {
580                 DescriptorType::UniformBufferDynamic
581             }
582             DescriptorWriteInner::DynamicStorageBuffer(_, _, _) => {
583                 DescriptorType::StorageBufferDynamic
584             }
585             DescriptorWriteInner::InputAttachment(_, _) => DescriptorType::InputAttachment,
586         }
587     }
588 }
589