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