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