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