1 // Copyright (c) 2021 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 //! Describes the layout of all descriptors within a descriptor set. 11 //! 12 //! When creating a new descriptor set, you must provide a *layout* object to create it from. 13 14 use crate::{ 15 device::{Device, DeviceOwned}, 16 macros::{impl_id_counter, vulkan_enum}, 17 sampler::Sampler, 18 shader::{DescriptorBindingRequirements, ShaderStages}, 19 OomError, RequirementNotMet, RequiresOneOf, Version, VulkanError, VulkanObject, 20 }; 21 use ahash::HashMap; 22 use std::{ 23 collections::BTreeMap, 24 error::Error, 25 fmt::{Display, Error as FmtError, Formatter}, 26 mem::MaybeUninit, 27 num::NonZeroU64, 28 ptr, 29 sync::Arc, 30 }; 31 32 /// Describes to the Vulkan implementation the layout of all descriptors within a descriptor set. 33 #[derive(Debug)] 34 pub struct DescriptorSetLayout { 35 handle: ash::vk::DescriptorSetLayout, 36 device: Arc<Device>, 37 id: NonZeroU64, 38 39 bindings: BTreeMap<u32, DescriptorSetLayoutBinding>, 40 push_descriptor: bool, 41 42 descriptor_counts: HashMap<DescriptorType, u32>, 43 } 44 45 impl DescriptorSetLayout { 46 /// Creates a new `DescriptorSetLayout`. 47 #[inline] new( device: Arc<Device>, mut create_info: DescriptorSetLayoutCreateInfo, ) -> Result<Arc<DescriptorSetLayout>, DescriptorSetLayoutCreationError>48 pub fn new( 49 device: Arc<Device>, 50 mut create_info: DescriptorSetLayoutCreateInfo, 51 ) -> Result<Arc<DescriptorSetLayout>, DescriptorSetLayoutCreationError> { 52 let descriptor_counts = Self::validate(&device, &mut create_info)?; 53 let handle = unsafe { Self::create(&device, &create_info)? }; 54 55 let DescriptorSetLayoutCreateInfo { 56 bindings, 57 push_descriptor, 58 _ne: _, 59 } = create_info; 60 61 Ok(Arc::new(DescriptorSetLayout { 62 handle, 63 device, 64 id: Self::next_id(), 65 bindings, 66 push_descriptor, 67 descriptor_counts, 68 })) 69 } 70 71 /// Creates a new `DescriptorSetLayout` from a raw object handle. 72 /// 73 /// # Safety 74 /// 75 /// - `handle` must be a valid Vulkan object handle created from `device`. 76 /// - `create_info` must match the info used to create the object. 77 #[inline] from_handle( device: Arc<Device>, handle: ash::vk::DescriptorSetLayout, create_info: DescriptorSetLayoutCreateInfo, ) -> Arc<DescriptorSetLayout>78 pub unsafe fn from_handle( 79 device: Arc<Device>, 80 handle: ash::vk::DescriptorSetLayout, 81 create_info: DescriptorSetLayoutCreateInfo, 82 ) -> Arc<DescriptorSetLayout> { 83 let DescriptorSetLayoutCreateInfo { 84 bindings, 85 push_descriptor, 86 _ne: _, 87 } = create_info; 88 89 let mut descriptor_counts = HashMap::default(); 90 for binding in bindings.values() { 91 if binding.descriptor_count != 0 { 92 *descriptor_counts 93 .entry(binding.descriptor_type) 94 .or_default() += binding.descriptor_count; 95 } 96 } 97 98 Arc::new(DescriptorSetLayout { 99 handle, 100 device, 101 id: Self::next_id(), 102 bindings, 103 push_descriptor, 104 descriptor_counts, 105 }) 106 } 107 validate( device: &Device, create_info: &mut DescriptorSetLayoutCreateInfo, ) -> Result<HashMap<DescriptorType, u32>, DescriptorSetLayoutCreationError>108 fn validate( 109 device: &Device, 110 create_info: &mut DescriptorSetLayoutCreateInfo, 111 ) -> Result<HashMap<DescriptorType, u32>, DescriptorSetLayoutCreationError> { 112 let &mut DescriptorSetLayoutCreateInfo { 113 ref bindings, 114 push_descriptor, 115 _ne: _, 116 } = create_info; 117 118 let mut descriptor_counts = HashMap::default(); 119 120 if push_descriptor { 121 if !device.enabled_extensions().khr_push_descriptor { 122 return Err(DescriptorSetLayoutCreationError::RequirementNotMet { 123 required_for: "`create_info.push_descriptor` is set", 124 requires_one_of: RequiresOneOf { 125 device_extensions: &["khr_push_descriptor"], 126 ..Default::default() 127 }, 128 }); 129 } 130 } 131 132 let highest_binding_num = bindings.keys().copied().next_back(); 133 134 for (&binding_num, binding) in bindings.iter() { 135 let &DescriptorSetLayoutBinding { 136 descriptor_type, 137 descriptor_count, 138 variable_descriptor_count, 139 stages, 140 ref immutable_samplers, 141 _ne: _, 142 } = binding; 143 144 // VUID-VkDescriptorSetLayoutBinding-descriptorType-parameter 145 descriptor_type.validate_device(device)?; 146 147 if descriptor_count != 0 { 148 // VUID-VkDescriptorSetLayoutBinding-descriptorCount-00283 149 stages.validate_device(device)?; 150 151 *descriptor_counts.entry(descriptor_type).or_default() += descriptor_count; 152 } 153 154 if push_descriptor { 155 // VUID-VkDescriptorSetLayoutCreateInfo-flags-00280 156 if matches!( 157 descriptor_type, 158 DescriptorType::StorageBufferDynamic | DescriptorType::UniformBufferDynamic 159 ) { 160 return Err( 161 DescriptorSetLayoutCreationError::PushDescriptorDescriptorTypeIncompatible { 162 binding_num, 163 }, 164 ); 165 } 166 167 // VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-flags-03003 168 if variable_descriptor_count { 169 return Err( 170 DescriptorSetLayoutCreationError::PushDescriptorVariableDescriptorCount { 171 binding_num, 172 }, 173 ); 174 } 175 } 176 177 if !immutable_samplers.is_empty() { 178 if immutable_samplers 179 .iter() 180 .any(|sampler| sampler.sampler_ycbcr_conversion().is_some()) 181 { 182 if !matches!(descriptor_type, DescriptorType::CombinedImageSampler) { 183 return Err( 184 DescriptorSetLayoutCreationError::ImmutableSamplersDescriptorTypeIncompatible { 185 binding_num, 186 }, 187 ); 188 } 189 } else { 190 if !matches!( 191 descriptor_type, 192 DescriptorType::Sampler | DescriptorType::CombinedImageSampler 193 ) { 194 return Err( 195 DescriptorSetLayoutCreationError::ImmutableSamplersDescriptorTypeIncompatible { 196 binding_num, 197 }, 198 ); 199 } 200 } 201 202 // VUID-VkDescriptorSetLayoutBinding-descriptorType-00282 203 if descriptor_count != immutable_samplers.len() as u32 { 204 return Err( 205 DescriptorSetLayoutCreationError::ImmutableSamplersCountMismatch { 206 binding_num, 207 sampler_count: immutable_samplers.len() as u32, 208 descriptor_count, 209 }, 210 ); 211 } 212 } 213 214 // VUID-VkDescriptorSetLayoutBinding-descriptorType-01510 215 // If descriptorType is VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT and descriptorCount is not 0, then stageFlags must be 0 or VK_SHADER_STAGE_FRAGMENT_BIT 216 217 if variable_descriptor_count { 218 // VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-descriptorBindingVariableDescriptorCount-03014 219 if !device 220 .enabled_features() 221 .descriptor_binding_variable_descriptor_count 222 { 223 return Err(DescriptorSetLayoutCreationError::RequirementNotMet { 224 required_for: "`create_info.bindings` has an element where \ 225 `variable_descriptor_count` is set", 226 requires_one_of: RequiresOneOf { 227 features: &["descriptor_binding_variable_descriptor_count"], 228 ..Default::default() 229 }, 230 }); 231 } 232 233 // VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-pBindingFlags-03004 234 if Some(binding_num) != highest_binding_num { 235 return Err( 236 DescriptorSetLayoutCreationError::VariableDescriptorCountBindingNotHighest { 237 binding_num, 238 highest_binding_num: highest_binding_num.unwrap(), 239 }, 240 ); 241 } 242 243 // VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-pBindingFlags-03015 244 if matches!( 245 descriptor_type, 246 DescriptorType::UniformBufferDynamic | DescriptorType::StorageBufferDynamic 247 ) { 248 return Err( 249 DescriptorSetLayoutCreationError::VariableDescriptorCountDescriptorTypeIncompatible { 250 binding_num, 251 }, 252 ); 253 } 254 } 255 } 256 257 // VUID-VkDescriptorSetLayoutCreateInfo-flags-00281 258 if push_descriptor 259 && descriptor_counts.values().copied().sum::<u32>() 260 > device 261 .physical_device() 262 .properties() 263 .max_push_descriptors 264 .unwrap_or(0) 265 { 266 return Err( 267 DescriptorSetLayoutCreationError::MaxPushDescriptorsExceeded { 268 provided: descriptor_counts.values().copied().sum(), 269 max_supported: device 270 .physical_device() 271 .properties() 272 .max_push_descriptors 273 .unwrap_or(0), 274 }, 275 ); 276 } 277 278 Ok(descriptor_counts) 279 } 280 create( device: &Device, create_info: &DescriptorSetLayoutCreateInfo, ) -> Result<ash::vk::DescriptorSetLayout, DescriptorSetLayoutCreationError>281 unsafe fn create( 282 device: &Device, 283 create_info: &DescriptorSetLayoutCreateInfo, 284 ) -> Result<ash::vk::DescriptorSetLayout, DescriptorSetLayoutCreationError> { 285 let &DescriptorSetLayoutCreateInfo { 286 ref bindings, 287 push_descriptor, 288 _ne: _, 289 } = create_info; 290 291 let mut bindings_vk = Vec::with_capacity(bindings.len()); 292 let mut binding_flags_vk = Vec::with_capacity(bindings.len()); 293 let mut immutable_samplers_vk: Vec<Box<[ash::vk::Sampler]>> = Vec::new(); // only to keep the arrays of handles alive 294 let mut flags = ash::vk::DescriptorSetLayoutCreateFlags::empty(); 295 296 if push_descriptor { 297 flags |= ash::vk::DescriptorSetLayoutCreateFlags::PUSH_DESCRIPTOR_KHR; 298 } 299 300 for (&binding_num, binding) in bindings.iter() { 301 let mut binding_flags = ash::vk::DescriptorBindingFlags::empty(); 302 303 let p_immutable_samplers = if !binding.immutable_samplers.is_empty() { 304 // VUID-VkDescriptorSetLayoutBinding-descriptorType-00282 305 let sampler_handles = binding 306 .immutable_samplers 307 .iter() 308 .map(|s| s.handle()) 309 .collect::<Vec<_>>() 310 .into_boxed_slice(); 311 let p_immutable_samplers = sampler_handles.as_ptr(); 312 immutable_samplers_vk.push(sampler_handles); 313 p_immutable_samplers 314 } else { 315 ptr::null() 316 }; 317 318 if binding.variable_descriptor_count { 319 binding_flags |= ash::vk::DescriptorBindingFlags::VARIABLE_DESCRIPTOR_COUNT; 320 } 321 322 // VUID-VkDescriptorSetLayoutCreateInfo-binding-00279 323 // Guaranteed by BTreeMap 324 bindings_vk.push(ash::vk::DescriptorSetLayoutBinding { 325 binding: binding_num, 326 descriptor_type: binding.descriptor_type.into(), 327 descriptor_count: binding.descriptor_count, 328 stage_flags: binding.stages.into(), 329 p_immutable_samplers, 330 }); 331 binding_flags_vk.push(binding_flags); 332 } 333 334 let mut binding_flags_create_info = if device.api_version() >= Version::V1_2 335 || device.enabled_extensions().ext_descriptor_indexing 336 { 337 Some(ash::vk::DescriptorSetLayoutBindingFlagsCreateInfo { 338 // VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-bindingCount-03002 339 binding_count: binding_flags_vk.len() as u32, 340 p_binding_flags: binding_flags_vk.as_ptr(), 341 ..Default::default() 342 }) 343 } else { 344 None 345 }; 346 347 let mut create_info = ash::vk::DescriptorSetLayoutCreateInfo { 348 flags, 349 binding_count: bindings_vk.len() as u32, 350 p_bindings: bindings_vk.as_ptr(), 351 ..Default::default() 352 }; 353 354 if let Some(binding_flags_create_info) = binding_flags_create_info.as_mut() { 355 binding_flags_create_info.p_next = create_info.p_next; 356 create_info.p_next = binding_flags_create_info as *const _ as *const _; 357 } 358 359 let handle = { 360 let fns = device.fns(); 361 let mut output = MaybeUninit::uninit(); 362 (fns.v1_0.create_descriptor_set_layout)( 363 device.handle(), 364 &create_info, 365 ptr::null(), 366 output.as_mut_ptr(), 367 ) 368 .result() 369 .map_err(VulkanError::from)?; 370 output.assume_init() 371 }; 372 373 Ok(handle) 374 } 375 id(&self) -> NonZeroU64376 pub(crate) fn id(&self) -> NonZeroU64 { 377 self.id 378 } 379 380 /// Returns the bindings of the descriptor set layout. 381 #[inline] bindings(&self) -> &BTreeMap<u32, DescriptorSetLayoutBinding>382 pub fn bindings(&self) -> &BTreeMap<u32, DescriptorSetLayoutBinding> { 383 &self.bindings 384 } 385 386 /// Returns whether the descriptor set layout is for push descriptors or regular descriptor 387 /// sets. 388 #[inline] push_descriptor(&self) -> bool389 pub fn push_descriptor(&self) -> bool { 390 self.push_descriptor 391 } 392 393 /// Returns the number of descriptors of each type. 394 /// 395 /// The map is guaranteed to not contain any elements with a count of `0`. 396 #[inline] descriptor_counts(&self) -> &HashMap<DescriptorType, u32>397 pub fn descriptor_counts(&self) -> &HashMap<DescriptorType, u32> { 398 &self.descriptor_counts 399 } 400 401 /// If the highest-numbered binding has a variable count, returns its `descriptor_count`. 402 /// Otherwise returns `0`. 403 #[inline] variable_descriptor_count(&self) -> u32404 pub fn variable_descriptor_count(&self) -> u32 { 405 self.bindings 406 .values() 407 .next_back() 408 .map(|binding| { 409 if binding.variable_descriptor_count { 410 binding.descriptor_count 411 } else { 412 0 413 } 414 }) 415 .unwrap_or(0) 416 } 417 418 /// Returns whether `self` is compatible with `other`. 419 /// 420 /// "Compatible" in this sense is defined by the Vulkan specification under the section 421 /// "Pipeline layout compatibility": either the two are the same descriptor set layout object, 422 /// or they must be identically defined to the Vulkan API. 423 #[inline] is_compatible_with(&self, other: &DescriptorSetLayout) -> bool424 pub fn is_compatible_with(&self, other: &DescriptorSetLayout) -> bool { 425 self == other 426 || (self.bindings == other.bindings && self.push_descriptor == other.push_descriptor) 427 } 428 } 429 430 impl Drop for DescriptorSetLayout { 431 #[inline] drop(&mut self)432 fn drop(&mut self) { 433 unsafe { 434 let fns = self.device.fns(); 435 (fns.v1_0.destroy_descriptor_set_layout)( 436 self.device.handle(), 437 self.handle, 438 ptr::null(), 439 ); 440 } 441 } 442 } 443 444 unsafe impl VulkanObject for DescriptorSetLayout { 445 type Handle = ash::vk::DescriptorSetLayout; 446 447 #[inline] handle(&self) -> Self::Handle448 fn handle(&self) -> Self::Handle { 449 self.handle 450 } 451 } 452 453 unsafe impl DeviceOwned for DescriptorSetLayout { 454 #[inline] device(&self) -> &Arc<Device>455 fn device(&self) -> &Arc<Device> { 456 &self.device 457 } 458 } 459 460 impl_id_counter!(DescriptorSetLayout); 461 462 /// Error related to descriptor set layout. 463 #[derive(Debug, Clone, PartialEq, Eq)] 464 pub enum DescriptorSetLayoutCreationError { 465 /// Out of Memory. 466 OomError(OomError), 467 468 RequirementNotMet { 469 required_for: &'static str, 470 requires_one_of: RequiresOneOf, 471 }, 472 473 /// A binding includes immutable samplers but their number differs from `descriptor_count`. 474 ImmutableSamplersCountMismatch { 475 binding_num: u32, 476 sampler_count: u32, 477 descriptor_count: u32, 478 }, 479 480 /// A binding includes immutable samplers but it has an incompatible `descriptor_type`. 481 ImmutableSamplersDescriptorTypeIncompatible { binding_num: u32 }, 482 483 /// More descriptors were provided in all bindings than the 484 /// [`max_push_descriptors`](crate::device::Properties::max_push_descriptors) limit. 485 MaxPushDescriptorsExceeded { provided: u32, max_supported: u32 }, 486 487 /// `push_descriptor` is enabled, but a binding has an incompatible `descriptor_type`. 488 PushDescriptorDescriptorTypeIncompatible { binding_num: u32 }, 489 490 /// `push_descriptor` is enabled, but a binding has `variable_descriptor_count` enabled. 491 PushDescriptorVariableDescriptorCount { binding_num: u32 }, 492 493 /// A binding has `variable_descriptor_count` enabled, but it is not the highest-numbered 494 /// binding. 495 VariableDescriptorCountBindingNotHighest { 496 binding_num: u32, 497 highest_binding_num: u32, 498 }, 499 500 /// A binding has `variable_descriptor_count` enabled, but it has an incompatible 501 /// `descriptor_type`. 502 VariableDescriptorCountDescriptorTypeIncompatible { binding_num: u32 }, 503 } 504 505 impl From<VulkanError> for DescriptorSetLayoutCreationError { from(error: VulkanError) -> Self506 fn from(error: VulkanError) -> Self { 507 Self::OomError(error.into()) 508 } 509 } 510 511 impl Error for DescriptorSetLayoutCreationError {} 512 513 impl Display for DescriptorSetLayoutCreationError { fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError>514 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { 515 match self { 516 Self::OomError(_) => { 517 write!(f, "out of memory") 518 } 519 Self::RequirementNotMet { 520 required_for, 521 requires_one_of, 522 } => write!( 523 f, 524 "a requirement was not met for: {}; requires one of: {}", 525 required_for, requires_one_of, 526 ), 527 Self::ImmutableSamplersCountMismatch { 528 binding_num, 529 sampler_count, 530 descriptor_count, 531 } => write!( 532 f, 533 "binding {} includes immutable samplers but their number ({}) differs from \ 534 `descriptor_count` ({})", 535 binding_num, sampler_count, descriptor_count, 536 ), 537 Self::ImmutableSamplersDescriptorTypeIncompatible { binding_num } => write!( 538 f, 539 "binding {} includes immutable samplers but it has an incompatible \ 540 `descriptor_type`", 541 binding_num, 542 ), 543 Self::MaxPushDescriptorsExceeded { 544 provided, 545 max_supported, 546 } => write!( 547 f, 548 "more descriptors were provided in all bindings ({}) than the \ 549 `max_push_descriptors` limit ({})", 550 provided, max_supported, 551 ), 552 Self::PushDescriptorDescriptorTypeIncompatible { binding_num } => write!( 553 f, 554 "`push_descriptor` is enabled, but binding {} has an incompatible \ 555 `descriptor_type`", 556 binding_num, 557 ), 558 Self::PushDescriptorVariableDescriptorCount { binding_num } => write!( 559 f, 560 "`push_descriptor` is enabled, but binding {} has `variable_descriptor_count` \ 561 enabled", 562 binding_num, 563 ), 564 Self::VariableDescriptorCountBindingNotHighest { 565 binding_num, 566 highest_binding_num, 567 } => write!( 568 f, 569 "binding {} has `variable_descriptor_count` enabled, but it is not the \ 570 highest-numbered binding ({})", 571 binding_num, highest_binding_num, 572 ), 573 Self::VariableDescriptorCountDescriptorTypeIncompatible { binding_num } => write!( 574 f, 575 "binding {} has `variable_descriptor_count` enabled, but it has an incompatible \ 576 `descriptor_type`", 577 binding_num, 578 ), 579 } 580 } 581 } 582 583 impl From<RequirementNotMet> for DescriptorSetLayoutCreationError { from(err: RequirementNotMet) -> Self584 fn from(err: RequirementNotMet) -> Self { 585 Self::RequirementNotMet { 586 required_for: err.required_for, 587 requires_one_of: err.requires_one_of, 588 } 589 } 590 } 591 592 /// Parameters to create a new `DescriptorSetLayout`. 593 #[derive(Clone, Debug)] 594 pub struct DescriptorSetLayoutCreateInfo { 595 /// The bindings of the desriptor set layout. These are specified according to binding number. 596 /// 597 /// It is generally advisable to keep the binding numbers low. Higher binding numbers may 598 /// use more memory inside Vulkan. 599 /// 600 /// The default value is empty. 601 pub bindings: BTreeMap<u32, DescriptorSetLayoutBinding>, 602 603 /// Whether the descriptor set layout should be created for push descriptors. 604 /// 605 /// If `true`, the layout can only be used for push descriptors, and if `false`, it can only 606 /// be used for regular descriptor sets. 607 /// 608 /// If set to `true`, the 609 /// [`khr_push_descriptor`](crate::device::DeviceExtensions::khr_push_descriptor) extension must 610 /// be enabled on the device, and there are several restrictions: 611 /// - There must be no bindings with a type of [`DescriptorType::UniformBufferDynamic`] 612 /// or [`DescriptorType::StorageBufferDynamic`]. 613 /// - There must be no bindings with `variable_descriptor_count` enabled. 614 /// - The total number of descriptors across all bindings must be less than the 615 /// [`max_push_descriptors`](crate::device::Properties::max_push_descriptors) limit. 616 /// 617 /// The default value is `false`. 618 pub push_descriptor: bool, 619 620 pub _ne: crate::NonExhaustive, 621 } 622 623 impl Default for DescriptorSetLayoutCreateInfo { 624 #[inline] default() -> Self625 fn default() -> Self { 626 Self { 627 bindings: BTreeMap::new(), 628 push_descriptor: false, 629 _ne: crate::NonExhaustive(()), 630 } 631 } 632 } 633 634 impl DescriptorSetLayoutCreateInfo { 635 /// Builds a list of `DescriptorSetLayoutCreateInfo` from an iterator of 636 /// `DescriptorBindingRequirements` originating from a shader. from_requirements<'a>( descriptor_requirements: impl IntoIterator< Item = ((u32, u32), &'a DescriptorBindingRequirements), >, ) -> Vec<Self>637 pub fn from_requirements<'a>( 638 descriptor_requirements: impl IntoIterator< 639 Item = ((u32, u32), &'a DescriptorBindingRequirements), 640 >, 641 ) -> Vec<Self> { 642 let mut create_infos: Vec<Self> = Vec::new(); 643 644 for ((set_num, binding_num), reqs) in descriptor_requirements { 645 let set_num = set_num as usize; 646 647 if set_num >= create_infos.len() { 648 create_infos.resize(set_num + 1, Self::default()); 649 } 650 651 let bindings = &mut create_infos[set_num].bindings; 652 bindings.insert(binding_num, reqs.into()); 653 } 654 655 create_infos 656 } 657 } 658 659 /// A binding in a descriptor set layout. 660 #[derive(Clone, Debug, PartialEq, Eq)] 661 pub struct DescriptorSetLayoutBinding { 662 /// The content and layout of each array element of a binding. 663 /// 664 /// There is no default value. 665 pub descriptor_type: DescriptorType, 666 667 /// How many descriptors (array elements) this binding is made of. 668 /// 669 /// If the binding is a single element rather than an array, then you must specify `1`. 670 /// 671 /// The default value is `1`. 672 pub descriptor_count: u32, 673 674 /// Whether the binding has a variable number of descriptors. 675 /// 676 /// If set to `true`, the [`descriptor_binding_variable_descriptor_count`] feature must be 677 /// enabled. The value of `descriptor_count` specifies the maximum number of descriptors 678 /// allowed. 679 /// 680 /// There may only be one binding with a variable count in a descriptor set, and it must be the 681 /// binding with the highest binding number. The `descriptor_type` must not be 682 /// [`DescriptorType::UniformBufferDynamic`] or [`DescriptorType::StorageBufferDynamic`]. 683 /// 684 /// The default value is `false`. 685 /// 686 /// [`descriptor_binding_variable_descriptor_count`]: crate::device::Features::descriptor_binding_variable_descriptor_count 687 pub variable_descriptor_count: bool, 688 689 /// Which shader stages are going to access the descriptors in this binding. 690 /// 691 /// The default value is [`ShaderStages::empty()`], which must be overridden. 692 pub stages: ShaderStages, 693 694 /// Samplers that are included as a fixed part of the descriptor set layout. Once bound, they 695 /// do not need to be provided when creating a descriptor set. 696 /// 697 /// The list must be either empty, or contain exactly `descriptor_count` samplers. It can only 698 /// be non-empty if `descriptor_type` is [`DescriptorType::Sampler`] or 699 /// [`DescriptorType::CombinedImageSampler`]. If any of the samplers has an attached sampler 700 /// YCbCr conversion, then only [`DescriptorType::CombinedImageSampler`] is allowed. 701 /// 702 /// The default value is empty. 703 pub immutable_samplers: Vec<Arc<Sampler>>, 704 705 pub _ne: crate::NonExhaustive, 706 } 707 708 impl DescriptorSetLayoutBinding { 709 /// Returns a `DescriptorSetLayoutBinding` with the given type. 710 #[inline] descriptor_type(descriptor_type: DescriptorType) -> Self711 pub fn descriptor_type(descriptor_type: DescriptorType) -> Self { 712 Self { 713 descriptor_type, 714 descriptor_count: 1, 715 variable_descriptor_count: false, 716 stages: ShaderStages::empty(), 717 immutable_samplers: Vec::new(), 718 _ne: crate::NonExhaustive(()), 719 } 720 } 721 722 /// Checks whether the descriptor of a pipeline layout `self` is compatible with the 723 /// requirements of a shader `other`. 724 #[inline] ensure_compatible_with_shader( &self, binding_requirements: &DescriptorBindingRequirements, ) -> Result<(), DescriptorRequirementsNotMet>725 pub fn ensure_compatible_with_shader( 726 &self, 727 binding_requirements: &DescriptorBindingRequirements, 728 ) -> Result<(), DescriptorRequirementsNotMet> { 729 let &DescriptorBindingRequirements { 730 ref descriptor_types, 731 descriptor_count, 732 image_format: _, 733 image_multisampled: _, 734 image_scalar_type: _, 735 image_view_type: _, 736 stages, 737 descriptors: _, 738 } = binding_requirements; 739 740 if !descriptor_types.contains(&self.descriptor_type) { 741 return Err(DescriptorRequirementsNotMet::DescriptorType { 742 required: descriptor_types.clone(), 743 obtained: self.descriptor_type, 744 }); 745 } 746 747 if let Some(required) = descriptor_count { 748 if self.descriptor_count < required { 749 return Err(DescriptorRequirementsNotMet::DescriptorCount { 750 required, 751 obtained: self.descriptor_count, 752 }); 753 } 754 } 755 756 if !self.stages.contains(stages) { 757 return Err(DescriptorRequirementsNotMet::ShaderStages { 758 required: stages, 759 obtained: self.stages, 760 }); 761 } 762 763 Ok(()) 764 } 765 } 766 767 impl From<&DescriptorBindingRequirements> for DescriptorSetLayoutBinding { 768 #[inline] from(reqs: &DescriptorBindingRequirements) -> Self769 fn from(reqs: &DescriptorBindingRequirements) -> Self { 770 Self { 771 descriptor_type: reqs.descriptor_types[0], 772 descriptor_count: reqs.descriptor_count.unwrap_or(0), 773 variable_descriptor_count: false, 774 stages: reqs.stages, 775 immutable_samplers: Vec::new(), 776 _ne: crate::NonExhaustive(()), 777 } 778 } 779 } 780 781 /// Error when checking whether the requirements for a binding have been met. 782 #[derive(Debug, Clone, PartialEq, Eq)] 783 pub enum DescriptorRequirementsNotMet { 784 /// The binding's `descriptor_type` is not one of those required. 785 DescriptorType { 786 required: Vec<DescriptorType>, 787 obtained: DescriptorType, 788 }, 789 790 /// The binding's `descriptor_count` is less than what is required. 791 DescriptorCount { required: u32, obtained: u32 }, 792 793 /// The binding's `stages` does not contain the stages that are required. 794 ShaderStages { 795 required: ShaderStages, 796 obtained: ShaderStages, 797 }, 798 } 799 800 impl Error for DescriptorRequirementsNotMet {} 801 802 impl Display for DescriptorRequirementsNotMet { fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError>803 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { 804 match self { 805 Self::DescriptorType { required, obtained } => write!( 806 f, 807 "the descriptor's type ({:?}) is not one of those required ({:?})", 808 obtained, required, 809 ), 810 Self::DescriptorCount { required, obtained } => write!( 811 f, 812 "the descriptor count ({}) is less than what is required ({})", 813 obtained, required, 814 ), 815 Self::ShaderStages { .. } => write!( 816 f, 817 "the descriptor's shader stages do not contain the stages that are required", 818 ), 819 } 820 } 821 } 822 823 vulkan_enum! { 824 #[non_exhaustive] 825 826 /// Describes what kind of resource may later be bound to a descriptor. 827 DescriptorType = DescriptorType(i32); 828 829 /// Describes how a `SampledImage` descriptor should be read. 830 Sampler = SAMPLER, 831 832 /// Combines `SampledImage` and `Sampler` in one descriptor. 833 CombinedImageSampler = COMBINED_IMAGE_SAMPLER, 834 835 /// Gives read-only access to an image via a sampler. The image must be combined with a sampler 836 /// inside the shader. 837 SampledImage = SAMPLED_IMAGE, 838 839 /// Gives read and/or write access to individual pixels in an image. The image cannot be 840 /// sampled, so you have exactly specify which pixel to read or write. 841 StorageImage = STORAGE_IMAGE, 842 843 /// Gives read-only access to the content of a buffer, interpreted as an array of texel data. 844 UniformTexelBuffer = UNIFORM_TEXEL_BUFFER, 845 846 /// Gives read and/or write access to the content of a buffer, interpreted as an array of texel 847 /// data. Less restrictive but sometimes slower than a uniform texel buffer. 848 StorageTexelBuffer = STORAGE_TEXEL_BUFFER, 849 850 /// Gives read-only access to the content of a buffer, interpreted as a structure. 851 UniformBuffer = UNIFORM_BUFFER, 852 853 /// Gives read and/or write access to the content of a buffer, interpreted as a structure. Less 854 /// restrictive but sometimes slower than a uniform buffer. 855 StorageBuffer = STORAGE_BUFFER, 856 857 /// As `UniformBuffer`, but the offset within the buffer is specified at the time the descriptor 858 /// set is bound, rather than when the descriptor set is updated. 859 UniformBufferDynamic = UNIFORM_BUFFER_DYNAMIC, 860 861 /// As `StorageBuffer`, but the offset within the buffer is specified at the time the descriptor 862 /// set is bound, rather than when the descriptor set is updated. 863 StorageBufferDynamic = STORAGE_BUFFER_DYNAMIC, 864 865 /// Gives access to an image inside a fragment shader via a render pass. You can only access the 866 /// pixel that is currently being processed by the fragment shader. 867 InputAttachment = INPUT_ATTACHMENT, 868 869 /* TODO: enable 870 // TODO: document 871 InlineUniformBlock = INLINE_UNIFORM_BLOCK { 872 api_version: V1_3, 873 device_extensions: [ext_inline_uniform_block], 874 },*/ 875 876 /* TODO: enable 877 // TODO: document 878 AccelerationStructure = ACCELERATION_STRUCTURE_KHR { 879 device_extensions: [khr_acceleration_structure], 880 },*/ 881 882 /* TODO: enable 883 // TODO: document 884 AccelerationStructureNV = ACCELERATION_STRUCTURE_NV { 885 device_extensions: [nv_ray_tracing], 886 },*/ 887 888 /* TODO: enable 889 // TODO: document 890 SampleWeightImage = SAMPLE_WEIGHT_IMAGE_QCOM { 891 device_extensions: [qcom_image_processing], 892 },*/ 893 894 /* TODO: enable 895 // TODO: document 896 BlockMatchImage = BLOCK_MATCH_IMAGE_QCOM { 897 device_extensions: [qcom_image_processing], 898 },*/ 899 900 /* TODO: enable 901 // TODO: document 902 Mutable = MUTABLE_VALVE { 903 device_extensions: [valve_mutable_descriptor_type], 904 },*/ 905 } 906 907 #[cfg(test)] 908 mod tests { 909 use crate::{ 910 descriptor_set::layout::{ 911 DescriptorSetLayout, DescriptorSetLayoutBinding, DescriptorSetLayoutCreateInfo, 912 DescriptorType, 913 }, 914 shader::ShaderStages, 915 }; 916 use ahash::HashMap; 917 918 #[test] empty()919 fn empty() { 920 let (device, _) = gfx_dev_and_queue!(); 921 let _layout = DescriptorSetLayout::new(device, Default::default()); 922 } 923 924 #[test] basic_create()925 fn basic_create() { 926 let (device, _) = gfx_dev_and_queue!(); 927 928 let sl = DescriptorSetLayout::new( 929 device, 930 DescriptorSetLayoutCreateInfo { 931 bindings: [( 932 0, 933 DescriptorSetLayoutBinding { 934 stages: ShaderStages::all_graphics(), 935 ..DescriptorSetLayoutBinding::descriptor_type(DescriptorType::UniformBuffer) 936 }, 937 )] 938 .into(), 939 ..Default::default() 940 }, 941 ) 942 .unwrap(); 943 944 assert_eq!( 945 sl.descriptor_counts(), 946 &[(DescriptorType::UniformBuffer, 1)] 947 .into_iter() 948 .collect::<HashMap<_, _>>(), 949 ); 950 } 951 } 952