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 //! Description of a single descriptor. 11 //! 12 //! This module contains traits and structs related to describing a single descriptor. A descriptor 13 //! is a slot where you can bind a buffer or an image so that it can be accessed from your shaders. 14 //! In order to specify which buffer or image to bind to a descriptor, see the `descriptor_set` 15 //! module. 16 //! 17 //! There are four different kinds of descriptors that give access to buffers: 18 //! 19 //! - Uniform texel buffers. Gives read-only access to the content of a buffer. Only supports 20 //! certain buffer formats. 21 //! - Storage texel buffers. Gives read and/or write access to the content of a buffer. Only 22 //! supports certain buffer formats. Less restrictive but sometimes slower than uniform texel 23 //! buffers. 24 //! - Uniform buffers. Gives read-only access to the content of a buffer. Less restrictive but 25 //! sometimes slower than uniform texel buffers. 26 //! - Storage buffers. Gives read and/or write access to the content of a buffer. Less restrictive 27 //! but sometimes slower than uniform buffers and storage texel buffers. 28 //! 29 //! There are five different kinds of descriptors related to images: 30 //! 31 //! - Storage images. Gives read and/or write access to individual pixels in an image. The image 32 //! cannot be sampled. In other words, you have exactly specify which pixel to read or write. 33 //! - Sampled images. Gives read-only access to an image. Before you can use a sampled image in a 34 //! a shader, you have to combine it with a sampler (see below). The sampler describes how 35 //! reading the image will behave. 36 //! - Samplers. Doesn't contain an image but a sampler object that describes how an image will be 37 //! accessed. This is meant to be combined with a sampled image (see above). 38 //! - Combined image and sampler. Similar to a sampled image, but also directly includes the 39 //! sampler which indicates how the sampling is done. 40 //! - Input attachments. The fastest but also most restrictive access to images. Must be integrated 41 //! in a render pass. Can only give access to the same pixel as the one you're processing. 42 //! 43 44 use crate::format::Format; 45 use crate::image::view::ImageViewType; 46 use crate::pipeline::shader::ShaderStages; 47 use crate::pipeline::shader::ShaderStagesSupersetError; 48 use crate::sync::AccessFlags; 49 use crate::sync::PipelineStages; 50 use smallvec::SmallVec; 51 use std::cmp; 52 use std::error; 53 use std::fmt; 54 55 #[derive(Clone, Debug, Default)] 56 pub struct DescriptorSetDesc { 57 descriptors: SmallVec<[Option<DescriptorDesc>; 32]>, 58 } 59 60 impl DescriptorSetDesc { 61 /// Builds a new `DescriptorSetDesc` with the given descriptors. 62 /// 63 /// The descriptors must be passed in the order of the bindings. In order words, descriptor 64 /// at bind point 0 first, then descriptor at bind point 1, and so on. If a binding must remain 65 /// empty, you can make the iterator yield `None` for an element. 66 #[inline] new<I>(descriptors: I) -> DescriptorSetDesc where I: IntoIterator<Item = Option<DescriptorDesc>>,67 pub fn new<I>(descriptors: I) -> DescriptorSetDesc 68 where 69 I: IntoIterator<Item = Option<DescriptorDesc>>, 70 { 71 DescriptorSetDesc { 72 descriptors: descriptors.into_iter().collect(), 73 } 74 } 75 76 /// Builds a new empty `DescriptorSetDesc`. 77 #[inline] empty() -> DescriptorSetDesc78 pub fn empty() -> DescriptorSetDesc { 79 DescriptorSetDesc { 80 descriptors: SmallVec::new(), 81 } 82 } 83 84 /// Returns the descriptors in the set. bindings(&self) -> &[Option<DescriptorDesc>]85 pub fn bindings(&self) -> &[Option<DescriptorDesc>] { 86 &self.descriptors 87 } 88 89 /// Returns the descriptor with the given binding number, or `None` if the binding is empty. 90 #[inline] descriptor(&self, num: usize) -> Option<&DescriptorDesc>91 pub fn descriptor(&self, num: usize) -> Option<&DescriptorDesc> { 92 self.descriptors.get(num).and_then(|b| b.as_ref()) 93 } 94 95 /// Builds the union of this layout description and another. 96 #[inline] union( first: &DescriptorSetDesc, second: &DescriptorSetDesc, ) -> Result<DescriptorSetDesc, ()>97 pub fn union( 98 first: &DescriptorSetDesc, 99 second: &DescriptorSetDesc, 100 ) -> Result<DescriptorSetDesc, ()> { 101 let num_bindings = cmp::max(first.descriptors.len(), second.descriptors.len()); 102 let descriptors = (0..num_bindings) 103 .map(|binding_num| { 104 DescriptorDesc::union( 105 first 106 .descriptors 107 .get(binding_num) 108 .map(|desc| desc.as_ref()) 109 .flatten(), 110 second 111 .descriptors 112 .get(binding_num) 113 .map(|desc| desc.as_ref()) 114 .flatten(), 115 ) 116 }) 117 .collect::<Result<_, ()>>()?; 118 Ok(DescriptorSetDesc { descriptors }) 119 } 120 121 /// Builds the union of multiple descriptor sets. union_multiple( first: &[DescriptorSetDesc], second: &[DescriptorSetDesc], ) -> Result<Vec<DescriptorSetDesc>, ()>122 pub fn union_multiple( 123 first: &[DescriptorSetDesc], 124 second: &[DescriptorSetDesc], 125 ) -> Result<Vec<DescriptorSetDesc>, ()> { 126 // Ewwwwwww 127 let empty = DescriptorSetDesc::empty(); 128 let num_sets = cmp::max(first.len(), second.len()); 129 130 (0..num_sets) 131 .map(|set_num| { 132 Ok(DescriptorSetDesc::union( 133 first.get(set_num).unwrap_or_else(|| &empty), 134 second.get(set_num).unwrap_or_else(|| &empty), 135 )?) 136 }) 137 .collect() 138 } 139 140 /// Transforms a `DescriptorSetDesc`. 141 /// 142 /// Used to adjust automatically inferred `DescriptorSetDesc`s with information that cannot be inferred. tweak<I>(&mut self, dynamic_buffers: I) where I: IntoIterator<Item = usize>,143 pub fn tweak<I>(&mut self, dynamic_buffers: I) 144 where 145 I: IntoIterator<Item = usize>, 146 { 147 for binding_num in dynamic_buffers { 148 debug_assert!( 149 self.descriptor(binding_num) 150 .map_or(false, |desc| match desc.ty { 151 DescriptorDescTy::Buffer(_) => true, 152 _ => false, 153 }), 154 "tried to make the non-buffer descriptor at binding {} a dynamic buffer", 155 binding_num 156 ); 157 158 let binding = self 159 .descriptors 160 .get_mut(binding_num) 161 .and_then(|b| b.as_mut()); 162 163 if let Some(desc) = binding { 164 if let DescriptorDescTy::Buffer(ref buffer_desc) = desc.ty { 165 desc.ty = DescriptorDescTy::Buffer(DescriptorBufferDesc { 166 dynamic: Some(true), 167 ..*buffer_desc 168 }); 169 } 170 } 171 } 172 } 173 tweak_multiple<I>(sets: &mut [DescriptorSetDesc], dynamic_buffers: I) where I: IntoIterator<Item = (usize, usize)>,174 pub fn tweak_multiple<I>(sets: &mut [DescriptorSetDesc], dynamic_buffers: I) 175 where 176 I: IntoIterator<Item = (usize, usize)>, 177 { 178 for (set_num, binding_num) in dynamic_buffers { 179 debug_assert!( 180 set_num < sets.len(), 181 "tried to make a dynamic buffer in the nonexistent set {}", 182 set_num, 183 ); 184 185 sets.get_mut(set_num).map(|set| set.tweak([binding_num])); 186 } 187 } 188 189 /// Returns whether `self` is a superset of `other`. ensure_superset_of( &self, other: &DescriptorSetDesc, ) -> Result<(), DescriptorSetDescSupersetError>190 pub fn ensure_superset_of( 191 &self, 192 other: &DescriptorSetDesc, 193 ) -> Result<(), DescriptorSetDescSupersetError> { 194 if self.descriptors.len() < other.descriptors.len() { 195 return Err(DescriptorSetDescSupersetError::DescriptorsCountMismatch { 196 self_num: self.descriptors.len() as u32, 197 other_num: other.descriptors.len() as u32, 198 }); 199 } 200 201 for binding_num in 0..other.descriptors.len() { 202 let self_desc = self.descriptor(binding_num); 203 let other_desc = self.descriptor(binding_num); 204 205 match (self_desc, other_desc) { 206 (Some(mine), Some(other)) => { 207 if let Err(err) = mine.ensure_superset_of(&other) { 208 return Err(DescriptorSetDescSupersetError::IncompatibleDescriptors { 209 error: err, 210 binding_num: binding_num as u32, 211 }); 212 } 213 } 214 (None, Some(_)) => { 215 return Err(DescriptorSetDescSupersetError::ExpectedEmptyDescriptor { 216 binding_num: binding_num as u32, 217 }) 218 } 219 _ => (), 220 } 221 } 222 223 Ok(()) 224 } 225 } 226 227 impl<I> From<I> for DescriptorSetDesc 228 where 229 I: IntoIterator<Item = Option<DescriptorDesc>>, 230 { 231 #[inline] from(val: I) -> Self232 fn from(val: I) -> Self { 233 DescriptorSetDesc { 234 descriptors: val.into_iter().collect(), 235 } 236 } 237 } 238 239 /// Contains the exact description of a single descriptor. 240 /// 241 /// > **Note**: You are free to fill a `DescriptorDesc` struct the way you want, but its validity 242 /// > will be checked when you create a pipeline layout, a descriptor set, or when you try to bind 243 /// > a descriptor set. 244 // TODO: add example 245 #[derive(Clone, Debug, PartialEq)] 246 pub struct DescriptorDesc { 247 /// Describes the content and layout of each array element of a descriptor. 248 pub ty: DescriptorDescTy, 249 250 /// How many array elements this descriptor is made of. The value 0 is invalid and may trigger 251 /// a panic depending on the situation. 252 pub array_count: u32, 253 254 /// Which shader stages are going to access this descriptor. 255 pub stages: ShaderStages, 256 257 /// True if the attachment is only ever read by the shader. False if it is also written. 258 pub readonly: bool, 259 } 260 261 impl DescriptorDesc { 262 /// Checks whether we are a superset of another descriptor. 263 /// 264 /// Returns true if `self` is the same descriptor as `other`, or if `self` is the same as 265 /// `other` but with a larger array elements count and/or more shader stages. 266 /// 267 ///# Example 268 ///``` 269 ///use vulkano::descriptor_set::layout::DescriptorDesc; 270 ///use vulkano::descriptor_set::layout::DescriptorDescTy::*; 271 ///use vulkano::pipeline::shader::ShaderStages; 272 /// 273 ///let desc_super = DescriptorDesc{ ty: Sampler, array_count: 2, stages: ShaderStages{ 274 /// vertex: true, 275 /// tessellation_control: true, 276 /// tessellation_evaluation: true, 277 /// geometry: true, 278 /// fragment: true, 279 /// compute: true 280 ///}, readonly: false }; 281 ///let desc_sub = DescriptorDesc{ ty: Sampler, array_count: 1, stages: ShaderStages{ 282 /// vertex: true, 283 /// tessellation_control: false, 284 /// tessellation_evaluation: false, 285 /// geometry: false, 286 /// fragment: true, 287 /// compute: false 288 ///}, readonly: true }; 289 /// 290 ///assert_eq!(desc_super.ensure_superset_of(&desc_sub).unwrap(), ()); 291 /// 292 ///``` 293 #[inline] ensure_superset_of( &self, other: &DescriptorDesc, ) -> Result<(), DescriptorDescSupersetError>294 pub fn ensure_superset_of( 295 &self, 296 other: &DescriptorDesc, 297 ) -> Result<(), DescriptorDescSupersetError> { 298 self.ty.ensure_superset_of(&other.ty)?; 299 self.stages.ensure_superset_of(&other.stages)?; 300 301 if self.array_count < other.array_count { 302 return Err(DescriptorDescSupersetError::ArrayTooSmall { 303 len: self.array_count, 304 required: other.array_count, 305 }); 306 } 307 308 if self.readonly && !other.readonly { 309 return Err(DescriptorDescSupersetError::MutabilityRequired); 310 } 311 312 Ok(()) 313 } 314 315 /// Builds a `DescriptorDesc` that is the union of `self` and `other`, if possible. 316 /// 317 /// The returned value will be a superset of both `self` and `other`, or `None` if both were 318 /// `None`. 319 /// 320 /// `Err` is returned if the descriptors are not compatible. 321 /// 322 ///# Example 323 ///``` 324 ///use vulkano::descriptor_set::layout::DescriptorDesc; 325 ///use vulkano::descriptor_set::layout::DescriptorDescTy::*; 326 ///use vulkano::pipeline::shader::ShaderStages; 327 /// 328 ///let desc_part1 = DescriptorDesc{ ty: Sampler, array_count: 2, stages: ShaderStages{ 329 /// vertex: true, 330 /// tessellation_control: true, 331 /// tessellation_evaluation: false, 332 /// geometry: true, 333 /// fragment: false, 334 /// compute: true 335 ///}, readonly: false }; 336 /// 337 ///let desc_part2 = DescriptorDesc{ ty: Sampler, array_count: 1, stages: ShaderStages{ 338 /// vertex: true, 339 /// tessellation_control: false, 340 /// tessellation_evaluation: true, 341 /// geometry: false, 342 /// fragment: true, 343 /// compute: true 344 ///}, readonly: true }; 345 /// 346 ///let desc_union = DescriptorDesc{ ty: Sampler, array_count: 2, stages: ShaderStages{ 347 /// vertex: true, 348 /// tessellation_control: true, 349 /// tessellation_evaluation: true, 350 /// geometry: true, 351 /// fragment: true, 352 /// compute: true 353 ///}, readonly: false }; 354 /// 355 ///assert_eq!(DescriptorDesc::union(Some(&desc_part1), Some(&desc_part2)), Ok(Some(desc_union))); 356 ///``` 357 #[inline] union( first: Option<&DescriptorDesc>, second: Option<&DescriptorDesc>, ) -> Result<Option<DescriptorDesc>, ()>358 pub fn union( 359 first: Option<&DescriptorDesc>, 360 second: Option<&DescriptorDesc>, 361 ) -> Result<Option<DescriptorDesc>, ()> { 362 if let (Some(first), Some(second)) = (first, second) { 363 if first.ty != second.ty { 364 return Err(()); 365 } 366 367 Ok(Some(DescriptorDesc { 368 ty: first.ty.clone(), 369 array_count: cmp::max(first.array_count, second.array_count), 370 stages: first.stages | second.stages, 371 readonly: first.readonly && second.readonly, 372 })) 373 } else { 374 Ok(first.or(second).cloned()) 375 } 376 } 377 378 /// Returns the pipeline stages and access flags corresponding to the usage of this descriptor. 379 /// 380 /// # Panic 381 /// 382 /// Panics if the type is `Sampler`. 383 /// pipeline_stages_and_access(&self) -> (PipelineStages, AccessFlags)384 pub fn pipeline_stages_and_access(&self) -> (PipelineStages, AccessFlags) { 385 let stages: PipelineStages = self.stages.into(); 386 387 let access = match self.ty { 388 DescriptorDescTy::Sampler => panic!(), 389 DescriptorDescTy::CombinedImageSampler(_) | DescriptorDescTy::Image(_) => AccessFlags { 390 shader_read: true, 391 shader_write: !self.readonly, 392 ..AccessFlags::none() 393 }, 394 DescriptorDescTy::TexelBuffer { .. } => AccessFlags { 395 shader_read: true, 396 shader_write: !self.readonly, 397 ..AccessFlags::none() 398 }, 399 DescriptorDescTy::InputAttachment { .. } => AccessFlags { 400 input_attachment_read: true, 401 ..AccessFlags::none() 402 }, 403 DescriptorDescTy::Buffer(ref buf) => { 404 if buf.storage { 405 AccessFlags { 406 shader_read: true, 407 shader_write: !self.readonly, 408 ..AccessFlags::none() 409 } 410 } else { 411 AccessFlags { 412 uniform_read: true, 413 ..AccessFlags::none() 414 } 415 } 416 } 417 }; 418 419 (stages, access) 420 } 421 } 422 423 /// Describes the content and layout of each array element of a descriptor. 424 #[derive(Debug, Clone, PartialEq, Eq)] 425 pub enum DescriptorDescTy { 426 Sampler, // TODO: the sampler has some restrictions as well 427 CombinedImageSampler(DescriptorImageDesc), // TODO: the sampler has some restrictions as well 428 Image(DescriptorImageDesc), 429 TexelBuffer { 430 /// If `true`, this describes a storage texel buffer. 431 storage: bool, 432 433 /// The format of the content, or `None` if the format is unknown. Depending on the 434 /// context, it may be invalid to have a `None` value here. If the format is `Some`, only 435 /// buffer views that have this exact format can be attached to this descriptor. 436 format: Option<Format>, 437 }, 438 InputAttachment { 439 /// If `true`, the input attachment is multisampled. Only multisampled images can be 440 /// attached to this descriptor. If `false`, only single-sampled images can be attached. 441 multisampled: bool, 442 array_layers: DescriptorImageDescArray, 443 }, 444 Buffer(DescriptorBufferDesc), 445 } 446 447 impl DescriptorDescTy { 448 /// Returns the type of descriptor. 449 // TODO: add example ty(&self) -> DescriptorType450 pub fn ty(&self) -> DescriptorType { 451 match *self { 452 DescriptorDescTy::Sampler => DescriptorType::Sampler, 453 DescriptorDescTy::CombinedImageSampler(_) => DescriptorType::CombinedImageSampler, 454 DescriptorDescTy::Image(ref desc) => { 455 if desc.sampled { 456 DescriptorType::SampledImage 457 } else { 458 DescriptorType::StorageImage 459 } 460 } 461 DescriptorDescTy::InputAttachment { .. } => DescriptorType::InputAttachment, 462 DescriptorDescTy::Buffer(ref desc) => { 463 let dynamic = desc.dynamic.unwrap_or(false); 464 match (desc.storage, dynamic) { 465 (false, false) => DescriptorType::UniformBuffer, 466 (true, false) => DescriptorType::StorageBuffer, 467 (false, true) => DescriptorType::UniformBufferDynamic, 468 (true, true) => DescriptorType::StorageBufferDynamic, 469 } 470 } 471 DescriptorDescTy::TexelBuffer { storage, .. } => { 472 if storage { 473 DescriptorType::StorageTexelBuffer 474 } else { 475 DescriptorType::UniformTexelBuffer 476 } 477 } 478 } 479 } 480 481 /// Checks whether we are a superset of another descriptor type. 482 // TODO: add example 483 #[inline] ensure_superset_of( &self, other: &DescriptorDescTy, ) -> Result<(), DescriptorDescSupersetError>484 pub fn ensure_superset_of( 485 &self, 486 other: &DescriptorDescTy, 487 ) -> Result<(), DescriptorDescSupersetError> { 488 match (self, other) { 489 (&DescriptorDescTy::Sampler, &DescriptorDescTy::Sampler) => Ok(()), 490 491 ( 492 &DescriptorDescTy::CombinedImageSampler(ref me), 493 &DescriptorDescTy::CombinedImageSampler(ref other), 494 ) => me.ensure_superset_of(other), 495 496 (&DescriptorDescTy::Image(ref me), &DescriptorDescTy::Image(ref other)) => { 497 me.ensure_superset_of(other) 498 } 499 500 ( 501 &DescriptorDescTy::InputAttachment { 502 multisampled: me_multisampled, 503 array_layers: me_array_layers, 504 }, 505 &DescriptorDescTy::InputAttachment { 506 multisampled: other_multisampled, 507 array_layers: other_array_layers, 508 }, 509 ) => { 510 if me_multisampled != other_multisampled { 511 return Err(DescriptorDescSupersetError::MultisampledMismatch { 512 provided: me_multisampled, 513 expected: other_multisampled, 514 }); 515 } 516 517 if me_array_layers != other_array_layers { 518 return Err(DescriptorDescSupersetError::IncompatibleArrayLayers { 519 provided: me_array_layers, 520 required: other_array_layers, 521 }); 522 } 523 524 Ok(()) 525 } 526 527 (&DescriptorDescTy::Buffer(ref me), &DescriptorDescTy::Buffer(ref other)) => { 528 if me.storage != other.storage { 529 return Err(DescriptorDescSupersetError::TypeMismatch); 530 } 531 532 match (me.dynamic, other.dynamic) { 533 (Some(_), None) => Ok(()), 534 (Some(m), Some(o)) => { 535 if m == o { 536 Ok(()) 537 } else { 538 Err(DescriptorDescSupersetError::TypeMismatch) 539 } 540 } 541 (None, None) => Ok(()), 542 (None, Some(_)) => Err(DescriptorDescSupersetError::TypeMismatch), 543 } 544 } 545 546 ( 547 &DescriptorDescTy::TexelBuffer { 548 storage: me_storage, 549 format: me_format, 550 }, 551 &DescriptorDescTy::TexelBuffer { 552 storage: other_storage, 553 format: other_format, 554 }, 555 ) => { 556 if me_storage != other_storage { 557 return Err(DescriptorDescSupersetError::TypeMismatch); 558 } 559 560 match (me_format, other_format) { 561 (Some(_), None) => Ok(()), 562 (Some(m), Some(o)) => { 563 if m == o { 564 Ok(()) 565 } else { 566 Err(DescriptorDescSupersetError::FormatMismatch { 567 provided: Some(m), 568 expected: o, 569 }) 570 } 571 } 572 (None, None) => Ok(()), 573 (None, Some(a)) => Err(DescriptorDescSupersetError::FormatMismatch { 574 provided: Some(a), 575 expected: a, 576 }), 577 } 578 } 579 580 // Any other combination is invalid. 581 _ => Err(DescriptorDescSupersetError::TypeMismatch), 582 } 583 } 584 } 585 586 /// Additional description for descriptors that contain images. 587 #[derive(Debug, Copy, Clone, PartialEq, Eq)] 588 pub struct DescriptorImageDesc { 589 /// If `true`, the image can be sampled by the shader. Only images that were created with the 590 /// `sampled` usage can be attached to the descriptor. 591 pub sampled: bool, 592 /// The kind of image: one-dimensional, two-dimensional, three-dimensional, or cube. 593 pub dimensions: DescriptorImageDescDimensions, 594 /// The format of the image, or `None` if the format is unknown. If `Some`, only images with 595 /// exactly that format can be attached. 596 pub format: Option<Format>, 597 /// True if the image is multisampled. 598 pub multisampled: bool, 599 /// Whether the descriptor contains one or more array layers of an image. 600 pub array_layers: DescriptorImageDescArray, 601 } 602 603 impl DescriptorImageDesc { 604 /// Checks whether we are a superset of another image. 605 // TODO: add example 606 #[inline] ensure_superset_of( &self, other: &DescriptorImageDesc, ) -> Result<(), DescriptorDescSupersetError>607 pub fn ensure_superset_of( 608 &self, 609 other: &DescriptorImageDesc, 610 ) -> Result<(), DescriptorDescSupersetError> { 611 if self.dimensions != other.dimensions { 612 return Err(DescriptorDescSupersetError::DimensionsMismatch { 613 provided: self.dimensions, 614 expected: other.dimensions, 615 }); 616 } 617 618 if self.multisampled != other.multisampled { 619 return Err(DescriptorDescSupersetError::MultisampledMismatch { 620 provided: self.multisampled, 621 expected: other.multisampled, 622 }); 623 } 624 625 match (self.format, other.format) { 626 (Some(a), Some(b)) => { 627 if a != b { 628 return Err(DescriptorDescSupersetError::FormatMismatch { 629 provided: Some(a), 630 expected: b, 631 }); 632 } 633 } 634 (Some(_), None) => (), 635 (None, None) => (), 636 (None, Some(a)) => { 637 return Err(DescriptorDescSupersetError::FormatMismatch { 638 provided: None, 639 expected: a, 640 }); 641 } 642 }; 643 644 match (self.array_layers, other.array_layers) { 645 (DescriptorImageDescArray::NonArrayed, DescriptorImageDescArray::NonArrayed) => (), 646 ( 647 DescriptorImageDescArray::Arrayed { max_layers: my_max }, 648 DescriptorImageDescArray::Arrayed { 649 max_layers: other_max, 650 }, 651 ) => { 652 match (my_max, other_max) { 653 (Some(m), Some(o)) => { 654 if m < o { 655 return Err(DescriptorDescSupersetError::IncompatibleArrayLayers { 656 provided: DescriptorImageDescArray::Arrayed { max_layers: my_max }, 657 required: DescriptorImageDescArray::Arrayed { 658 max_layers: other_max, 659 }, 660 }); 661 } 662 } 663 (Some(_), None) => (), 664 (None, Some(m)) => { 665 return Err(DescriptorDescSupersetError::IncompatibleArrayLayers { 666 provided: DescriptorImageDescArray::Arrayed { max_layers: my_max }, 667 required: DescriptorImageDescArray::Arrayed { 668 max_layers: other_max, 669 }, 670 }); 671 } 672 (None, None) => (), // TODO: is this correct? 673 }; 674 } 675 (a, b) => { 676 return Err(DescriptorDescSupersetError::IncompatibleArrayLayers { 677 provided: a, 678 required: b, 679 }) 680 } 681 }; 682 683 Ok(()) 684 } 685 } 686 687 // TODO: documentation 688 #[derive(Debug, Copy, Clone, PartialEq, Eq)] 689 pub enum DescriptorImageDescArray { 690 NonArrayed, 691 Arrayed { max_layers: Option<u32> }, 692 } 693 694 // TODO: documentation 695 #[derive(Debug, Copy, Clone, PartialEq, Eq)] 696 pub enum DescriptorImageDescDimensions { 697 OneDimensional, 698 TwoDimensional, 699 ThreeDimensional, 700 Cube, 701 } 702 703 impl DescriptorImageDescDimensions { 704 /// Builds the `DescriptorImageDescDimensions` that corresponds to the view type. 705 #[inline] from_image_view_type(ty: ImageViewType) -> DescriptorImageDescDimensions706 pub fn from_image_view_type(ty: ImageViewType) -> DescriptorImageDescDimensions { 707 match ty { 708 ImageViewType::Dim1d => DescriptorImageDescDimensions::OneDimensional, 709 ImageViewType::Dim1dArray => DescriptorImageDescDimensions::OneDimensional, 710 ImageViewType::Dim2d => DescriptorImageDescDimensions::TwoDimensional, 711 ImageViewType::Dim2dArray => DescriptorImageDescDimensions::TwoDimensional, 712 ImageViewType::Dim3d => DescriptorImageDescDimensions::ThreeDimensional, 713 ImageViewType::Cubemap => DescriptorImageDescDimensions::Cube, 714 ImageViewType::CubemapArray => DescriptorImageDescDimensions::Cube, 715 } 716 } 717 } 718 719 /// Additional description for descriptors that contain buffers. 720 #[derive(Debug, Clone, PartialEq, Eq)] 721 pub struct DescriptorBufferDesc { 722 /// If `true`, this buffer is a dynamic buffer. Assumes false if `None`. 723 pub dynamic: Option<bool>, 724 /// If `true`, this buffer is a storage buffer. 725 pub storage: bool, 726 } 727 728 /// Describes what kind of resource may later be bound to a descriptor. 729 /// 730 /// This is mostly the same as a `DescriptorDescTy` but with less precise information. 731 #[derive(Debug, Copy, Clone, PartialEq, Eq)] 732 #[repr(i32)] 733 pub enum DescriptorType { 734 Sampler = ash::vk::DescriptorType::SAMPLER.as_raw(), 735 CombinedImageSampler = ash::vk::DescriptorType::COMBINED_IMAGE_SAMPLER.as_raw(), 736 SampledImage = ash::vk::DescriptorType::SAMPLED_IMAGE.as_raw(), 737 StorageImage = ash::vk::DescriptorType::STORAGE_IMAGE.as_raw(), 738 UniformTexelBuffer = ash::vk::DescriptorType::UNIFORM_TEXEL_BUFFER.as_raw(), 739 StorageTexelBuffer = ash::vk::DescriptorType::STORAGE_TEXEL_BUFFER.as_raw(), 740 UniformBuffer = ash::vk::DescriptorType::UNIFORM_BUFFER.as_raw(), 741 StorageBuffer = ash::vk::DescriptorType::STORAGE_BUFFER.as_raw(), 742 UniformBufferDynamic = ash::vk::DescriptorType::UNIFORM_BUFFER_DYNAMIC.as_raw(), 743 StorageBufferDynamic = ash::vk::DescriptorType::STORAGE_BUFFER_DYNAMIC.as_raw(), 744 InputAttachment = ash::vk::DescriptorType::INPUT_ATTACHMENT.as_raw(), 745 } 746 747 impl From<DescriptorType> for ash::vk::DescriptorType { 748 #[inline] from(val: DescriptorType) -> Self749 fn from(val: DescriptorType) -> Self { 750 Self::from_raw(val as i32) 751 } 752 } 753 754 /// Error when checking whether a descriptor set is a superset of another one. 755 #[derive(Debug, Clone, PartialEq, Eq)] 756 pub enum DescriptorSetDescSupersetError { 757 /// There are more descriptors in the child than in the parent layout. 758 DescriptorsCountMismatch { self_num: u32, other_num: u32 }, 759 760 /// Expected an empty descriptor, but got something instead. 761 ExpectedEmptyDescriptor { binding_num: u32 }, 762 763 /// Two descriptors are incompatible. 764 IncompatibleDescriptors { 765 error: DescriptorDescSupersetError, 766 binding_num: u32, 767 }, 768 } 769 770 impl error::Error for DescriptorSetDescSupersetError { 771 #[inline] source(&self) -> Option<&(dyn error::Error + 'static)>772 fn source(&self) -> Option<&(dyn error::Error + 'static)> { 773 match *self { 774 DescriptorSetDescSupersetError::IncompatibleDescriptors { ref error, .. } => { 775 Some(error) 776 } 777 _ => None, 778 } 779 } 780 } 781 782 impl fmt::Display for DescriptorSetDescSupersetError { 783 #[inline] fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error>784 fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { 785 write!( 786 fmt, 787 "{}", 788 match *self { 789 DescriptorSetDescSupersetError::DescriptorsCountMismatch { .. } => { 790 "there are more descriptors in the child than in the parent layout" 791 } 792 DescriptorSetDescSupersetError::ExpectedEmptyDescriptor { .. } => { 793 "expected an empty descriptor, but got something instead" 794 } 795 DescriptorSetDescSupersetError::IncompatibleDescriptors { .. } => { 796 "two descriptors are incompatible" 797 } 798 } 799 ) 800 } 801 } 802 803 /// Error when checking whether a descriptor is a superset of another one. 804 #[derive(Debug, Clone, PartialEq, Eq)] 805 pub enum DescriptorDescSupersetError { 806 /// The number of array elements of the descriptor is smaller than expected. 807 ArrayTooSmall { 808 len: u32, 809 required: u32, 810 }, 811 812 DimensionsMismatch { 813 provided: DescriptorImageDescDimensions, 814 expected: DescriptorImageDescDimensions, 815 }, 816 817 FormatMismatch { 818 provided: Option<Format>, 819 expected: Format, 820 }, 821 822 IncompatibleArrayLayers { 823 provided: DescriptorImageDescArray, 824 required: DescriptorImageDescArray, 825 }, 826 827 MultisampledMismatch { 828 provided: bool, 829 expected: bool, 830 }, 831 832 /// The descriptor is marked as read-only, but the other is not. 833 MutabilityRequired, 834 835 /// The shader stages are not a superset of one another. 836 ShaderStagesNotSuperset, 837 838 /// The descriptor type doesn't match the type of the other descriptor. 839 TypeMismatch, 840 } 841 842 impl error::Error for DescriptorDescSupersetError {} 843 844 impl fmt::Display for DescriptorDescSupersetError { 845 #[inline] fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error>846 fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { 847 write!( 848 fmt, 849 "{}", 850 match *self { 851 DescriptorDescSupersetError::ArrayTooSmall { .. } => { 852 "the number of array elements of the descriptor is smaller than expected" 853 } 854 DescriptorDescSupersetError::TypeMismatch => { 855 "the descriptor type doesn't match the type of the other descriptor" 856 } 857 DescriptorDescSupersetError::MutabilityRequired => { 858 "the descriptor is marked as read-only, but the other is not" 859 } 860 DescriptorDescSupersetError::ShaderStagesNotSuperset => { 861 "the shader stages are not a superset of one another" 862 } 863 DescriptorDescSupersetError::DimensionsMismatch { .. } => { 864 "mismatch between the dimensions of the two descriptors" 865 } 866 DescriptorDescSupersetError::FormatMismatch { .. } => { 867 "mismatch between the format of the two descriptors" 868 } 869 DescriptorDescSupersetError::MultisampledMismatch { .. } => { 870 "mismatch between whether the descriptors are multisampled" 871 } 872 DescriptorDescSupersetError::IncompatibleArrayLayers { .. } => { 873 "the array layers of the descriptors aren't compatible" 874 } 875 } 876 ) 877 } 878 } 879 880 impl From<ShaderStagesSupersetError> for DescriptorDescSupersetError { 881 #[inline] from(err: ShaderStagesSupersetError) -> DescriptorDescSupersetError882 fn from(err: ShaderStagesSupersetError) -> DescriptorDescSupersetError { 883 match err { 884 ShaderStagesSupersetError::NotSuperset => { 885 DescriptorDescSupersetError::ShaderStagesNotSuperset 886 } 887 } 888 } 889 } 890