• 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 use crate::check_errors;
11 use crate::descriptor_set::layout::DescriptorDesc;
12 use crate::descriptor_set::layout::DescriptorSetDesc;
13 use crate::descriptor_set::pool::DescriptorsCount;
14 use crate::device::Device;
15 use crate::device::DeviceOwned;
16 use crate::OomError;
17 use crate::VulkanObject;
18 use smallvec::SmallVec;
19 use std::mem::MaybeUninit;
20 use std::ptr;
21 use std::sync::Arc;
22 
23 /// Describes to the Vulkan implementation the layout of all descriptors within a descriptor set.
24 #[derive(Debug)]
25 pub struct DescriptorSetLayout {
26     // The layout.
27     handle: ash::vk::DescriptorSetLayout,
28     // The device this layout belongs to.
29     device: Arc<Device>,
30     // Descriptors.
31     desc: DescriptorSetDesc,
32     // Number of descriptors.
33     descriptors_count: DescriptorsCount,
34 }
35 
36 impl DescriptorSetLayout {
37     /// Builds a new `DescriptorSetLayout` with the given descriptors.
38     ///
39     /// The descriptors must be passed in the order of the bindings. In order words, descriptor
40     /// at bind point 0 first, then descriptor at bind point 1, and so on. If a binding must remain
41     /// empty, you can make the iterator yield `None` for an element.
new<D>(device: Arc<Device>, desc: D) -> Result<DescriptorSetLayout, OomError> where D: Into<DescriptorSetDesc>,42     pub fn new<D>(device: Arc<Device>, desc: D) -> Result<DescriptorSetLayout, OomError>
43     where
44         D: Into<DescriptorSetDesc>,
45     {
46         let desc = desc.into();
47         let mut descriptors_count = DescriptorsCount::zero();
48 
49         let bindings = desc
50             .bindings()
51             .iter()
52             .enumerate()
53             .filter_map(|(binding, desc)| {
54                 let desc = match desc {
55                     Some(d) => d,
56                     None => return None,
57                 };
58 
59                 // FIXME: it is not legal to pass eg. the TESSELLATION_SHADER bit when the device
60                 //        doesn't have tess shaders enabled
61 
62                 let ty = desc.ty.ty();
63                 descriptors_count.add_num(ty, desc.array_count);
64 
65                 Some(ash::vk::DescriptorSetLayoutBinding {
66                     binding: binding as u32,
67                     descriptor_type: ty.into(),
68                     descriptor_count: desc.array_count,
69                     stage_flags: desc.stages.into(),
70                     p_immutable_samplers: ptr::null(), // FIXME: not yet implemented
71                 })
72             })
73             .collect::<SmallVec<[_; 32]>>();
74 
75         // Note that it seems legal to have no descriptor at all in the set.
76 
77         let handle = unsafe {
78             let infos = ash::vk::DescriptorSetLayoutCreateInfo {
79                 flags: ash::vk::DescriptorSetLayoutCreateFlags::empty(),
80                 binding_count: bindings.len() as u32,
81                 p_bindings: bindings.as_ptr(),
82                 ..Default::default()
83             };
84 
85             let mut output = MaybeUninit::uninit();
86             let fns = device.fns();
87             check_errors(fns.v1_0.create_descriptor_set_layout(
88                 device.internal_object(),
89                 &infos,
90                 ptr::null(),
91                 output.as_mut_ptr(),
92             ))?;
93             output.assume_init()
94         };
95 
96         Ok(DescriptorSetLayout {
97             handle,
98             device,
99             desc,
100             descriptors_count,
101         })
102     }
103 
desc(&self) -> &DescriptorSetDesc104     pub(crate) fn desc(&self) -> &DescriptorSetDesc {
105         &self.desc
106     }
107 
108     /// Returns the number of descriptors of each type.
109     #[inline]
descriptors_count(&self) -> &DescriptorsCount110     pub fn descriptors_count(&self) -> &DescriptorsCount {
111         &self.descriptors_count
112     }
113 
114     /// Returns the number of binding slots in the set.
115     #[inline]
num_bindings(&self) -> usize116     pub fn num_bindings(&self) -> usize {
117         self.desc.bindings().len()
118     }
119 
120     /// Returns a description of a descriptor, or `None` if out of range.
121     #[inline]
descriptor(&self, binding: usize) -> Option<DescriptorDesc>122     pub fn descriptor(&self, binding: usize) -> Option<DescriptorDesc> {
123         self.desc.bindings().get(binding).cloned().unwrap_or(None)
124     }
125 }
126 
127 unsafe impl DeviceOwned for DescriptorSetLayout {
128     #[inline]
device(&self) -> &Arc<Device>129     fn device(&self) -> &Arc<Device> {
130         &self.device
131     }
132 }
133 
134 unsafe impl VulkanObject for DescriptorSetLayout {
135     type Object = ash::vk::DescriptorSetLayout;
136 
137     #[inline]
internal_object(&self) -> ash::vk::DescriptorSetLayout138     fn internal_object(&self) -> ash::vk::DescriptorSetLayout {
139         self.handle
140     }
141 }
142 
143 impl Drop for DescriptorSetLayout {
144     #[inline]
drop(&mut self)145     fn drop(&mut self) {
146         unsafe {
147             let fns = self.device.fns();
148             fns.v1_0.destroy_descriptor_set_layout(
149                 self.device.internal_object(),
150                 self.handle,
151                 ptr::null(),
152             );
153         }
154     }
155 }
156 
157 #[cfg(test)]
158 mod tests {
159     use crate::descriptor_set::layout::DescriptorBufferDesc;
160     use crate::descriptor_set::layout::DescriptorDesc;
161     use crate::descriptor_set::layout::DescriptorDescTy;
162     use crate::descriptor_set::layout::DescriptorSetDesc;
163     use crate::descriptor_set::layout::DescriptorSetLayout;
164     use crate::descriptor_set::pool::DescriptorsCount;
165     use crate::pipeline::shader::ShaderStages;
166     use std::iter;
167 
168     #[test]
empty()169     fn empty() {
170         let (device, _) = gfx_dev_and_queue!();
171         let _layout = DescriptorSetLayout::new(device, DescriptorSetDesc::empty());
172     }
173 
174     #[test]
basic_create()175     fn basic_create() {
176         let (device, _) = gfx_dev_and_queue!();
177 
178         let layout = DescriptorDesc {
179             ty: DescriptorDescTy::Buffer(DescriptorBufferDesc {
180                 dynamic: Some(false),
181                 storage: false,
182             }),
183             array_count: 1,
184             stages: ShaderStages::all_graphics(),
185             readonly: true,
186         };
187 
188         let sl = DescriptorSetLayout::new(
189             device.clone(),
190             DescriptorSetDesc::new(iter::once(Some(layout))),
191         )
192         .unwrap();
193 
194         assert_eq!(
195             sl.descriptors_count(),
196             &DescriptorsCount {
197                 uniform_buffer: 1,
198                 ..DescriptorsCount::zero()
199             }
200         );
201     }
202 }
203