• 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::{
13     descriptor_set::{
14         layout::DescriptorSetLayout,
15         update::{DescriptorWriteInfo, WriteDescriptorSet},
16     },
17     device::DeviceOwned,
18     macros::impl_id_counter,
19     VulkanObject,
20 };
21 use smallvec::SmallVec;
22 use std::{
23     fmt::{Debug, Error as FmtError, Formatter},
24     num::NonZeroU64,
25     ptr,
26 };
27 
28 /// Low-level descriptor set.
29 ///
30 /// Contrary to most other objects in this library, this one doesn't free itself automatically and
31 /// doesn't hold the pool or the device it is associated to.
32 /// Instead it is an object meant to be used with the [`DescriptorPool`].
33 ///
34 /// [`DescriptorPool`]: super::pool::DescriptorPool
35 pub struct UnsafeDescriptorSet {
36     handle: ash::vk::DescriptorSet,
37     id: NonZeroU64,
38 }
39 
40 impl UnsafeDescriptorSet {
new(handle: ash::vk::DescriptorSet) -> Self41     pub(crate) fn new(handle: ash::vk::DescriptorSet) -> Self {
42         Self {
43             handle,
44             id: Self::next_id(),
45         }
46     }
47 
48     /// Modifies a descriptor set. Doesn't check that the writes or copies are correct, and
49     /// doesn't check whether the descriptor set is in use.
50     ///
51     /// # Safety
52     ///
53     /// - The `Device` must be the device the pool of this set was created with.
54     /// - Doesn't verify that the things you write in the descriptor set match its layout.
55     /// - Doesn't keep the resources alive. You have to do that yourself.
56     /// - Updating a descriptor set obeys synchronization rules that aren't checked here. Once a
57     ///   command buffer contains a pointer/reference to a descriptor set, it is illegal to write
58     ///   to it.
write<'a>( &mut self, layout: &DescriptorSetLayout, writes: impl IntoIterator<Item = &'a WriteDescriptorSet>, )59     pub unsafe fn write<'a>(
60         &mut self,
61         layout: &DescriptorSetLayout,
62         writes: impl IntoIterator<Item = &'a WriteDescriptorSet>,
63     ) {
64         let (infos, mut writes): (SmallVec<[_; 8]>, SmallVec<[_; 8]>) = writes
65             .into_iter()
66             .map(|write| {
67                 let descriptor_type = layout.bindings()[&write.binding()].descriptor_type;
68 
69                 (
70                     write.to_vulkan_info(descriptor_type),
71                     write.to_vulkan(self.handle, descriptor_type),
72                 )
73             })
74             .unzip();
75 
76         // It is forbidden to call `vkUpdateDescriptorSets` with 0 writes, so we need to perform
77         // this emptiness check.
78         if writes.is_empty() {
79             return;
80         }
81 
82         // Set the info pointers separately.
83         for (info, write) in infos.iter().zip(writes.iter_mut()) {
84             match info {
85                 DescriptorWriteInfo::Image(info) => {
86                     write.descriptor_count = info.len() as u32;
87                     write.p_image_info = info.as_ptr();
88                 }
89                 DescriptorWriteInfo::Buffer(info) => {
90                     write.descriptor_count = info.len() as u32;
91                     write.p_buffer_info = info.as_ptr();
92                 }
93                 DescriptorWriteInfo::BufferView(info) => {
94                     write.descriptor_count = info.len() as u32;
95                     write.p_texel_buffer_view = info.as_ptr();
96                 }
97             }
98 
99             debug_assert!(write.descriptor_count != 0);
100         }
101 
102         let fns = layout.device().fns();
103 
104         (fns.v1_0.update_descriptor_sets)(
105             layout.device().handle(),
106             writes.len() as u32,
107             writes.as_ptr(),
108             0,
109             ptr::null(),
110         );
111     }
112 
113     // TODO: add copying from other descriptor sets
114     //       add a `copy` method that just takes a copy, and an `update` method that takes both
115     //       writes and copies and that actually performs the operation
116 }
117 
118 unsafe impl VulkanObject for UnsafeDescriptorSet {
119     type Handle = ash::vk::DescriptorSet;
120 
121     #[inline]
handle(&self) -> Self::Handle122     fn handle(&self) -> Self::Handle {
123         self.handle
124     }
125 }
126 
127 impl Debug for UnsafeDescriptorSet {
fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError>128     fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
129         write!(f, "<Vulkan descriptor set {:?}>", self.handle)
130     }
131 }
132 
133 impl_id_counter!(UnsafeDescriptorSet);
134