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}