1use std::fmt;
3use std::hash::Hash;
4use std::rc::Rc;
5
6pub mod reg;
7pub mod walk;
8
9pub use self::{reg::TypeRegistry, walk::Walk};
10pub use crate::spirv::{Dim, ImageFormat, StorageClass};
11
12pub trait SpirvType {
13 fn min_nbyte(&self) -> Option<usize>;
17 fn nbyte(&self) -> Option<usize> {
19 self.min_nbyte()
20 }
21 fn is_sized(&self) -> bool {
24 self.nbyte().is_some()
25 }
26 fn member_offset(&self, _member_index: usize) -> Option<usize> {
28 None
29 }
30 fn access_ty(&self) -> Option<AccessType> {
33 None
34 }
35}
36
37#[derive(PartialEq, Eq, Hash, Clone, Debug)]
38pub enum ScalarType {
39 Void,
43 Boolean,
47 Integer {
49 bits: u32,
51 is_signed: bool,
53 },
54 Float {
56 bits: u32,
58 },
59}
60impl ScalarType {
61 pub fn int(bits: u32) -> Self {
63 Self::Integer {
64 bits,
65 is_signed: true,
66 }
67 }
68 pub fn uint(bits: u32) -> Self {
70 Self::Integer {
71 bits,
72 is_signed: false,
73 }
74 }
75 pub fn float(bits: u32) -> Self {
77 Self::Float { bits }
78 }
79 pub fn i32() -> Self {
81 Self::int(32)
82 }
83 pub fn u32() -> Self {
85 Self::uint(32)
86 }
87 pub fn f32() -> Self {
89 Self::float(32)
90 }
91}
92impl SpirvType for ScalarType {
93 fn min_nbyte(&self) -> Option<usize> {
94 match self {
95 Self::Void => None,
96 Self::Boolean => None,
97 Self::Integer { bits, .. } => Some((*bits / 8) as usize),
98 Self::Float { bits } => Some((*bits / 8) as usize),
99 }
100 }
101}
102impl fmt::Display for ScalarType {
103 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
104 match self {
105 Self::Void => f.write_str("void"),
106 Self::Boolean => f.write_str("bool"),
107 Self::Integer { bits, is_signed } => match is_signed {
108 true => write!(f, "i{}", bits),
109 false => write!(f, "u{}", bits),
110 },
111 Self::Float { bits } => write!(f, "f{}", bits),
112 }
113 }
114}
115
116#[derive(PartialEq, Eq, Hash, Clone, Debug)]
117pub struct VectorType {
118 pub scalar_ty: ScalarType,
120 pub nscalar: u32,
122}
123impl SpirvType for VectorType {
124 fn min_nbyte(&self) -> Option<usize> {
125 Some(self.scalar_ty.min_nbyte()? * self.nscalar as usize)
126 }
127}
128impl fmt::Display for VectorType {
129 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
130 write!(f, "vec{}<{}>", self.nscalar, self.scalar_ty)
131 }
132}
133
134#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
135pub enum MatrixAxisOrder {
136 ColumnMajor,
137 RowMajor,
138}
139impl Default for MatrixAxisOrder {
140 fn default() -> MatrixAxisOrder {
141 MatrixAxisOrder::ColumnMajor
142 }
143}
144
145#[derive(PartialEq, Eq, Hash, Clone, Debug)]
146pub struct MatrixType {
147 pub vector_ty: VectorType,
149 pub nvector: u32,
151 pub axis_order: Option<MatrixAxisOrder>,
153 pub stride: Option<usize>,
156}
157impl SpirvType for MatrixType {
158 fn min_nbyte(&self) -> Option<usize> {
159 Some(self.stride? * self.nvector as usize)
160 }
161}
162impl fmt::Display for MatrixType {
163 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
164 let major = match self.axis_order {
165 Some(MatrixAxisOrder::ColumnMajor) => "ColumnMajor",
166 Some(MatrixAxisOrder::RowMajor) => "RowMajor",
167 None => "AxisOrder?",
168 };
169 let nrow = self.vector_ty.nscalar;
170 let ncol = self.nvector;
171 let scalar_ty = &self.vector_ty.scalar_ty;
172 let stride = match self.stride {
173 Some(x) => x.to_string(),
174 None => "?".to_owned(),
175 };
176 write!(f, "mat{nrow}x{ncol}<{scalar_ty},{major},{stride}>")
177 }
178}
179
180#[derive(PartialEq, Eq, Hash, Clone, Debug)]
181pub struct ImageType {
182 pub scalar_ty: ScalarType,
184 pub dim: Dim,
186 pub is_depth: Option<bool>,
189 pub is_array: bool,
193 pub is_multisampled: bool,
196 pub is_sampled: Option<bool>,
198 pub fmt: ImageFormat,
201}
202impl SpirvType for ImageType {
203 fn min_nbyte(&self) -> Option<usize> {
204 None
205 }
206}
207impl fmt::Display for ImageType {
208 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
209 let scalar_ty = &self.scalar_ty;
210 let is_sampled = match self.is_sampled {
211 Some(true) => "Sampled",
212 Some(false) => "Storage",
213 None => "Sampled?",
214 };
215 let depth = match self.is_depth {
216 Some(true) => "Depth",
217 Some(false) => "Color",
218 None => "Depth?",
219 };
220 let dim = format!("{:?}", self.dim)[3..].to_owned();
221 let is_array = match self.is_array {
222 true => "Array",
223 false => "",
224 };
225 let is_multisampled = match self.is_multisampled {
226 true => "MS",
227 false => "",
228 };
229 write!(
230 f,
231 "Image{dim}{is_array}{is_multisampled}<{scalar_ty},{is_sampled},{depth},{:?}>",
232 self.fmt
233 )
234 }
235}
236
237#[derive(PartialEq, Eq, Hash, Clone, Debug)]
238pub struct SamplerType {}
239impl SpirvType for SamplerType {
240 fn min_nbyte(&self) -> Option<usize> {
241 None
242 }
243}
244impl fmt::Display for SamplerType {
245 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
246 f.write_str("Sampler")
247 }
248}
249
250#[derive(PartialEq, Eq, Hash, Clone, Debug)]
251pub struct CombinedImageSamplerType {
252 pub sampled_image_ty: SampledImageType,
253}
254impl SpirvType for CombinedImageSamplerType {
255 fn min_nbyte(&self) -> Option<usize> {
256 None
257 }
258}
259impl fmt::Display for CombinedImageSamplerType {
260 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
261 write!(f, "CombinedImageSampler<{}>", self.sampled_image_ty)
262 }
263}
264
265#[derive(PartialEq, Eq, Hash, Clone, Debug)]
266pub struct SampledImageType {
267 pub scalar_ty: ScalarType,
269 pub dim: Dim,
271 pub is_depth: Option<bool>,
274 pub is_array: bool,
278 pub is_multisampled: bool,
281}
282impl SpirvType for SampledImageType {
283 fn min_nbyte(&self) -> Option<usize> {
284 None
285 }
286}
287impl fmt::Display for SampledImageType {
288 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
289 let scalar_ty = &self.scalar_ty;
290 let dim = format!("{:?}", self.dim)[3..].to_owned();
291 let depth = match self.is_depth {
292 Some(true) => "Depth",
293 Some(false) => "Color",
294 None => "Depth?",
295 };
296 let is_array = match self.is_array {
297 true => "Array",
298 false => "",
299 };
300 let is_multisampled = match self.is_multisampled {
301 true => "MS",
302 false => "",
303 };
304 write!(
305 f,
306 "SampledImage{dim}{is_array}{is_multisampled}<{scalar_ty},{depth}>"
307 )
308 }
309}
310
311#[derive(PartialEq, Eq, Hash, Clone, Debug)]
312pub struct StorageImageType {
313 pub dim: Dim,
315 pub is_array: bool,
319 pub is_multisampled: bool,
322 pub fmt: ImageFormat,
325}
326impl SpirvType for StorageImageType {
327 fn min_nbyte(&self) -> Option<usize> {
328 None
329 }
330}
331impl fmt::Display for StorageImageType {
332 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
333 let dim = format!("{:?}", self.dim)[3..].to_owned();
334 let is_array = match self.is_array {
335 true => "Array",
336 false => "",
337 };
338 let is_multisampled = match self.is_multisampled {
339 true => "MS",
340 false => "",
341 };
342 write!(
343 f,
344 "StorageImage{dim}{is_array}{is_multisampled}<{:?}>",
345 self.fmt
346 )
347 }
348}
349
350#[derive(PartialEq, Eq, Hash, Clone, Debug)]
351pub struct SubpassDataType {
352 pub scalar_ty: ScalarType,
354 pub is_multisampled: bool,
356}
357impl SpirvType for SubpassDataType {
358 fn min_nbyte(&self) -> Option<usize> {
359 None
360 }
361}
362impl fmt::Display for SubpassDataType {
363 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
364 let scalar_ty = &self.scalar_ty;
365 let is_multisampled = match self.is_multisampled {
366 true => "MS",
367 false => "",
368 };
369 write!(f, "SubpassData{is_multisampled}<{scalar_ty}>")
370 }
371}
372
373#[derive(PartialEq, Eq, Hash, Clone, Debug)]
374pub struct ArrayType {
375 pub element_ty: Box<Type>,
377 pub nelement: Option<u32>,
380 pub stride: Option<usize>,
384}
385impl SpirvType for ArrayType {
386 fn min_nbyte(&self) -> Option<usize> {
387 Some(self.stride? * self.nelement.unwrap_or(0).max(1) as usize)
388 }
389 fn nbyte(&self) -> Option<usize> {
390 Some(self.stride? * self.nelement.unwrap_or(0) as usize)
391 }
392 fn member_offset(&self, member_index: usize) -> Option<usize> {
393 Some(self.stride? * member_index)
394 }
395 fn access_ty(&self) -> Option<AccessType> {
396 self.element_ty.access_ty()
397 }
398}
399impl fmt::Display for ArrayType {
400 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
401 if let Some(nrepeat) = self.nelement {
402 write!(f, "[{}; {}]", self.element_ty, nrepeat)
403 } else {
404 write!(f, "[{}]", self.element_ty)
405 }
406 }
407}
408
409#[repr(u32)]
411#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
412pub enum AccessType {
413 ReadOnly = 1,
415 WriteOnly = 2,
417 ReadWrite = 3,
419}
420impl std::ops::BitOr<AccessType> for AccessType {
421 type Output = AccessType;
422 fn bitor(self, rhs: AccessType) -> AccessType {
423 return match (self, rhs) {
424 (Self::ReadOnly, Self::ReadOnly) => Self::ReadOnly,
425 (Self::WriteOnly, Self::WriteOnly) => Self::WriteOnly,
426 _ => Self::ReadWrite,
427 };
428 }
429}
430impl std::ops::BitAnd<AccessType> for AccessType {
431 type Output = Option<AccessType>;
432 fn bitand(self, rhs: AccessType) -> Option<AccessType> {
433 return match (self, rhs) {
434 (Self::ReadOnly, Self::ReadWrite)
435 | (Self::ReadWrite, Self::ReadOnly)
436 | (Self::ReadOnly, Self::ReadOnly) => Some(Self::ReadOnly),
437 (Self::WriteOnly, Self::ReadWrite)
438 | (Self::ReadWrite, Self::WriteOnly)
439 | (Self::WriteOnly, Self::WriteOnly) => Some(Self::WriteOnly),
440 (Self::ReadWrite, Self::ReadWrite) => Some(Self::ReadWrite),
441 (_, _) => None,
442 };
443 }
444}
445
446#[derive(PartialEq, Eq, Clone, Hash, Debug)]
447pub struct StructMember {
448 pub name: Option<String>,
449 pub offset: Option<usize>,
454 pub ty: Type,
455 pub access_ty: AccessType,
456}
457#[derive(PartialEq, Eq, Default, Clone, Hash, Debug)]
458pub struct StructType {
459 pub name: Option<String>,
460 pub members: Vec<StructMember>, }
462impl StructType {
463 pub fn name(&self) -> Option<&str> {
464 self.name.as_ref().map(AsRef::as_ref)
465 }
466}
467impl SpirvType for StructType {
468 fn min_nbyte(&self) -> Option<usize> {
469 let last_member = &self.members.last()?;
470 Some(last_member.offset? + last_member.ty.min_nbyte()?)
471 }
472 fn nbyte(&self) -> Option<usize> {
473 let last_member = &self.members.last()?;
474 Some(last_member.offset? + last_member.ty.nbyte()?)
475 }
476 fn member_offset(&self, member_index: usize) -> Option<usize> {
477 self.members.get(member_index).and_then(|x| x.offset)
478 }
479 fn access_ty(&self) -> Option<AccessType> {
480 self.members.iter().fold(None, |seed, x| match seed {
481 None => Some(x.access_ty),
482 Some(AccessType::ReadOnly) => match x.access_ty {
483 AccessType::ReadOnly => Some(AccessType::ReadOnly),
484 _ => Some(AccessType::ReadWrite),
485 },
486 Some(AccessType::WriteOnly) => match x.access_ty {
487 AccessType::WriteOnly => Some(AccessType::WriteOnly),
488 _ => Some(AccessType::ReadWrite),
489 },
490 Some(AccessType::ReadWrite) => Some(AccessType::ReadWrite),
491 })
492 }
493}
494impl fmt::Display for StructType {
495 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
496 if let Some(name) = &self.name {
497 write!(f, "{} {{ ", name)?;
498 } else {
499 f.write_str("{ ")?;
500 }
501 for (i, member) in self.members.iter().enumerate() {
502 if i != 0 {
503 f.write_str(", ")?;
504 }
505 if let Some(name) = &member.name {
506 write!(f, "{}: {}", name, member.ty)?;
507 } else {
508 write!(f, "{}: {}", i, member.ty)?;
509 }
510 }
511 f.write_str(" }")
512 }
513}
514
515#[derive(PartialEq, Eq, Hash, Clone, Debug)]
516pub struct AccelStructType {}
517impl SpirvType for AccelStructType {
518 fn min_nbyte(&self) -> Option<usize> {
519 None
520 }
521}
522impl fmt::Display for AccelStructType {
523 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
524 f.write_str("AccelStruct")
525 }
526}
527
528#[derive(PartialEq, Eq, Hash, Clone, Debug)]
529pub struct DeviceAddressType {}
530impl SpirvType for DeviceAddressType {
531 fn min_nbyte(&self) -> Option<usize> {
532 Some(std::mem::size_of::<u64>())
533 }
534}
535impl fmt::Display for DeviceAddressType {
536 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
537 f.write_str("Address")
538 }
539}
540
541#[derive(PartialEq, Eq, Hash, Clone, Debug)]
542pub struct PointerType {
543 pub pointee_ty: Box<Type>,
544 pub store_cls: StorageClass,
545}
546impl SpirvType for PointerType {
547 fn min_nbyte(&self) -> Option<usize> {
548 Some(std::mem::size_of::<u64>())
549 }
550 fn access_ty(&self) -> Option<AccessType> {
551 self.pointee_ty.access_ty()
552 }
553}
554impl fmt::Display for PointerType {
555 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
556 f.write_str("Pointer { ")?;
557 write!(f, "{}", *self.pointee_ty)?;
558 f.write_str(" }")
559 }
560}
561
562#[derive(PartialEq, Eq, Hash, Clone, Debug)]
563pub struct RayQueryType {}
564impl SpirvType for RayQueryType {
565 fn min_nbyte(&self) -> Option<usize> {
566 None
567 }
568}
569impl fmt::Display for RayQueryType {
570 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
571 f.write_str("RayQuery")
572 }
573}
574
575macro_rules! declr_ty_accessor {
576 ([$e:ident] $($name:ident -> $ty:ident,)+) => {
577 $(
578 pub fn $name(&self) -> bool {
579 match self {
580 $e::$ty(..) => true,
581 _ => false
582 }
583 }
584 )+
585 }
586}
587macro_rules! declr_ty_downcast {
588 ([$e:ident] $($name:ident -> $ty:ident($inner_ty:ident),)+) => {
589 $(
590 pub fn $name(&self) -> Option<&$inner_ty> {
591 match self {
592 $e::$ty(x) => Some(x),
593 _ => None
594 }
595 }
596 )+
597 }
598}
599
600#[derive(PartialEq, Eq, Hash, Clone, Debug)]
601#[non_exhaustive]
602pub enum Type {
603 Scalar(ScalarType),
606 Vector(VectorType),
608 Matrix(MatrixType),
610 Image(ImageType),
614 CombinedImageSampler(CombinedImageSamplerType),
617 SampledImage(SampledImageType),
620 StorageImage(StorageImageType),
622 Sampler(SamplerType),
624 SubpassData(SubpassDataType),
626 Array(ArrayType),
628 Struct(StructType),
630 AccelStruct(AccelStructType),
633 DeviceAddress(DeviceAddressType),
636 DevicePointer(PointerType),
639 RayQuery(RayQueryType),
642}
643impl Type {
644 pub fn min_nbyte(&self) -> Option<usize> {
645 match self {
646 Type::Scalar(x) => x.min_nbyte(),
647 Type::Vector(x) => x.min_nbyte(),
648 Type::Matrix(x) => x.min_nbyte(),
649 Type::Image(x) => x.min_nbyte(),
650 Type::CombinedImageSampler(x) => x.min_nbyte(),
651 Type::SampledImage(x) => x.min_nbyte(),
652 Type::StorageImage(x) => x.min_nbyte(),
653 Type::Sampler(x) => x.min_nbyte(),
654 Type::SubpassData(x) => x.min_nbyte(),
655 Type::Array(x) => x.min_nbyte(),
656 Type::Struct(x) => x.min_nbyte(),
657 Type::AccelStruct(x) => x.min_nbyte(),
658 Type::DeviceAddress(x) => x.min_nbyte(),
659 Type::DevicePointer(x) => x.min_nbyte(),
660 Type::RayQuery(x) => x.min_nbyte(),
661 }
662 }
663 pub fn nbyte(&self) -> Option<usize> {
664 match self {
665 Type::Scalar(x) => x.nbyte(),
666 Type::Vector(x) => x.nbyte(),
667 Type::Matrix(x) => x.nbyte(),
668 Type::Image(x) => x.nbyte(),
669 Type::CombinedImageSampler(x) => x.nbyte(),
670 Type::SampledImage(x) => x.nbyte(),
671 Type::StorageImage(x) => x.nbyte(),
672 Type::Sampler(x) => x.nbyte(),
673 Type::SubpassData(x) => x.nbyte(),
674 Type::Array(x) => x.nbyte(),
675 Type::Struct(x) => x.nbyte(),
676 Type::AccelStruct(x) => x.nbyte(),
677 Type::DeviceAddress(x) => x.nbyte(),
678 Type::DevicePointer(x) => x.nbyte(),
679 Type::RayQuery(x) => x.nbyte(),
680 }
681 }
682 pub fn member_offset(&self, member_index: usize) -> Option<usize> {
683 match self {
684 Type::Scalar(x) => x.member_offset(member_index),
685 Type::Vector(x) => x.member_offset(member_index),
686 Type::Matrix(x) => x.member_offset(member_index),
687 Type::Image(x) => x.member_offset(member_index),
688 Type::CombinedImageSampler(x) => x.member_offset(member_index),
689 Type::SampledImage(x) => x.member_offset(member_index),
690 Type::StorageImage(x) => x.member_offset(member_index),
691 Type::Sampler(x) => x.member_offset(member_index),
692 Type::SubpassData(x) => x.member_offset(member_index),
693 Type::Array(x) => x.member_offset(member_index),
694 Type::Struct(x) => x.member_offset(member_index),
695 Type::AccelStruct(x) => x.member_offset(member_index),
696 Type::DeviceAddress(x) => x.member_offset(member_index),
697 Type::DevicePointer(x) => x.member_offset(member_index),
698 Type::RayQuery(x) => x.member_offset(member_index),
699 }
700 }
701 pub fn access_ty(&self) -> Option<AccessType> {
702 match self {
703 Type::Scalar(x) => x.access_ty(),
704 Type::Vector(x) => x.access_ty(),
705 Type::Matrix(x) => x.access_ty(),
706 Type::Image(x) => x.access_ty(),
707 Type::CombinedImageSampler(x) => x.access_ty(),
708 Type::SampledImage(x) => x.access_ty(),
709 Type::StorageImage(x) => x.access_ty(),
710 Type::Sampler(x) => x.access_ty(),
711 Type::SubpassData(x) => x.access_ty(),
712 Type::Array(x) => x.access_ty(),
713 Type::Struct(x) => x.access_ty(),
714 Type::AccelStruct(x) => x.access_ty(),
715 Type::DeviceAddress(x) => x.access_ty(),
716 Type::DevicePointer(x) => x.access_ty(),
717 Type::RayQuery(x) => x.access_ty(),
718 }
719 }
720
721 pub fn walk<'a>(&'a self) -> Walk<'a> {
723 Walk::new(self)
724 }
725 declr_ty_accessor! {
726 [Type]
727 is_scalar -> Scalar,
728 is_vector -> Vector,
729 is_matrix -> Matrix,
730 is_image -> Image,
731 is_sampler -> Sampler,
732 is_combined_image_sampler -> CombinedImageSampler,
733 is_sampled_image -> SampledImage,
734 is_storage_image -> StorageImage,
735 is_subpass_data -> SubpassData,
736 is_array -> Array,
737 is_struct -> Struct,
738 is_accel_struct -> AccelStruct,
739 is_device_address -> DeviceAddress,
740 is_device_pointer -> DevicePointer,
741 }
742 declr_ty_downcast! {
743 [Type]
744 as_scalar -> Scalar(ScalarType),
745 as_vector -> Vector(VectorType),
746 as_matrix -> Matrix(MatrixType),
747 as_image -> Image(ImageType),
748 as_sampler -> Sampler(SamplerType),
749 as_combined_image_sampler -> CombinedImageSampler(CombinedImageSamplerType),
750 as_sampled_image -> SampledImage(SampledImageType),
751 as_storage_image -> StorageImage(StorageImageType),
752 as_subpass_data -> SubpassData(SubpassDataType),
753 as_array -> Array(ArrayType),
754 as_struct -> Struct(StructType),
755 as_accel_struct -> AccelStruct(AccelStructType),
756 as_device_address -> DeviceAddress(DeviceAddressType),
757 as_device_pointer -> DevicePointer(PointerType),
758 }
759 fn mutate_impl<F: Fn(Type) -> Type>(self, f: Rc<F>) -> Type {
760 use Type::*;
761 let out = match self {
762 Array(src) => {
763 let dst = ArrayType {
764 element_ty: Box::new(src.element_ty.mutate_impl(f.clone())),
765 nelement: src.nelement,
766 stride: src.stride,
767 };
768 Type::Array(dst)
769 }
770 Struct(src) => {
771 let dst = StructType {
772 name: src.name,
773 members: src
774 .members
775 .into_iter()
776 .map(|x| StructMember {
777 name: x.name,
778 offset: x.offset,
779 ty: x.ty.mutate_impl(f.clone()),
780 access_ty: x.access_ty,
781 })
782 .collect(),
783 };
784 Type::Struct(dst)
785 }
786 _ => self,
787 };
788 (*f)(out)
789 }
790 pub fn mutate<F: Fn(Type) -> Type>(self, f: F) -> Type {
791 self.mutate_impl(Rc::new(f))
792 }
793}
794impl fmt::Display for Type {
795 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
796 match self {
797 Type::Scalar(x) => x.fmt(f),
798 Type::Vector(x) => x.fmt(f),
799 Type::Matrix(x) => x.fmt(f),
800 Type::Image(x) => x.fmt(f),
801 Type::Sampler(x) => x.fmt(f),
802 Type::CombinedImageSampler(x) => x.fmt(f),
803 Type::SampledImage(x) => x.fmt(f),
804 Type::StorageImage(x) => x.fmt(f),
805 Type::SubpassData(x) => x.fmt(f),
806 Type::Array(x) => x.fmt(f),
807 Type::Struct(x) => x.fmt(f),
808 Type::AccelStruct(x) => x.fmt(f),
809 Type::DeviceAddress(x) => x.fmt(f),
810 Type::DevicePointer(x) => x.fmt(f),
811 Type::RayQuery(x) => x.fmt(f),
812 }
813 }
814}
815
816#[derive(Debug, PartialEq, Eq, Hash, Clone)]
818pub enum DescriptorType {
819 Sampler(),
821 CombinedImageSampler(),
823 SampledImage(),
825 StorageImage(AccessType),
827 UniformTexelBuffer(),
829 StorageTexelBuffer(AccessType),
831 UniformBuffer(),
835 StorageBuffer(AccessType),
839 InputAttachment(u32),
841 AccelStruct(),
843}