1use alloc::vec::Vec;
2
3use crate::{Features, TextureAspect, TextureSampleType, TextureUsages};
4
5#[cfg(any(feature = "serde", test))]
6use serde::{Deserialize, Serialize};
7
8#[repr(C)]
10#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
11#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
12#[cfg_attr(any(test, feature = "exhaust"), derive(exhaust::Exhaust))]
13pub enum AstcBlock {
14 B4x4,
16 B5x4,
18 B5x5,
20 B6x5,
22 B6x6,
24 B8x5,
26 B8x6,
28 B8x8,
30 B10x5,
32 B10x6,
34 B10x8,
36 B10x10,
38 B12x10,
40 B12x12,
42}
43
44#[repr(C)]
46#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
47#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
48#[cfg_attr(any(test, feature = "exhaust"), derive(exhaust::Exhaust))]
49pub enum AstcChannel {
50 Unorm,
54 UnormSrgb,
58 Hdr,
62}
63
64bitflags::bitflags! {
65 #[repr(transparent)]
67 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
68 #[cfg_attr(feature = "serde", serde(transparent))]
69 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
70 pub struct TextureChannel: u16 {
71 const RED = 1 << 0;
73 const GREEN = 1 << 1;
75 const BLUE = 1 << 2;
77 const ALPHA = 1 << 3;
79 const STENCIL = 1 << 4;
81 const DEPTH = 1 << 5;
83 const LUMINANCE = 1 << 6;
85 const CHROMINANCE_BLUE = 1 << 7;
87 const CHROMINANCE_RED = 1 << 8;
89
90 const RG = Self::RED.bits() | Self::GREEN.bits();
92 const RGB = Self::RG.bits() | Self::BLUE.bits();
94 const RGBA = Self::RGB.bits() | Self::ALPHA.bits();
96 const DEPTH_STENCIL = Self::DEPTH.bits() | Self::STENCIL.bits();
98 const LUMINANCE_CHROMINANCE = Self::LUMINANCE.bits() | Self::CHROMINANCE_BLUE.bits() | Self::CHROMINANCE_RED.bits();
100 }
101}
102
103#[repr(C)]
126#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
127#[cfg_attr(any(test, feature = "exhaust"), derive(exhaust::Exhaust))]
128pub enum TextureFormat {
129 R8Unorm,
132 R8Snorm,
134 R8Uint,
136 R8Sint,
138
139 R16Uint,
142 R16Sint,
144 R16Unorm,
148 R16Snorm,
152 R16Float,
154 Rg8Unorm,
156 Rg8Snorm,
158 Rg8Uint,
160 Rg8Sint,
162
163 R32Uint,
166 R32Sint,
168 R32Float,
170 Rg16Uint,
172 Rg16Sint,
174 Rg16Unorm,
178 Rg16Snorm,
182 Rg16Float,
184 Rgba8Unorm,
186 Rgba8UnormSrgb,
188 Rgba8Snorm,
190 Rgba8Uint,
192 Rgba8Sint,
194 Bgra8Unorm,
196 Bgra8UnormSrgb,
198
199 Rgb9e5Ufloat,
202 Rgb10a2Uint,
204 Rgb10a2Unorm,
206 Rg11b10Ufloat,
208
209 R64Uint,
214 Rg32Uint,
216 Rg32Sint,
218 Rg32Float,
220 Rgba16Uint,
222 Rgba16Sint,
224 Rgba16Unorm,
228 Rgba16Snorm,
232 Rgba16Float,
234
235 Rgba32Uint,
238 Rgba32Sint,
240 Rgba32Float,
242
243 Stencil8,
246 Depth16Unorm,
248 Depth24Plus,
250 Depth24PlusStencil8,
252 Depth32Float,
254 Depth32FloatStencil8,
258
259 NV12,
273
274 P010,
290
291 Bc1RgbaUnorm,
300 Bc1RgbaUnormSrgb,
308 Bc2RgbaUnorm,
316 Bc2RgbaUnormSrgb,
324 Bc3RgbaUnorm,
332 Bc3RgbaUnormSrgb,
340 Bc4RUnorm,
348 Bc4RSnorm,
356 Bc5RgUnorm,
364 Bc5RgSnorm,
372 Bc6hRgbUfloat,
379 Bc6hRgbFloat,
386 Bc7RgbaUnorm,
394 Bc7RgbaUnormSrgb,
402 Etc2Rgb8Unorm,
407 Etc2Rgb8UnormSrgb,
412 Etc2Rgb8A1Unorm,
417 Etc2Rgb8A1UnormSrgb,
422 Etc2Rgba8Unorm,
427 Etc2Rgba8UnormSrgb,
432 EacR11Unorm,
437 EacR11Snorm,
442 EacRg11Unorm,
447 EacRg11Snorm,
452 Astc {
460 block: AstcBlock,
462 channel: AstcChannel,
464 },
465}
466
467impl TextureFormat {
470 #[must_use]
474 pub fn aspect_specific_format(&self, aspect: TextureAspect) -> Option<Self> {
475 match (*self, aspect) {
476 (Self::Stencil8, TextureAspect::StencilOnly) => Some(*self),
477 (
478 Self::Depth16Unorm | Self::Depth24Plus | Self::Depth32Float,
479 TextureAspect::DepthOnly,
480 ) => Some(*self),
481 (
482 Self::Depth24PlusStencil8 | Self::Depth32FloatStencil8,
483 TextureAspect::StencilOnly,
484 ) => Some(Self::Stencil8),
485 (Self::Depth24PlusStencil8, TextureAspect::DepthOnly) => Some(Self::Depth24Plus),
486 (Self::Depth32FloatStencil8, TextureAspect::DepthOnly) => Some(Self::Depth32Float),
487 (Self::NV12, TextureAspect::Plane0) => Some(Self::R8Unorm),
488 (Self::NV12, TextureAspect::Plane1) => Some(Self::Rg8Unorm),
489 (Self::P010, TextureAspect::Plane0) => Some(Self::R16Unorm),
490 (Self::P010, TextureAspect::Plane1) => Some(Self::Rg16Unorm),
491 (format, TextureAspect::All) if !format.is_multi_planar_format() => Some(format),
493 _ => None,
494 }
495 }
496
497 #[must_use]
500 pub fn is_depth_stencil_component(&self, combined_format: Self) -> bool {
501 match (combined_format, *self) {
502 (Self::Depth24PlusStencil8, Self::Depth24Plus | Self::Stencil8)
503 | (Self::Depth32FloatStencil8, Self::Depth32Float | Self::Stencil8) => true,
504 _ => false,
505 }
506 }
507
508 #[must_use]
512 pub fn is_depth_stencil_format(&self) -> bool {
513 self.channels().intersects(TextureChannel::DEPTH_STENCIL)
514 }
515
516 #[must_use]
520 pub fn is_combined_depth_stencil_format(&self) -> bool {
521 self.channels().contains(TextureChannel::DEPTH_STENCIL)
522 }
523
524 #[must_use]
526 pub fn is_multi_planar_format(&self) -> bool {
527 self.planes().is_some()
528 }
529
530 #[must_use]
532 pub fn planes(&self) -> Option<u32> {
533 match *self {
534 Self::NV12 => Some(2),
535 Self::P010 => Some(2),
536 _ => None,
537 }
538 }
539
540 #[must_use]
542 pub fn subsampling_factors(&self, plane: Option<u32>) -> (u32, u32) {
543 match *self {
544 Self::NV12 | Self::P010 => match plane {
545 Some(0) => (1, 1),
546 Some(1) => (2, 2),
547 Some(plane) => unreachable!("plane {plane} is not valid for {self:?}"),
548 None => unreachable!("the plane must be specified for multi-planar formats"),
549 },
550 _ => (1, 1),
551 }
552 }
553
554 #[must_use]
577 pub fn channels(&self) -> TextureChannel {
578 match self {
579 Self::R8Unorm
580 | Self::R8Snorm
581 | Self::R8Uint
582 | Self::R8Sint
583 | Self::R16Uint
584 | Self::R16Sint
585 | Self::R16Unorm
586 | Self::R16Snorm
587 | Self::R32Uint
588 | Self::R32Sint
589 | Self::R32Float
590 | Self::R16Float
591 | Self::R64Uint
592 | Self::Bc4RUnorm
593 | Self::Bc4RSnorm
594 | Self::EacR11Unorm
595 | Self::EacR11Snorm => TextureChannel::RED,
596
597 Self::Rg8Unorm
598 | Self::Rg8Snorm
599 | Self::Rg8Uint
600 | Self::Rg8Sint
601 | Self::Rg16Uint
602 | Self::Rg16Sint
603 | Self::Rg16Unorm
604 | Self::Rg16Snorm
605 | Self::Rg16Float
606 | Self::Rg32Uint
607 | Self::Rg32Sint
608 | Self::Rg32Float
609 | Self::Bc5RgUnorm
610 | Self::Bc5RgSnorm
611 | Self::EacRg11Unorm
612 | Self::EacRg11Snorm => TextureChannel::RG,
613
614 Self::Rgb9e5Ufloat
615 | Self::Rg11b10Ufloat
616 | Self::Bc6hRgbUfloat
617 | Self::Bc6hRgbFloat
618 | Self::Etc2Rgb8Unorm
619 | Self::Etc2Rgb8UnormSrgb => TextureChannel::RGB,
620
621 Self::Rgba8Unorm
622 | Self::Rgba8UnormSrgb
623 | Self::Rgba8Snorm
624 | Self::Rgba8Uint
625 | Self::Rgba8Sint
626 | Self::Bgra8Unorm
627 | Self::Bgra8UnormSrgb
628 | Self::Rgb10a2Uint
629 | Self::Rgb10a2Unorm
630 | Self::Rgba16Uint
631 | Self::Rgba16Sint
632 | Self::Rgba16Unorm
633 | Self::Rgba16Snorm
634 | Self::Rgba16Float
635 | Self::Rgba32Uint
636 | Self::Rgba32Sint
637 | Self::Rgba32Float
638 | Self::Bc1RgbaUnorm
639 | Self::Bc1RgbaUnormSrgb
640 | Self::Bc2RgbaUnorm
641 | Self::Bc2RgbaUnormSrgb
642 | Self::Bc3RgbaUnorm
643 | Self::Bc3RgbaUnormSrgb
644 | Self::Bc7RgbaUnorm
645 | Self::Bc7RgbaUnormSrgb
646 | Self::Etc2Rgb8A1Unorm
647 | Self::Etc2Rgb8A1UnormSrgb
648 | Self::Etc2Rgba8Unorm
649 | Self::Etc2Rgba8UnormSrgb
650 | Self::Astc { .. } => TextureChannel::RGBA,
651
652 Self::Stencil8 => TextureChannel::STENCIL,
653 Self::Depth16Unorm | Self::Depth24Plus | Self::Depth32Float => TextureChannel::DEPTH,
654
655 Self::Depth24PlusStencil8 | Self::Depth32FloatStencil8 => TextureChannel::DEPTH_STENCIL,
656
657 Self::NV12 | Self::P010 => TextureChannel::LUMINANCE_CHROMINANCE,
658 }
659 }
660
661 #[must_use]
663 pub fn has_color_aspect(&self) -> bool {
664 self.channels().intersects(TextureChannel::RGBA)
665 }
666
667 #[must_use]
669 pub fn has_depth_aspect(&self) -> bool {
670 self.channels().intersects(TextureChannel::DEPTH)
671 }
672
673 #[must_use]
675 pub fn has_stencil_aspect(&self) -> bool {
676 self.channels().intersects(TextureChannel::STENCIL)
677 }
678
679 #[must_use]
685 pub fn size_multiple_requirement(&self) -> (u32, u32) {
686 match *self {
687 Self::NV12 => (2, 2),
688 Self::P010 => (2, 2),
689 _ => self.block_dimensions(),
690 }
691 }
692
693 #[must_use]
697 pub fn block_dimensions(&self) -> (u32, u32) {
698 match *self {
699 Self::R8Unorm
700 | Self::R8Snorm
701 | Self::R8Uint
702 | Self::R8Sint
703 | Self::R16Uint
704 | Self::R16Sint
705 | Self::R16Unorm
706 | Self::R16Snorm
707 | Self::R16Float
708 | Self::Rg8Unorm
709 | Self::Rg8Snorm
710 | Self::Rg8Uint
711 | Self::Rg8Sint
712 | Self::R32Uint
713 | Self::R32Sint
714 | Self::R32Float
715 | Self::Rg16Uint
716 | Self::Rg16Sint
717 | Self::Rg16Unorm
718 | Self::Rg16Snorm
719 | Self::Rg16Float
720 | Self::Rgba8Unorm
721 | Self::Rgba8UnormSrgb
722 | Self::Rgba8Snorm
723 | Self::Rgba8Uint
724 | Self::Rgba8Sint
725 | Self::Bgra8Unorm
726 | Self::Bgra8UnormSrgb
727 | Self::Rgb9e5Ufloat
728 | Self::Rgb10a2Uint
729 | Self::Rgb10a2Unorm
730 | Self::Rg11b10Ufloat
731 | Self::R64Uint
732 | Self::Rg32Uint
733 | Self::Rg32Sint
734 | Self::Rg32Float
735 | Self::Rgba16Uint
736 | Self::Rgba16Sint
737 | Self::Rgba16Unorm
738 | Self::Rgba16Snorm
739 | Self::Rgba16Float
740 | Self::Rgba32Uint
741 | Self::Rgba32Sint
742 | Self::Rgba32Float
743 | Self::Stencil8
744 | Self::Depth16Unorm
745 | Self::Depth24Plus
746 | Self::Depth24PlusStencil8
747 | Self::Depth32Float
748 | Self::Depth32FloatStencil8
749 | Self::NV12
750 | Self::P010 => (1, 1),
751
752 Self::Bc1RgbaUnorm
753 | Self::Bc1RgbaUnormSrgb
754 | Self::Bc2RgbaUnorm
755 | Self::Bc2RgbaUnormSrgb
756 | Self::Bc3RgbaUnorm
757 | Self::Bc3RgbaUnormSrgb
758 | Self::Bc4RUnorm
759 | Self::Bc4RSnorm
760 | Self::Bc5RgUnorm
761 | Self::Bc5RgSnorm
762 | Self::Bc6hRgbUfloat
763 | Self::Bc6hRgbFloat
764 | Self::Bc7RgbaUnorm
765 | Self::Bc7RgbaUnormSrgb => (4, 4),
766
767 Self::Etc2Rgb8Unorm
768 | Self::Etc2Rgb8UnormSrgb
769 | Self::Etc2Rgb8A1Unorm
770 | Self::Etc2Rgb8A1UnormSrgb
771 | Self::Etc2Rgba8Unorm
772 | Self::Etc2Rgba8UnormSrgb
773 | Self::EacR11Unorm
774 | Self::EacR11Snorm
775 | Self::EacRg11Unorm
776 | Self::EacRg11Snorm => (4, 4),
777
778 Self::Astc { block, .. } => match block {
779 AstcBlock::B4x4 => (4, 4),
780 AstcBlock::B5x4 => (5, 4),
781 AstcBlock::B5x5 => (5, 5),
782 AstcBlock::B6x5 => (6, 5),
783 AstcBlock::B6x6 => (6, 6),
784 AstcBlock::B8x5 => (8, 5),
785 AstcBlock::B8x6 => (8, 6),
786 AstcBlock::B8x8 => (8, 8),
787 AstcBlock::B10x5 => (10, 5),
788 AstcBlock::B10x6 => (10, 6),
789 AstcBlock::B10x8 => (10, 8),
790 AstcBlock::B10x10 => (10, 10),
791 AstcBlock::B12x10 => (12, 10),
792 AstcBlock::B12x12 => (12, 12),
793 },
794 }
795 }
796
797 #[must_use]
799 pub fn is_compressed(&self) -> bool {
800 self.block_dimensions() != (1, 1)
801 }
802
803 #[must_use]
805 pub fn is_bcn(&self) -> bool {
806 self.required_features() == Features::TEXTURE_COMPRESSION_BC
807 }
808
809 #[must_use]
811 pub fn is_astc(&self) -> bool {
812 self.required_features() == Features::TEXTURE_COMPRESSION_ASTC
813 || self.required_features() == Features::TEXTURE_COMPRESSION_ASTC_HDR
814 }
815
816 #[must_use]
818 pub fn required_features(&self) -> Features {
819 match *self {
820 Self::R8Unorm
821 | Self::R8Snorm
822 | Self::R8Uint
823 | Self::R8Sint
824 | Self::R16Uint
825 | Self::R16Sint
826 | Self::R16Float
827 | Self::Rg8Unorm
828 | Self::Rg8Snorm
829 | Self::Rg8Uint
830 | Self::Rg8Sint
831 | Self::R32Uint
832 | Self::R32Sint
833 | Self::R32Float
834 | Self::Rg16Uint
835 | Self::Rg16Sint
836 | Self::Rg16Float
837 | Self::Rgba8Unorm
838 | Self::Rgba8UnormSrgb
839 | Self::Rgba8Snorm
840 | Self::Rgba8Uint
841 | Self::Rgba8Sint
842 | Self::Bgra8Unorm
843 | Self::Bgra8UnormSrgb
844 | Self::Rgb9e5Ufloat
845 | Self::Rgb10a2Uint
846 | Self::Rgb10a2Unorm
847 | Self::Rg11b10Ufloat
848 | Self::Rg32Uint
849 | Self::Rg32Sint
850 | Self::Rg32Float
851 | Self::Rgba16Uint
852 | Self::Rgba16Sint
853 | Self::Rgba16Float
854 | Self::Rgba32Uint
855 | Self::Rgba32Sint
856 | Self::Rgba32Float
857 | Self::Stencil8
858 | Self::Depth16Unorm
859 | Self::Depth24Plus
860 | Self::Depth24PlusStencil8
861 | Self::Depth32Float => Features::empty(),
862
863 Self::R64Uint => Features::TEXTURE_INT64_ATOMIC,
864
865 Self::Depth32FloatStencil8 => Features::DEPTH32FLOAT_STENCIL8,
866
867 Self::NV12 => Features::TEXTURE_FORMAT_NV12,
868 Self::P010 => Features::TEXTURE_FORMAT_P010,
869
870 Self::R16Unorm
871 | Self::R16Snorm
872 | Self::Rg16Unorm
873 | Self::Rg16Snorm
874 | Self::Rgba16Unorm
875 | Self::Rgba16Snorm => Features::TEXTURE_FORMAT_16BIT_NORM,
876
877 Self::Bc1RgbaUnorm
878 | Self::Bc1RgbaUnormSrgb
879 | Self::Bc2RgbaUnorm
880 | Self::Bc2RgbaUnormSrgb
881 | Self::Bc3RgbaUnorm
882 | Self::Bc3RgbaUnormSrgb
883 | Self::Bc4RUnorm
884 | Self::Bc4RSnorm
885 | Self::Bc5RgUnorm
886 | Self::Bc5RgSnorm
887 | Self::Bc6hRgbUfloat
888 | Self::Bc6hRgbFloat
889 | Self::Bc7RgbaUnorm
890 | Self::Bc7RgbaUnormSrgb => Features::TEXTURE_COMPRESSION_BC,
891
892 Self::Etc2Rgb8Unorm
893 | Self::Etc2Rgb8UnormSrgb
894 | Self::Etc2Rgb8A1Unorm
895 | Self::Etc2Rgb8A1UnormSrgb
896 | Self::Etc2Rgba8Unorm
897 | Self::Etc2Rgba8UnormSrgb
898 | Self::EacR11Unorm
899 | Self::EacR11Snorm
900 | Self::EacRg11Unorm
901 | Self::EacRg11Snorm => Features::TEXTURE_COMPRESSION_ETC2,
902
903 Self::Astc { channel, .. } => match channel {
904 AstcChannel::Hdr => Features::TEXTURE_COMPRESSION_ASTC_HDR,
905 AstcChannel::Unorm | AstcChannel::UnormSrgb => Features::TEXTURE_COMPRESSION_ASTC,
906 },
907 }
908 }
909
910 #[must_use]
914 pub fn guaranteed_format_features(&self, device_features: Features) -> TextureFormatFeatures {
915 let none = TextureFormatFeatureFlags::empty();
917 let msaa = TextureFormatFeatureFlags::MULTISAMPLE_X4;
918 let msaa_resolve = msaa | TextureFormatFeatureFlags::MULTISAMPLE_RESOLVE;
919
920 let s_ro_wo = TextureFormatFeatureFlags::STORAGE_READ_ONLY
921 | TextureFormatFeatureFlags::STORAGE_WRITE_ONLY;
922 let s_all = s_ro_wo | TextureFormatFeatureFlags::STORAGE_READ_WRITE;
923
924 let basic =
926 TextureUsages::COPY_SRC | TextureUsages::COPY_DST | TextureUsages::TEXTURE_BINDING;
927 let attachment =
928 basic | TextureUsages::RENDER_ATTACHMENT | TextureUsages::TRANSIENT_ATTACHMENT;
929 let storage = basic | TextureUsages::STORAGE_BINDING;
930 let binding = TextureUsages::TEXTURE_BINDING;
931 let all_flags = attachment | storage | binding;
932 let atomic_64 = if device_features.contains(Features::TEXTURE_ATOMIC) {
933 storage | binding | TextureUsages::STORAGE_ATOMIC
934 } else {
935 storage | binding
936 };
937 let atomic = attachment | atomic_64;
938 let (rg11b10f_f, rg11b10f_u) =
939 if device_features.contains(Features::RG11B10UFLOAT_RENDERABLE) {
940 (msaa_resolve, attachment)
941 } else {
942 (msaa, basic)
943 };
944 let (bgra8unorm_f, bgra8unorm) = if device_features.contains(Features::BGRA8UNORM_STORAGE) {
945 (
946 msaa_resolve | TextureFormatFeatureFlags::STORAGE_WRITE_ONLY,
947 attachment | TextureUsages::STORAGE_BINDING,
948 )
949 } else {
950 (msaa_resolve, attachment)
951 };
952
953 #[rustfmt::skip] let (
955 mut flags,
956 allowed_usages,
957 ) = match *self {
958 Self::R8Unorm => (msaa_resolve, attachment),
959 Self::R8Snorm => ( none, basic),
960 Self::R8Uint => ( msaa, attachment),
961 Self::R8Sint => ( msaa, attachment),
962 Self::R16Uint => ( msaa, attachment),
963 Self::R16Sint => ( msaa, attachment),
964 Self::R16Float => (msaa_resolve, attachment),
965 Self::Rg8Unorm => (msaa_resolve, attachment),
966 Self::Rg8Snorm => ( none, basic),
967 Self::Rg8Uint => ( msaa, attachment),
968 Self::Rg8Sint => ( msaa, attachment),
969 Self::R32Uint => ( s_all, atomic),
970 Self::R32Sint => ( s_all, atomic),
971 Self::R32Float => (msaa | s_all, all_flags),
972 Self::Rg16Uint => ( msaa, attachment),
973 Self::Rg16Sint => ( msaa, attachment),
974 Self::Rg16Float => (msaa_resolve, attachment),
975 Self::Rgba8Unorm => (msaa_resolve | s_ro_wo, all_flags),
976 Self::Rgba8UnormSrgb => (msaa_resolve, attachment),
977 Self::Rgba8Snorm => ( s_ro_wo, storage),
978 Self::Rgba8Uint => ( msaa | s_ro_wo, all_flags),
979 Self::Rgba8Sint => ( msaa | s_ro_wo, all_flags),
980 Self::Bgra8Unorm => (bgra8unorm_f, bgra8unorm),
981 Self::Bgra8UnormSrgb => (msaa_resolve, attachment),
982 Self::Rgb10a2Uint => ( msaa, attachment),
983 Self::Rgb10a2Unorm => (msaa_resolve, attachment),
984 Self::Rg11b10Ufloat => ( rg11b10f_f, rg11b10f_u),
985 Self::R64Uint => ( s_ro_wo, atomic_64),
986 Self::Rg32Uint => ( s_ro_wo, all_flags),
987 Self::Rg32Sint => ( s_ro_wo, all_flags),
988 Self::Rg32Float => ( s_ro_wo, all_flags),
989 Self::Rgba16Uint => ( msaa | s_ro_wo, all_flags),
990 Self::Rgba16Sint => ( msaa | s_ro_wo, all_flags),
991 Self::Rgba16Float => (msaa_resolve | s_ro_wo, all_flags),
992 Self::Rgba32Uint => ( s_ro_wo, all_flags),
993 Self::Rgba32Sint => ( s_ro_wo, all_flags),
994 Self::Rgba32Float => ( s_ro_wo, all_flags),
995
996 Self::Stencil8 => ( msaa, attachment),
997 Self::Depth16Unorm => ( msaa, attachment),
998 Self::Depth24Plus => ( msaa, attachment),
999 Self::Depth24PlusStencil8 => ( msaa, attachment),
1000 Self::Depth32Float => ( msaa, attachment),
1001 Self::Depth32FloatStencil8 => ( msaa, attachment),
1002
1003 Self::NV12 => ( none, binding),
1006 Self::P010 => ( none, binding),
1007
1008 Self::R16Unorm => ( msaa | s_ro_wo, storage),
1009 Self::R16Snorm => ( msaa | s_ro_wo, storage),
1010 Self::Rg16Unorm => ( msaa | s_ro_wo, storage),
1011 Self::Rg16Snorm => ( msaa | s_ro_wo, storage),
1012 Self::Rgba16Unorm => ( msaa | s_ro_wo, storage),
1013 Self::Rgba16Snorm => ( msaa | s_ro_wo, storage),
1014
1015 Self::Rgb9e5Ufloat => ( none, basic),
1016
1017 Self::Bc1RgbaUnorm => ( none, basic),
1018 Self::Bc1RgbaUnormSrgb => ( none, basic),
1019 Self::Bc2RgbaUnorm => ( none, basic),
1020 Self::Bc2RgbaUnormSrgb => ( none, basic),
1021 Self::Bc3RgbaUnorm => ( none, basic),
1022 Self::Bc3RgbaUnormSrgb => ( none, basic),
1023 Self::Bc4RUnorm => ( none, basic),
1024 Self::Bc4RSnorm => ( none, basic),
1025 Self::Bc5RgUnorm => ( none, basic),
1026 Self::Bc5RgSnorm => ( none, basic),
1027 Self::Bc6hRgbUfloat => ( none, basic),
1028 Self::Bc6hRgbFloat => ( none, basic),
1029 Self::Bc7RgbaUnorm => ( none, basic),
1030 Self::Bc7RgbaUnormSrgb => ( none, basic),
1031
1032 Self::Etc2Rgb8Unorm => ( none, basic),
1033 Self::Etc2Rgb8UnormSrgb => ( none, basic),
1034 Self::Etc2Rgb8A1Unorm => ( none, basic),
1035 Self::Etc2Rgb8A1UnormSrgb => ( none, basic),
1036 Self::Etc2Rgba8Unorm => ( none, basic),
1037 Self::Etc2Rgba8UnormSrgb => ( none, basic),
1038 Self::EacR11Unorm => ( none, basic),
1039 Self::EacR11Snorm => ( none, basic),
1040 Self::EacRg11Unorm => ( none, basic),
1041 Self::EacRg11Snorm => ( none, basic),
1042
1043 Self::Astc { .. } => ( none, basic),
1044 };
1045
1046 let sample_type1 = self.sample_type(None, Some(device_features));
1048 let is_filterable = sample_type1 == Some(TextureSampleType::Float { filterable: true });
1049
1050 let sample_type2 = self.sample_type(None, None);
1052 let is_blendable = sample_type2 == Some(TextureSampleType::Float { filterable: true })
1053 || device_features.contains(Features::FLOAT32_BLENDABLE)
1054 && matches!(self, Self::R32Float | Self::Rg32Float | Self::Rgba32Float);
1055
1056 flags.set(TextureFormatFeatureFlags::FILTERABLE, is_filterable);
1057 flags.set(TextureFormatFeatureFlags::BLENDABLE, is_blendable);
1058 flags.set(
1059 TextureFormatFeatureFlags::STORAGE_ATOMIC,
1060 allowed_usages.contains(TextureUsages::STORAGE_ATOMIC),
1061 );
1062
1063 TextureFormatFeatures {
1064 allowed_usages,
1065 flags,
1066 }
1067 }
1068
1069 #[must_use]
1074 pub fn sample_type(
1075 &self,
1076 aspect: Option<TextureAspect>,
1077 device_features: Option<Features>,
1078 ) -> Option<TextureSampleType> {
1079 let float = TextureSampleType::Float { filterable: true };
1080 let unfilterable_float = TextureSampleType::Float { filterable: false };
1081 let float32_sample_type = TextureSampleType::Float {
1082 filterable: device_features
1083 .unwrap_or(Features::empty())
1084 .contains(Features::FLOAT32_FILTERABLE),
1085 };
1086 let depth = TextureSampleType::Depth;
1087 let uint = TextureSampleType::Uint;
1088 let sint = TextureSampleType::Sint;
1089
1090 match *self {
1091 Self::R8Unorm
1092 | Self::R8Snorm
1093 | Self::Rg8Unorm
1094 | Self::Rg8Snorm
1095 | Self::Rgba8Unorm
1096 | Self::Rgba8UnormSrgb
1097 | Self::Rgba8Snorm
1098 | Self::Bgra8Unorm
1099 | Self::Bgra8UnormSrgb
1100 | Self::R16Float
1101 | Self::Rg16Float
1102 | Self::Rgba16Float
1103 | Self::Rgb10a2Unorm
1104 | Self::Rg11b10Ufloat => Some(float),
1105
1106 Self::R32Float | Self::Rg32Float | Self::Rgba32Float => Some(float32_sample_type),
1107
1108 Self::R8Uint
1109 | Self::Rg8Uint
1110 | Self::Rgba8Uint
1111 | Self::R16Uint
1112 | Self::Rg16Uint
1113 | Self::Rgba16Uint
1114 | Self::R32Uint
1115 | Self::R64Uint
1116 | Self::Rg32Uint
1117 | Self::Rgba32Uint
1118 | Self::Rgb10a2Uint => Some(uint),
1119
1120 Self::R8Sint
1121 | Self::Rg8Sint
1122 | Self::Rgba8Sint
1123 | Self::R16Sint
1124 | Self::Rg16Sint
1125 | Self::Rgba16Sint
1126 | Self::R32Sint
1127 | Self::Rg32Sint
1128 | Self::Rgba32Sint => Some(sint),
1129
1130 Self::Stencil8 => Some(uint),
1131 Self::Depth16Unorm | Self::Depth24Plus | Self::Depth32Float => Some(depth),
1132 Self::Depth24PlusStencil8 | Self::Depth32FloatStencil8 => match aspect {
1133 Some(TextureAspect::DepthOnly) => Some(depth),
1134 Some(TextureAspect::StencilOnly) => Some(uint),
1135 _ => None,
1136 },
1137
1138 Self::NV12 | Self::P010 => match aspect {
1139 Some(TextureAspect::Plane0) | Some(TextureAspect::Plane1) => {
1140 Some(unfilterable_float)
1141 }
1142 _ => None,
1143 },
1144
1145 Self::R16Unorm
1146 | Self::R16Snorm
1147 | Self::Rg16Unorm
1148 | Self::Rg16Snorm
1149 | Self::Rgba16Unorm
1150 | Self::Rgba16Snorm => Some(float),
1151
1152 Self::Rgb9e5Ufloat => Some(float),
1153
1154 Self::Bc1RgbaUnorm
1155 | Self::Bc1RgbaUnormSrgb
1156 | Self::Bc2RgbaUnorm
1157 | Self::Bc2RgbaUnormSrgb
1158 | Self::Bc3RgbaUnorm
1159 | Self::Bc3RgbaUnormSrgb
1160 | Self::Bc4RUnorm
1161 | Self::Bc4RSnorm
1162 | Self::Bc5RgUnorm
1163 | Self::Bc5RgSnorm
1164 | Self::Bc6hRgbUfloat
1165 | Self::Bc6hRgbFloat
1166 | Self::Bc7RgbaUnorm
1167 | Self::Bc7RgbaUnormSrgb => Some(float),
1168
1169 Self::Etc2Rgb8Unorm
1170 | Self::Etc2Rgb8UnormSrgb
1171 | Self::Etc2Rgb8A1Unorm
1172 | Self::Etc2Rgb8A1UnormSrgb
1173 | Self::Etc2Rgba8Unorm
1174 | Self::Etc2Rgba8UnormSrgb
1175 | Self::EacR11Unorm
1176 | Self::EacR11Snorm
1177 | Self::EacRg11Unorm
1178 | Self::EacRg11Snorm => Some(float),
1179
1180 Self::Astc { .. } => Some(float),
1181 }
1182 }
1183
1184 #[deprecated(since = "0.19.0", note = "Use `block_copy_size` instead.")]
1197 #[must_use]
1198 pub fn block_size(&self, aspect: Option<TextureAspect>) -> Option<u32> {
1199 self.block_copy_size(aspect)
1200 }
1201
1202 #[must_use]
1215 pub fn block_copy_size(&self, aspect: Option<TextureAspect>) -> Option<u32> {
1216 match *self {
1217 Self::R8Unorm | Self::R8Snorm | Self::R8Uint | Self::R8Sint => Some(1),
1218
1219 Self::Rg8Unorm | Self::Rg8Snorm | Self::Rg8Uint | Self::Rg8Sint => Some(2),
1220 Self::R16Unorm | Self::R16Snorm | Self::R16Uint | Self::R16Sint | Self::R16Float => {
1221 Some(2)
1222 }
1223
1224 Self::Rgba8Unorm
1225 | Self::Rgba8UnormSrgb
1226 | Self::Rgba8Snorm
1227 | Self::Rgba8Uint
1228 | Self::Rgba8Sint
1229 | Self::Bgra8Unorm
1230 | Self::Bgra8UnormSrgb => Some(4),
1231 Self::Rg16Unorm
1232 | Self::Rg16Snorm
1233 | Self::Rg16Uint
1234 | Self::Rg16Sint
1235 | Self::Rg16Float => Some(4),
1236 Self::R32Uint | Self::R32Sint | Self::R32Float => Some(4),
1237 Self::Rgb9e5Ufloat | Self::Rgb10a2Uint | Self::Rgb10a2Unorm | Self::Rg11b10Ufloat => {
1238 Some(4)
1239 }
1240
1241 Self::Rgba16Unorm
1242 | Self::Rgba16Snorm
1243 | Self::Rgba16Uint
1244 | Self::Rgba16Sint
1245 | Self::Rgba16Float => Some(8),
1246 Self::R64Uint | Self::Rg32Uint | Self::Rg32Sint | Self::Rg32Float => Some(8),
1247
1248 Self::Rgba32Uint | Self::Rgba32Sint | Self::Rgba32Float => Some(16),
1249
1250 Self::Stencil8 => Some(1),
1251 Self::Depth16Unorm => Some(2),
1252 Self::Depth32Float => Some(4),
1253 Self::Depth24Plus => None,
1254 Self::Depth24PlusStencil8 => match aspect {
1255 Some(TextureAspect::DepthOnly) => None,
1256 Some(TextureAspect::StencilOnly) => Some(1),
1257 _ => None,
1258 },
1259 Self::Depth32FloatStencil8 => match aspect {
1260 Some(TextureAspect::DepthOnly) => Some(4),
1261 Some(TextureAspect::StencilOnly) => Some(1),
1262 _ => None,
1263 },
1264
1265 Self::NV12 => match aspect {
1266 Some(TextureAspect::Plane0) => Some(1),
1267 Some(TextureAspect::Plane1) => Some(2),
1268 _ => None,
1269 },
1270
1271 Self::P010 => match aspect {
1272 Some(TextureAspect::Plane0) => Some(2),
1273 Some(TextureAspect::Plane1) => Some(4),
1274 _ => None,
1275 },
1276
1277 Self::Bc1RgbaUnorm | Self::Bc1RgbaUnormSrgb | Self::Bc4RUnorm | Self::Bc4RSnorm => {
1278 Some(8)
1279 }
1280 Self::Bc2RgbaUnorm
1281 | Self::Bc2RgbaUnormSrgb
1282 | Self::Bc3RgbaUnorm
1283 | Self::Bc3RgbaUnormSrgb
1284 | Self::Bc5RgUnorm
1285 | Self::Bc5RgSnorm
1286 | Self::Bc6hRgbUfloat
1287 | Self::Bc6hRgbFloat
1288 | Self::Bc7RgbaUnorm
1289 | Self::Bc7RgbaUnormSrgb => Some(16),
1290
1291 Self::Etc2Rgb8Unorm
1292 | Self::Etc2Rgb8UnormSrgb
1293 | Self::Etc2Rgb8A1Unorm
1294 | Self::Etc2Rgb8A1UnormSrgb
1295 | Self::EacR11Unorm
1296 | Self::EacR11Snorm => Some(8),
1297 Self::Etc2Rgba8Unorm
1298 | Self::Etc2Rgba8UnormSrgb
1299 | Self::EacRg11Unorm
1300 | Self::EacRg11Snorm => Some(16),
1301
1302 Self::Astc { .. } => Some(16),
1303 }
1304 }
1305
1306 pub const MAX_TARGET_PIXEL_BYTE_COST: u32 = 16;
1308
1309 #[must_use]
1312 pub fn target_pixel_byte_cost(&self) -> Option<u32> {
1313 match *self {
1314 Self::R8Unorm | Self::R8Snorm | Self::R8Uint | Self::R8Sint => Some(1),
1315 Self::Rg8Unorm
1316 | Self::Rg8Snorm
1317 | Self::Rg8Uint
1318 | Self::Rg8Sint
1319 | Self::R16Uint
1320 | Self::R16Sint
1321 | Self::R16Unorm
1322 | Self::R16Snorm
1323 | Self::R16Float => Some(2),
1324 Self::Rgba8Uint
1325 | Self::Rgba8Sint
1326 | Self::Rg16Uint
1327 | Self::Rg16Sint
1328 | Self::Rg16Unorm
1329 | Self::Rg16Snorm
1330 | Self::Rg16Float
1331 | Self::R32Uint
1332 | Self::R32Sint
1333 | Self::R32Float => Some(4),
1334 Self::Rgba8Unorm
1336 | Self::Rgba8UnormSrgb
1337 | Self::Rgba8Snorm
1338 | Self::Bgra8Unorm
1339 | Self::Bgra8UnormSrgb
1340 | Self::Rgba16Uint
1342 | Self::Rgba16Sint
1343 | Self::Rgba16Unorm
1344 | Self::Rgba16Snorm
1345 | Self::Rgba16Float
1346 | Self::R64Uint
1347 | Self::Rg32Uint
1348 | Self::Rg32Sint
1349 | Self::Rg32Float
1350 | Self::Rgb10a2Uint
1351 | Self::Rgb10a2Unorm
1352 | Self::Rg11b10Ufloat => Some(8),
1353 Self::Rgba32Uint | Self::Rgba32Sint | Self::Rgba32Float => Some(16),
1354 Self::Stencil8
1356 | Self::Depth16Unorm
1357 | Self::Depth24Plus
1358 | Self::Depth24PlusStencil8
1359 | Self::Depth32Float
1360 | Self::Depth32FloatStencil8
1361 | Self::NV12
1362 | Self::P010
1363 | Self::Rgb9e5Ufloat
1364 | Self::Bc1RgbaUnorm
1365 | Self::Bc1RgbaUnormSrgb
1366 | Self::Bc2RgbaUnorm
1367 | Self::Bc2RgbaUnormSrgb
1368 | Self::Bc3RgbaUnorm
1369 | Self::Bc3RgbaUnormSrgb
1370 | Self::Bc4RUnorm
1371 | Self::Bc4RSnorm
1372 | Self::Bc5RgUnorm
1373 | Self::Bc5RgSnorm
1374 | Self::Bc6hRgbUfloat
1375 | Self::Bc6hRgbFloat
1376 | Self::Bc7RgbaUnorm
1377 | Self::Bc7RgbaUnormSrgb
1378 | Self::Etc2Rgb8Unorm
1379 | Self::Etc2Rgb8UnormSrgb
1380 | Self::Etc2Rgb8A1Unorm
1381 | Self::Etc2Rgb8A1UnormSrgb
1382 | Self::Etc2Rgba8Unorm
1383 | Self::Etc2Rgba8UnormSrgb
1384 | Self::EacR11Unorm
1385 | Self::EacR11Snorm
1386 | Self::EacRg11Unorm
1387 | Self::EacRg11Snorm
1388 | Self::Astc { .. } => None,
1389 }
1390 }
1391
1392 #[must_use]
1394 pub fn target_component_alignment(&self) -> Option<u32> {
1395 match *self {
1396 Self::R8Unorm
1397 | Self::R8Snorm
1398 | Self::R8Uint
1399 | Self::R8Sint
1400 | Self::Rg8Unorm
1401 | Self::Rg8Snorm
1402 | Self::Rg8Uint
1403 | Self::Rg8Sint
1404 | Self::Rgba8Unorm
1405 | Self::Rgba8UnormSrgb
1406 | Self::Rgba8Snorm
1407 | Self::Rgba8Uint
1408 | Self::Rgba8Sint
1409 | Self::Bgra8Unorm
1410 | Self::Bgra8UnormSrgb => Some(1),
1411 Self::R16Uint
1412 | Self::R16Sint
1413 | Self::R16Unorm
1414 | Self::R16Snorm
1415 | Self::R16Float
1416 | Self::Rg16Uint
1417 | Self::Rg16Sint
1418 | Self::Rg16Unorm
1419 | Self::Rg16Snorm
1420 | Self::Rg16Float
1421 | Self::Rgba16Uint
1422 | Self::Rgba16Sint
1423 | Self::Rgba16Unorm
1424 | Self::Rgba16Snorm
1425 | Self::Rgba16Float => Some(2),
1426 Self::R32Uint
1427 | Self::R32Sint
1428 | Self::R32Float
1429 | Self::R64Uint
1430 | Self::Rg32Uint
1431 | Self::Rg32Sint
1432 | Self::Rg32Float
1433 | Self::Rgba32Uint
1434 | Self::Rgba32Sint
1435 | Self::Rgba32Float
1436 | Self::Rgb10a2Uint
1437 | Self::Rgb10a2Unorm
1438 | Self::Rg11b10Ufloat => Some(4),
1439 Self::Stencil8
1440 | Self::Depth16Unorm
1441 | Self::Depth24Plus
1442 | Self::Depth24PlusStencil8
1443 | Self::Depth32Float
1444 | Self::Depth32FloatStencil8
1445 | Self::NV12
1446 | Self::P010
1447 | Self::Rgb9e5Ufloat
1448 | Self::Bc1RgbaUnorm
1449 | Self::Bc1RgbaUnormSrgb
1450 | Self::Bc2RgbaUnorm
1451 | Self::Bc2RgbaUnormSrgb
1452 | Self::Bc3RgbaUnorm
1453 | Self::Bc3RgbaUnormSrgb
1454 | Self::Bc4RUnorm
1455 | Self::Bc4RSnorm
1456 | Self::Bc5RgUnorm
1457 | Self::Bc5RgSnorm
1458 | Self::Bc6hRgbUfloat
1459 | Self::Bc6hRgbFloat
1460 | Self::Bc7RgbaUnorm
1461 | Self::Bc7RgbaUnormSrgb
1462 | Self::Etc2Rgb8Unorm
1463 | Self::Etc2Rgb8UnormSrgb
1464 | Self::Etc2Rgb8A1Unorm
1465 | Self::Etc2Rgb8A1UnormSrgb
1466 | Self::Etc2Rgba8Unorm
1467 | Self::Etc2Rgba8UnormSrgb
1468 | Self::EacR11Unorm
1469 | Self::EacR11Snorm
1470 | Self::EacRg11Unorm
1471 | Self::EacRg11Snorm
1472 | Self::Astc { .. } => None,
1473 }
1474 }
1475
1476 #[must_use]
1478 pub fn components(&self) -> u8 {
1479 self.components_with_aspect(TextureAspect::All)
1480 }
1481
1482 #[must_use]
1486 pub fn components_with_aspect(&self, aspect: TextureAspect) -> u8 {
1487 match *self {
1488 Self::R8Unorm
1489 | Self::R8Snorm
1490 | Self::R8Uint
1491 | Self::R8Sint
1492 | Self::R16Unorm
1493 | Self::R16Snorm
1494 | Self::R16Uint
1495 | Self::R16Sint
1496 | Self::R16Float
1497 | Self::R32Uint
1498 | Self::R32Sint
1499 | Self::R32Float
1500 | Self::R64Uint => 1,
1501
1502 Self::Rg8Unorm
1503 | Self::Rg8Snorm
1504 | Self::Rg8Uint
1505 | Self::Rg8Sint
1506 | Self::Rg16Unorm
1507 | Self::Rg16Snorm
1508 | Self::Rg16Uint
1509 | Self::Rg16Sint
1510 | Self::Rg16Float
1511 | Self::Rg32Uint
1512 | Self::Rg32Sint
1513 | Self::Rg32Float => 2,
1514
1515 Self::Rgba8Unorm
1516 | Self::Rgba8UnormSrgb
1517 | Self::Rgba8Snorm
1518 | Self::Rgba8Uint
1519 | Self::Rgba8Sint
1520 | Self::Bgra8Unorm
1521 | Self::Bgra8UnormSrgb
1522 | Self::Rgba16Unorm
1523 | Self::Rgba16Snorm
1524 | Self::Rgba16Uint
1525 | Self::Rgba16Sint
1526 | Self::Rgba16Float
1527 | Self::Rgba32Uint
1528 | Self::Rgba32Sint
1529 | Self::Rgba32Float => 4,
1530
1531 Self::Rgb9e5Ufloat | Self::Rg11b10Ufloat => 3,
1532 Self::Rgb10a2Uint | Self::Rgb10a2Unorm => 4,
1533
1534 Self::Stencil8 | Self::Depth16Unorm | Self::Depth24Plus | Self::Depth32Float => 1,
1535
1536 Self::Depth24PlusStencil8 | Self::Depth32FloatStencil8 => match aspect {
1537 TextureAspect::DepthOnly | TextureAspect::StencilOnly => 1,
1538 _ => 2,
1539 },
1540
1541 Self::NV12 | Self::P010 => match aspect {
1542 TextureAspect::Plane0 => 1,
1543 TextureAspect::Plane1 => 2,
1544 _ => 3,
1545 },
1546
1547 Self::Bc4RUnorm | Self::Bc4RSnorm => 1,
1548 Self::Bc5RgUnorm | Self::Bc5RgSnorm => 2,
1549 Self::Bc6hRgbUfloat | Self::Bc6hRgbFloat => 3,
1550 Self::Bc1RgbaUnorm
1551 | Self::Bc1RgbaUnormSrgb
1552 | Self::Bc2RgbaUnorm
1553 | Self::Bc2RgbaUnormSrgb
1554 | Self::Bc3RgbaUnorm
1555 | Self::Bc3RgbaUnormSrgb
1556 | Self::Bc7RgbaUnorm
1557 | Self::Bc7RgbaUnormSrgb => 4,
1558
1559 Self::EacR11Unorm | Self::EacR11Snorm => 1,
1560 Self::EacRg11Unorm | Self::EacRg11Snorm => 2,
1561 Self::Etc2Rgb8Unorm | Self::Etc2Rgb8UnormSrgb => 3,
1562 Self::Etc2Rgb8A1Unorm
1563 | Self::Etc2Rgb8A1UnormSrgb
1564 | Self::Etc2Rgba8Unorm
1565 | Self::Etc2Rgba8UnormSrgb => 4,
1566
1567 Self::Astc { .. } => 4,
1568 }
1569 }
1570
1571 #[must_use]
1578 pub fn remove_srgb_suffix(&self) -> TextureFormat {
1579 match *self {
1580 Self::Rgba8UnormSrgb => Self::Rgba8Unorm,
1581 Self::Bgra8UnormSrgb => Self::Bgra8Unorm,
1582 Self::Bc1RgbaUnormSrgb => Self::Bc1RgbaUnorm,
1583 Self::Bc2RgbaUnormSrgb => Self::Bc2RgbaUnorm,
1584 Self::Bc3RgbaUnormSrgb => Self::Bc3RgbaUnorm,
1585 Self::Bc7RgbaUnormSrgb => Self::Bc7RgbaUnorm,
1586 Self::Etc2Rgb8UnormSrgb => Self::Etc2Rgb8Unorm,
1587 Self::Etc2Rgb8A1UnormSrgb => Self::Etc2Rgb8A1Unorm,
1588 Self::Etc2Rgba8UnormSrgb => Self::Etc2Rgba8Unorm,
1589 Self::Astc {
1590 block,
1591 channel: AstcChannel::UnormSrgb,
1592 } => Self::Astc {
1593 block,
1594 channel: AstcChannel::Unorm,
1595 },
1596 _ => *self,
1597 }
1598 }
1599
1600 #[must_use]
1606 pub fn add_srgb_suffix(&self) -> TextureFormat {
1607 match *self {
1608 Self::Rgba8Unorm => Self::Rgba8UnormSrgb,
1609 Self::Bgra8Unorm => Self::Bgra8UnormSrgb,
1610 Self::Bc1RgbaUnorm => Self::Bc1RgbaUnormSrgb,
1611 Self::Bc2RgbaUnorm => Self::Bc2RgbaUnormSrgb,
1612 Self::Bc3RgbaUnorm => Self::Bc3RgbaUnormSrgb,
1613 Self::Bc7RgbaUnorm => Self::Bc7RgbaUnormSrgb,
1614 Self::Etc2Rgb8Unorm => Self::Etc2Rgb8UnormSrgb,
1615 Self::Etc2Rgb8A1Unorm => Self::Etc2Rgb8A1UnormSrgb,
1616 Self::Etc2Rgba8Unorm => Self::Etc2Rgba8UnormSrgb,
1617 Self::Astc {
1618 block,
1619 channel: AstcChannel::Unorm,
1620 } => Self::Astc {
1621 block,
1622 channel: AstcChannel::UnormSrgb,
1623 },
1624 _ => *self,
1625 }
1626 }
1627
1628 #[must_use]
1635 pub fn has_srgb_suffix(&self) -> bool {
1636 *self != self.remove_srgb_suffix()
1637 }
1638
1639 #[must_use]
1643 pub fn theoretical_memory_footprint(&self, size: crate::Extent3d) -> u64 {
1644 let (block_width, block_height) = self.block_dimensions();
1645
1646 let block_size = self.block_copy_size(None);
1647
1648 let approximate_block_size = match block_size {
1649 Some(size) => size,
1650 None => match self {
1651 Self::Depth16Unorm => 2,
1653 Self::Depth24Plus => 4,
1655 Self::Depth24PlusStencil8 => 4,
1657 Self::Depth32Float => 4,
1659 Self::Depth32FloatStencil8 => 8,
1661 Self::Stencil8 => 1,
1663 Self::NV12 => 3,
1665 Self::P010 => 6,
1667 f => {
1668 unimplemented!("Memory footprint for format {f:?} is not implemented");
1669 }
1670 },
1671 };
1672
1673 let width_blocks = size.width.div_ceil(block_width) as u64;
1674 let height_blocks = size.height.div_ceil(block_height) as u64;
1675
1676 let total_blocks = width_blocks * height_blocks * size.depth_or_array_layers as u64;
1677
1678 total_blocks * approximate_block_size as u64
1679 }
1680}
1681
1682#[cfg(any(feature = "serde", test))]
1683impl<'de> Deserialize<'de> for TextureFormat {
1684 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1685 where
1686 D: serde::Deserializer<'de>,
1687 {
1688 use serde::de::{self, Error, Unexpected};
1689
1690 struct TextureFormatVisitor;
1691
1692 impl de::Visitor<'_> for TextureFormatVisitor {
1693 type Value = TextureFormat;
1694
1695 fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
1696 formatter.write_str("a valid texture format")
1697 }
1698
1699 fn visit_str<E: Error>(self, s: &str) -> Result<Self::Value, E> {
1700 let format = match s {
1701 "r8unorm" => TextureFormat::R8Unorm,
1702 "r8snorm" => TextureFormat::R8Snorm,
1703 "r8uint" => TextureFormat::R8Uint,
1704 "r8sint" => TextureFormat::R8Sint,
1705 "r16uint" => TextureFormat::R16Uint,
1706 "r16sint" => TextureFormat::R16Sint,
1707 "r16unorm" => TextureFormat::R16Unorm,
1708 "r16snorm" => TextureFormat::R16Snorm,
1709 "r16float" => TextureFormat::R16Float,
1710 "rg8unorm" => TextureFormat::Rg8Unorm,
1711 "rg8snorm" => TextureFormat::Rg8Snorm,
1712 "rg8uint" => TextureFormat::Rg8Uint,
1713 "rg8sint" => TextureFormat::Rg8Sint,
1714 "r32uint" => TextureFormat::R32Uint,
1715 "r32sint" => TextureFormat::R32Sint,
1716 "r32float" => TextureFormat::R32Float,
1717 "rg16uint" => TextureFormat::Rg16Uint,
1718 "rg16sint" => TextureFormat::Rg16Sint,
1719 "rg16unorm" => TextureFormat::Rg16Unorm,
1720 "rg16snorm" => TextureFormat::Rg16Snorm,
1721 "rg16float" => TextureFormat::Rg16Float,
1722 "rgba8unorm" => TextureFormat::Rgba8Unorm,
1723 "rgba8unorm-srgb" => TextureFormat::Rgba8UnormSrgb,
1724 "rgba8snorm" => TextureFormat::Rgba8Snorm,
1725 "rgba8uint" => TextureFormat::Rgba8Uint,
1726 "rgba8sint" => TextureFormat::Rgba8Sint,
1727 "bgra8unorm" => TextureFormat::Bgra8Unorm,
1728 "bgra8unorm-srgb" => TextureFormat::Bgra8UnormSrgb,
1729 "rgb10a2uint" => TextureFormat::Rgb10a2Uint,
1730 "rgb10a2unorm" => TextureFormat::Rgb10a2Unorm,
1731 "rg11b10ufloat" => TextureFormat::Rg11b10Ufloat,
1732 "r64uint" => TextureFormat::R64Uint,
1733 "rg32uint" => TextureFormat::Rg32Uint,
1734 "rg32sint" => TextureFormat::Rg32Sint,
1735 "rg32float" => TextureFormat::Rg32Float,
1736 "rgba16uint" => TextureFormat::Rgba16Uint,
1737 "rgba16sint" => TextureFormat::Rgba16Sint,
1738 "rgba16unorm" => TextureFormat::Rgba16Unorm,
1739 "rgba16snorm" => TextureFormat::Rgba16Snorm,
1740 "rgba16float" => TextureFormat::Rgba16Float,
1741 "rgba32uint" => TextureFormat::Rgba32Uint,
1742 "rgba32sint" => TextureFormat::Rgba32Sint,
1743 "rgba32float" => TextureFormat::Rgba32Float,
1744 "stencil8" => TextureFormat::Stencil8,
1745 "depth32float" => TextureFormat::Depth32Float,
1746 "depth32float-stencil8" => TextureFormat::Depth32FloatStencil8,
1747 "depth16unorm" => TextureFormat::Depth16Unorm,
1748 "depth24plus" => TextureFormat::Depth24Plus,
1749 "depth24plus-stencil8" => TextureFormat::Depth24PlusStencil8,
1750 "nv12" => TextureFormat::NV12,
1751 "p010" => TextureFormat::P010,
1752 "rgb9e5ufloat" => TextureFormat::Rgb9e5Ufloat,
1753 "bc1-rgba-unorm" => TextureFormat::Bc1RgbaUnorm,
1754 "bc1-rgba-unorm-srgb" => TextureFormat::Bc1RgbaUnormSrgb,
1755 "bc2-rgba-unorm" => TextureFormat::Bc2RgbaUnorm,
1756 "bc2-rgba-unorm-srgb" => TextureFormat::Bc2RgbaUnormSrgb,
1757 "bc3-rgba-unorm" => TextureFormat::Bc3RgbaUnorm,
1758 "bc3-rgba-unorm-srgb" => TextureFormat::Bc3RgbaUnormSrgb,
1759 "bc4-r-unorm" => TextureFormat::Bc4RUnorm,
1760 "bc4-r-snorm" => TextureFormat::Bc4RSnorm,
1761 "bc5-rg-unorm" => TextureFormat::Bc5RgUnorm,
1762 "bc5-rg-snorm" => TextureFormat::Bc5RgSnorm,
1763 "bc6h-rgb-ufloat" => TextureFormat::Bc6hRgbUfloat,
1764 "bc6h-rgb-float" => TextureFormat::Bc6hRgbFloat,
1765 "bc7-rgba-unorm" => TextureFormat::Bc7RgbaUnorm,
1766 "bc7-rgba-unorm-srgb" => TextureFormat::Bc7RgbaUnormSrgb,
1767 "etc2-rgb8unorm" => TextureFormat::Etc2Rgb8Unorm,
1768 "etc2-rgb8unorm-srgb" => TextureFormat::Etc2Rgb8UnormSrgb,
1769 "etc2-rgb8a1unorm" => TextureFormat::Etc2Rgb8A1Unorm,
1770 "etc2-rgb8a1unorm-srgb" => TextureFormat::Etc2Rgb8A1UnormSrgb,
1771 "etc2-rgba8unorm" => TextureFormat::Etc2Rgba8Unorm,
1772 "etc2-rgba8unorm-srgb" => TextureFormat::Etc2Rgba8UnormSrgb,
1773 "eac-r11unorm" => TextureFormat::EacR11Unorm,
1774 "eac-r11snorm" => TextureFormat::EacR11Snorm,
1775 "eac-rg11unorm" => TextureFormat::EacRg11Unorm,
1776 "eac-rg11snorm" => TextureFormat::EacRg11Snorm,
1777 other => {
1778 if let Some(parts) = other.strip_prefix("astc-") {
1779 let (block, channel) = parts
1780 .split_once('-')
1781 .ok_or_else(|| E::invalid_value(Unexpected::Str(s), &self))?;
1782
1783 let block = match block {
1784 "4x4" => AstcBlock::B4x4,
1785 "5x4" => AstcBlock::B5x4,
1786 "5x5" => AstcBlock::B5x5,
1787 "6x5" => AstcBlock::B6x5,
1788 "6x6" => AstcBlock::B6x6,
1789 "8x5" => AstcBlock::B8x5,
1790 "8x6" => AstcBlock::B8x6,
1791 "8x8" => AstcBlock::B8x8,
1792 "10x5" => AstcBlock::B10x5,
1793 "10x6" => AstcBlock::B10x6,
1794 "10x8" => AstcBlock::B10x8,
1795 "10x10" => AstcBlock::B10x10,
1796 "12x10" => AstcBlock::B12x10,
1797 "12x12" => AstcBlock::B12x12,
1798 _ => return Err(E::invalid_value(Unexpected::Str(s), &self)),
1799 };
1800
1801 let channel = match channel {
1802 "unorm" => AstcChannel::Unorm,
1803 "unorm-srgb" => AstcChannel::UnormSrgb,
1804 "hdr" => AstcChannel::Hdr,
1805 _ => return Err(E::invalid_value(Unexpected::Str(s), &self)),
1806 };
1807
1808 TextureFormat::Astc { block, channel }
1809 } else {
1810 return Err(E::invalid_value(Unexpected::Str(s), &self));
1811 }
1812 }
1813 };
1814
1815 Ok(format)
1816 }
1817 }
1818
1819 deserializer.deserialize_str(TextureFormatVisitor)
1820 }
1821}
1822
1823#[cfg(any(feature = "serde", test))]
1824impl Serialize for TextureFormat {
1825 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1826 where
1827 S: serde::Serializer,
1828 {
1829 let s: alloc::string::String;
1830 let name = match *self {
1831 TextureFormat::R8Unorm => "r8unorm",
1832 TextureFormat::R8Snorm => "r8snorm",
1833 TextureFormat::R8Uint => "r8uint",
1834 TextureFormat::R8Sint => "r8sint",
1835 TextureFormat::R16Uint => "r16uint",
1836 TextureFormat::R16Sint => "r16sint",
1837 TextureFormat::R16Unorm => "r16unorm",
1838 TextureFormat::R16Snorm => "r16snorm",
1839 TextureFormat::R16Float => "r16float",
1840 TextureFormat::Rg8Unorm => "rg8unorm",
1841 TextureFormat::Rg8Snorm => "rg8snorm",
1842 TextureFormat::Rg8Uint => "rg8uint",
1843 TextureFormat::Rg8Sint => "rg8sint",
1844 TextureFormat::R32Uint => "r32uint",
1845 TextureFormat::R32Sint => "r32sint",
1846 TextureFormat::R32Float => "r32float",
1847 TextureFormat::Rg16Uint => "rg16uint",
1848 TextureFormat::Rg16Sint => "rg16sint",
1849 TextureFormat::Rg16Unorm => "rg16unorm",
1850 TextureFormat::Rg16Snorm => "rg16snorm",
1851 TextureFormat::Rg16Float => "rg16float",
1852 TextureFormat::Rgba8Unorm => "rgba8unorm",
1853 TextureFormat::Rgba8UnormSrgb => "rgba8unorm-srgb",
1854 TextureFormat::Rgba8Snorm => "rgba8snorm",
1855 TextureFormat::Rgba8Uint => "rgba8uint",
1856 TextureFormat::Rgba8Sint => "rgba8sint",
1857 TextureFormat::Bgra8Unorm => "bgra8unorm",
1858 TextureFormat::Bgra8UnormSrgb => "bgra8unorm-srgb",
1859 TextureFormat::Rgb10a2Uint => "rgb10a2uint",
1860 TextureFormat::Rgb10a2Unorm => "rgb10a2unorm",
1861 TextureFormat::Rg11b10Ufloat => "rg11b10ufloat",
1862 TextureFormat::R64Uint => "r64uint",
1863 TextureFormat::Rg32Uint => "rg32uint",
1864 TextureFormat::Rg32Sint => "rg32sint",
1865 TextureFormat::Rg32Float => "rg32float",
1866 TextureFormat::Rgba16Uint => "rgba16uint",
1867 TextureFormat::Rgba16Sint => "rgba16sint",
1868 TextureFormat::Rgba16Unorm => "rgba16unorm",
1869 TextureFormat::Rgba16Snorm => "rgba16snorm",
1870 TextureFormat::Rgba16Float => "rgba16float",
1871 TextureFormat::Rgba32Uint => "rgba32uint",
1872 TextureFormat::Rgba32Sint => "rgba32sint",
1873 TextureFormat::Rgba32Float => "rgba32float",
1874 TextureFormat::Stencil8 => "stencil8",
1875 TextureFormat::Depth32Float => "depth32float",
1876 TextureFormat::Depth16Unorm => "depth16unorm",
1877 TextureFormat::Depth32FloatStencil8 => "depth32float-stencil8",
1878 TextureFormat::Depth24Plus => "depth24plus",
1879 TextureFormat::Depth24PlusStencil8 => "depth24plus-stencil8",
1880 TextureFormat::NV12 => "nv12",
1881 TextureFormat::P010 => "p010",
1882 TextureFormat::Rgb9e5Ufloat => "rgb9e5ufloat",
1883 TextureFormat::Bc1RgbaUnorm => "bc1-rgba-unorm",
1884 TextureFormat::Bc1RgbaUnormSrgb => "bc1-rgba-unorm-srgb",
1885 TextureFormat::Bc2RgbaUnorm => "bc2-rgba-unorm",
1886 TextureFormat::Bc2RgbaUnormSrgb => "bc2-rgba-unorm-srgb",
1887 TextureFormat::Bc3RgbaUnorm => "bc3-rgba-unorm",
1888 TextureFormat::Bc3RgbaUnormSrgb => "bc3-rgba-unorm-srgb",
1889 TextureFormat::Bc4RUnorm => "bc4-r-unorm",
1890 TextureFormat::Bc4RSnorm => "bc4-r-snorm",
1891 TextureFormat::Bc5RgUnorm => "bc5-rg-unorm",
1892 TextureFormat::Bc5RgSnorm => "bc5-rg-snorm",
1893 TextureFormat::Bc6hRgbUfloat => "bc6h-rgb-ufloat",
1894 TextureFormat::Bc6hRgbFloat => "bc6h-rgb-float",
1895 TextureFormat::Bc7RgbaUnorm => "bc7-rgba-unorm",
1896 TextureFormat::Bc7RgbaUnormSrgb => "bc7-rgba-unorm-srgb",
1897 TextureFormat::Etc2Rgb8Unorm => "etc2-rgb8unorm",
1898 TextureFormat::Etc2Rgb8UnormSrgb => "etc2-rgb8unorm-srgb",
1899 TextureFormat::Etc2Rgb8A1Unorm => "etc2-rgb8a1unorm",
1900 TextureFormat::Etc2Rgb8A1UnormSrgb => "etc2-rgb8a1unorm-srgb",
1901 TextureFormat::Etc2Rgba8Unorm => "etc2-rgba8unorm",
1902 TextureFormat::Etc2Rgba8UnormSrgb => "etc2-rgba8unorm-srgb",
1903 TextureFormat::EacR11Unorm => "eac-r11unorm",
1904 TextureFormat::EacR11Snorm => "eac-r11snorm",
1905 TextureFormat::EacRg11Unorm => "eac-rg11unorm",
1906 TextureFormat::EacRg11Snorm => "eac-rg11snorm",
1907 TextureFormat::Astc { block, channel } => {
1908 let block = match block {
1909 AstcBlock::B4x4 => "4x4",
1910 AstcBlock::B5x4 => "5x4",
1911 AstcBlock::B5x5 => "5x5",
1912 AstcBlock::B6x5 => "6x5",
1913 AstcBlock::B6x6 => "6x6",
1914 AstcBlock::B8x5 => "8x5",
1915 AstcBlock::B8x6 => "8x6",
1916 AstcBlock::B8x8 => "8x8",
1917 AstcBlock::B10x5 => "10x5",
1918 AstcBlock::B10x6 => "10x6",
1919 AstcBlock::B10x8 => "10x8",
1920 AstcBlock::B10x10 => "10x10",
1921 AstcBlock::B12x10 => "12x10",
1922 AstcBlock::B12x12 => "12x12",
1923 };
1924
1925 let channel = match channel {
1926 AstcChannel::Unorm => "unorm",
1927 AstcChannel::UnormSrgb => "unorm-srgb",
1928 AstcChannel::Hdr => "hdr",
1929 };
1930
1931 s = alloc::format!("astc-{block}-{channel}");
1932 &s
1933 }
1934 };
1935 serializer.serialize_str(name)
1936 }
1937}
1938
1939bitflags::bitflags! {
1940 #[repr(transparent)]
1942 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1943 #[cfg_attr(feature = "serde", serde(transparent))]
1944 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1945 pub struct TextureFormatFeatureFlags: u32 {
1946 const FILTERABLE = 1 << 0;
1949 const MULTISAMPLE_X2 = 1 << 1;
1951 const MULTISAMPLE_X4 = 1 << 2 ;
1953 const MULTISAMPLE_X8 = 1 << 3 ;
1955 const MULTISAMPLE_X16 = 1 << 4;
1957 const MULTISAMPLE_RESOLVE = 1 << 5;
1960 const STORAGE_READ_ONLY = 1 << 6;
1963 const STORAGE_WRITE_ONLY = 1 << 7;
1966 const STORAGE_READ_WRITE = 1 << 8;
1969 const STORAGE_ATOMIC = 1 << 9;
1972 const BLENDABLE = 1 << 10;
1974 }
1975}
1976
1977impl TextureFormatFeatureFlags {
1978 #[must_use]
1982 pub fn sample_count_supported(&self, count: u32) -> bool {
1983 use TextureFormatFeatureFlags as tfsc;
1984
1985 match count {
1986 1 => true,
1987 2 => self.contains(tfsc::MULTISAMPLE_X2),
1988 4 => self.contains(tfsc::MULTISAMPLE_X4),
1989 8 => self.contains(tfsc::MULTISAMPLE_X8),
1990 16 => self.contains(tfsc::MULTISAMPLE_X16),
1991 _ => false,
1992 }
1993 }
1994
1995 #[must_use]
1997 pub fn supported_sample_counts(&self) -> Vec<u32> {
1998 let all_possible_sample_counts: [u32; 5] = [1, 2, 4, 8, 16];
1999 all_possible_sample_counts
2000 .into_iter()
2001 .filter(|&sc| self.sample_count_supported(sc))
2002 .collect()
2003 }
2004}
2005
2006#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
2010#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2011pub struct TextureFormatFeatures {
2012 pub allowed_usages: TextureUsages,
2014 pub flags: TextureFormatFeatureFlags,
2016}
2017
2018#[cfg(test)]
2019mod tests {
2020 use super::*;
2021 use exhaust::Exhaust;
2022 use hashbrown::HashSet;
2023
2024 #[test]
2025 fn texture_format_serialize() {
2026 use alloc::string::ToString;
2027
2028 assert_eq!(
2029 serde_json::to_string(&TextureFormat::R8Unorm).unwrap(),
2030 "\"r8unorm\"".to_string()
2031 );
2032 assert_eq!(
2033 serde_json::to_string(&TextureFormat::R8Snorm).unwrap(),
2034 "\"r8snorm\"".to_string()
2035 );
2036 assert_eq!(
2037 serde_json::to_string(&TextureFormat::R8Uint).unwrap(),
2038 "\"r8uint\"".to_string()
2039 );
2040 assert_eq!(
2041 serde_json::to_string(&TextureFormat::R8Sint).unwrap(),
2042 "\"r8sint\"".to_string()
2043 );
2044 assert_eq!(
2045 serde_json::to_string(&TextureFormat::R16Uint).unwrap(),
2046 "\"r16uint\"".to_string()
2047 );
2048 assert_eq!(
2049 serde_json::to_string(&TextureFormat::R16Sint).unwrap(),
2050 "\"r16sint\"".to_string()
2051 );
2052 assert_eq!(
2053 serde_json::to_string(&TextureFormat::R16Unorm).unwrap(),
2054 "\"r16unorm\"".to_string()
2055 );
2056 assert_eq!(
2057 serde_json::to_string(&TextureFormat::R16Snorm).unwrap(),
2058 "\"r16snorm\"".to_string()
2059 );
2060 assert_eq!(
2061 serde_json::to_string(&TextureFormat::R16Float).unwrap(),
2062 "\"r16float\"".to_string()
2063 );
2064 assert_eq!(
2065 serde_json::to_string(&TextureFormat::Rg8Unorm).unwrap(),
2066 "\"rg8unorm\"".to_string()
2067 );
2068 assert_eq!(
2069 serde_json::to_string(&TextureFormat::Rg8Snorm).unwrap(),
2070 "\"rg8snorm\"".to_string()
2071 );
2072 assert_eq!(
2073 serde_json::to_string(&TextureFormat::Rg8Uint).unwrap(),
2074 "\"rg8uint\"".to_string()
2075 );
2076 assert_eq!(
2077 serde_json::to_string(&TextureFormat::Rg8Sint).unwrap(),
2078 "\"rg8sint\"".to_string()
2079 );
2080 assert_eq!(
2081 serde_json::to_string(&TextureFormat::R32Uint).unwrap(),
2082 "\"r32uint\"".to_string()
2083 );
2084 assert_eq!(
2085 serde_json::to_string(&TextureFormat::R32Sint).unwrap(),
2086 "\"r32sint\"".to_string()
2087 );
2088 assert_eq!(
2089 serde_json::to_string(&TextureFormat::R32Float).unwrap(),
2090 "\"r32float\"".to_string()
2091 );
2092 assert_eq!(
2093 serde_json::to_string(&TextureFormat::Rg16Uint).unwrap(),
2094 "\"rg16uint\"".to_string()
2095 );
2096 assert_eq!(
2097 serde_json::to_string(&TextureFormat::Rg16Sint).unwrap(),
2098 "\"rg16sint\"".to_string()
2099 );
2100 assert_eq!(
2101 serde_json::to_string(&TextureFormat::Rg16Unorm).unwrap(),
2102 "\"rg16unorm\"".to_string()
2103 );
2104 assert_eq!(
2105 serde_json::to_string(&TextureFormat::Rg16Snorm).unwrap(),
2106 "\"rg16snorm\"".to_string()
2107 );
2108 assert_eq!(
2109 serde_json::to_string(&TextureFormat::Rg16Float).unwrap(),
2110 "\"rg16float\"".to_string()
2111 );
2112 assert_eq!(
2113 serde_json::to_string(&TextureFormat::Rgba8Unorm).unwrap(),
2114 "\"rgba8unorm\"".to_string()
2115 );
2116 assert_eq!(
2117 serde_json::to_string(&TextureFormat::Rgba8UnormSrgb).unwrap(),
2118 "\"rgba8unorm-srgb\"".to_string()
2119 );
2120 assert_eq!(
2121 serde_json::to_string(&TextureFormat::Rgba8Snorm).unwrap(),
2122 "\"rgba8snorm\"".to_string()
2123 );
2124 assert_eq!(
2125 serde_json::to_string(&TextureFormat::Rgba8Uint).unwrap(),
2126 "\"rgba8uint\"".to_string()
2127 );
2128 assert_eq!(
2129 serde_json::to_string(&TextureFormat::Rgba8Sint).unwrap(),
2130 "\"rgba8sint\"".to_string()
2131 );
2132 assert_eq!(
2133 serde_json::to_string(&TextureFormat::Bgra8Unorm).unwrap(),
2134 "\"bgra8unorm\"".to_string()
2135 );
2136 assert_eq!(
2137 serde_json::to_string(&TextureFormat::Bgra8UnormSrgb).unwrap(),
2138 "\"bgra8unorm-srgb\"".to_string()
2139 );
2140 assert_eq!(
2141 serde_json::to_string(&TextureFormat::Rgb10a2Uint).unwrap(),
2142 "\"rgb10a2uint\"".to_string()
2143 );
2144 assert_eq!(
2145 serde_json::to_string(&TextureFormat::Rgb10a2Unorm).unwrap(),
2146 "\"rgb10a2unorm\"".to_string()
2147 );
2148 assert_eq!(
2149 serde_json::to_string(&TextureFormat::Rg11b10Ufloat).unwrap(),
2150 "\"rg11b10ufloat\"".to_string()
2151 );
2152 assert_eq!(
2153 serde_json::to_string(&TextureFormat::R64Uint).unwrap(),
2154 "\"r64uint\"".to_string()
2155 );
2156 assert_eq!(
2157 serde_json::to_string(&TextureFormat::Rg32Uint).unwrap(),
2158 "\"rg32uint\"".to_string()
2159 );
2160 assert_eq!(
2161 serde_json::to_string(&TextureFormat::Rg32Sint).unwrap(),
2162 "\"rg32sint\"".to_string()
2163 );
2164 assert_eq!(
2165 serde_json::to_string(&TextureFormat::Rg32Float).unwrap(),
2166 "\"rg32float\"".to_string()
2167 );
2168 assert_eq!(
2169 serde_json::to_string(&TextureFormat::Rgba16Uint).unwrap(),
2170 "\"rgba16uint\"".to_string()
2171 );
2172 assert_eq!(
2173 serde_json::to_string(&TextureFormat::Rgba16Sint).unwrap(),
2174 "\"rgba16sint\"".to_string()
2175 );
2176 assert_eq!(
2177 serde_json::to_string(&TextureFormat::Rgba16Unorm).unwrap(),
2178 "\"rgba16unorm\"".to_string()
2179 );
2180 assert_eq!(
2181 serde_json::to_string(&TextureFormat::Rgba16Snorm).unwrap(),
2182 "\"rgba16snorm\"".to_string()
2183 );
2184 assert_eq!(
2185 serde_json::to_string(&TextureFormat::Rgba16Float).unwrap(),
2186 "\"rgba16float\"".to_string()
2187 );
2188 assert_eq!(
2189 serde_json::to_string(&TextureFormat::Rgba32Uint).unwrap(),
2190 "\"rgba32uint\"".to_string()
2191 );
2192 assert_eq!(
2193 serde_json::to_string(&TextureFormat::Rgba32Sint).unwrap(),
2194 "\"rgba32sint\"".to_string()
2195 );
2196 assert_eq!(
2197 serde_json::to_string(&TextureFormat::Rgba32Float).unwrap(),
2198 "\"rgba32float\"".to_string()
2199 );
2200 assert_eq!(
2201 serde_json::to_string(&TextureFormat::Stencil8).unwrap(),
2202 "\"stencil8\"".to_string()
2203 );
2204 assert_eq!(
2205 serde_json::to_string(&TextureFormat::Depth32Float).unwrap(),
2206 "\"depth32float\"".to_string()
2207 );
2208 assert_eq!(
2209 serde_json::to_string(&TextureFormat::Depth16Unorm).unwrap(),
2210 "\"depth16unorm\"".to_string()
2211 );
2212 assert_eq!(
2213 serde_json::to_string(&TextureFormat::Depth32FloatStencil8).unwrap(),
2214 "\"depth32float-stencil8\"".to_string()
2215 );
2216 assert_eq!(
2217 serde_json::to_string(&TextureFormat::Depth24Plus).unwrap(),
2218 "\"depth24plus\"".to_string()
2219 );
2220 assert_eq!(
2221 serde_json::to_string(&TextureFormat::Depth24PlusStencil8).unwrap(),
2222 "\"depth24plus-stencil8\"".to_string()
2223 );
2224 assert_eq!(
2225 serde_json::to_string(&TextureFormat::Rgb9e5Ufloat).unwrap(),
2226 "\"rgb9e5ufloat\"".to_string()
2227 );
2228 assert_eq!(
2229 serde_json::to_string(&TextureFormat::Bc1RgbaUnorm).unwrap(),
2230 "\"bc1-rgba-unorm\"".to_string()
2231 );
2232 assert_eq!(
2233 serde_json::to_string(&TextureFormat::Bc1RgbaUnormSrgb).unwrap(),
2234 "\"bc1-rgba-unorm-srgb\"".to_string()
2235 );
2236 assert_eq!(
2237 serde_json::to_string(&TextureFormat::Bc2RgbaUnorm).unwrap(),
2238 "\"bc2-rgba-unorm\"".to_string()
2239 );
2240 assert_eq!(
2241 serde_json::to_string(&TextureFormat::Bc2RgbaUnormSrgb).unwrap(),
2242 "\"bc2-rgba-unorm-srgb\"".to_string()
2243 );
2244 assert_eq!(
2245 serde_json::to_string(&TextureFormat::Bc3RgbaUnorm).unwrap(),
2246 "\"bc3-rgba-unorm\"".to_string()
2247 );
2248 assert_eq!(
2249 serde_json::to_string(&TextureFormat::Bc3RgbaUnormSrgb).unwrap(),
2250 "\"bc3-rgba-unorm-srgb\"".to_string()
2251 );
2252 assert_eq!(
2253 serde_json::to_string(&TextureFormat::Bc4RUnorm).unwrap(),
2254 "\"bc4-r-unorm\"".to_string()
2255 );
2256 assert_eq!(
2257 serde_json::to_string(&TextureFormat::Bc4RSnorm).unwrap(),
2258 "\"bc4-r-snorm\"".to_string()
2259 );
2260 assert_eq!(
2261 serde_json::to_string(&TextureFormat::Bc5RgUnorm).unwrap(),
2262 "\"bc5-rg-unorm\"".to_string()
2263 );
2264 assert_eq!(
2265 serde_json::to_string(&TextureFormat::Bc5RgSnorm).unwrap(),
2266 "\"bc5-rg-snorm\"".to_string()
2267 );
2268 assert_eq!(
2269 serde_json::to_string(&TextureFormat::Bc6hRgbUfloat).unwrap(),
2270 "\"bc6h-rgb-ufloat\"".to_string()
2271 );
2272 assert_eq!(
2273 serde_json::to_string(&TextureFormat::Bc6hRgbFloat).unwrap(),
2274 "\"bc6h-rgb-float\"".to_string()
2275 );
2276 assert_eq!(
2277 serde_json::to_string(&TextureFormat::Bc7RgbaUnorm).unwrap(),
2278 "\"bc7-rgba-unorm\"".to_string()
2279 );
2280 assert_eq!(
2281 serde_json::to_string(&TextureFormat::Bc7RgbaUnormSrgb).unwrap(),
2282 "\"bc7-rgba-unorm-srgb\"".to_string()
2283 );
2284 assert_eq!(
2285 serde_json::to_string(&TextureFormat::Etc2Rgb8Unorm).unwrap(),
2286 "\"etc2-rgb8unorm\"".to_string()
2287 );
2288 assert_eq!(
2289 serde_json::to_string(&TextureFormat::Etc2Rgb8UnormSrgb).unwrap(),
2290 "\"etc2-rgb8unorm-srgb\"".to_string()
2291 );
2292 assert_eq!(
2293 serde_json::to_string(&TextureFormat::Etc2Rgb8A1Unorm).unwrap(),
2294 "\"etc2-rgb8a1unorm\"".to_string()
2295 );
2296 assert_eq!(
2297 serde_json::to_string(&TextureFormat::Etc2Rgb8A1UnormSrgb).unwrap(),
2298 "\"etc2-rgb8a1unorm-srgb\"".to_string()
2299 );
2300 assert_eq!(
2301 serde_json::to_string(&TextureFormat::Etc2Rgba8Unorm).unwrap(),
2302 "\"etc2-rgba8unorm\"".to_string()
2303 );
2304 assert_eq!(
2305 serde_json::to_string(&TextureFormat::Etc2Rgba8UnormSrgb).unwrap(),
2306 "\"etc2-rgba8unorm-srgb\"".to_string()
2307 );
2308 assert_eq!(
2309 serde_json::to_string(&TextureFormat::EacR11Unorm).unwrap(),
2310 "\"eac-r11unorm\"".to_string()
2311 );
2312 assert_eq!(
2313 serde_json::to_string(&TextureFormat::EacR11Snorm).unwrap(),
2314 "\"eac-r11snorm\"".to_string()
2315 );
2316 assert_eq!(
2317 serde_json::to_string(&TextureFormat::EacRg11Unorm).unwrap(),
2318 "\"eac-rg11unorm\"".to_string()
2319 );
2320 assert_eq!(
2321 serde_json::to_string(&TextureFormat::EacRg11Snorm).unwrap(),
2322 "\"eac-rg11snorm\"".to_string()
2323 );
2324 }
2325
2326 #[test]
2327 fn texture_format_deserialize() {
2328 assert_eq!(
2329 serde_json::from_str::<TextureFormat>("\"r8unorm\"").unwrap(),
2330 TextureFormat::R8Unorm
2331 );
2332 assert_eq!(
2333 serde_json::from_str::<TextureFormat>("\"r8snorm\"").unwrap(),
2334 TextureFormat::R8Snorm
2335 );
2336 assert_eq!(
2337 serde_json::from_str::<TextureFormat>("\"r8uint\"").unwrap(),
2338 TextureFormat::R8Uint
2339 );
2340 assert_eq!(
2341 serde_json::from_str::<TextureFormat>("\"r8sint\"").unwrap(),
2342 TextureFormat::R8Sint
2343 );
2344 assert_eq!(
2345 serde_json::from_str::<TextureFormat>("\"r16uint\"").unwrap(),
2346 TextureFormat::R16Uint
2347 );
2348 assert_eq!(
2349 serde_json::from_str::<TextureFormat>("\"r16sint\"").unwrap(),
2350 TextureFormat::R16Sint
2351 );
2352 assert_eq!(
2353 serde_json::from_str::<TextureFormat>("\"r16unorm\"").unwrap(),
2354 TextureFormat::R16Unorm
2355 );
2356 assert_eq!(
2357 serde_json::from_str::<TextureFormat>("\"r16snorm\"").unwrap(),
2358 TextureFormat::R16Snorm
2359 );
2360 assert_eq!(
2361 serde_json::from_str::<TextureFormat>("\"r16float\"").unwrap(),
2362 TextureFormat::R16Float
2363 );
2364 assert_eq!(
2365 serde_json::from_str::<TextureFormat>("\"rg8unorm\"").unwrap(),
2366 TextureFormat::Rg8Unorm
2367 );
2368 assert_eq!(
2369 serde_json::from_str::<TextureFormat>("\"rg8snorm\"").unwrap(),
2370 TextureFormat::Rg8Snorm
2371 );
2372 assert_eq!(
2373 serde_json::from_str::<TextureFormat>("\"rg8uint\"").unwrap(),
2374 TextureFormat::Rg8Uint
2375 );
2376 assert_eq!(
2377 serde_json::from_str::<TextureFormat>("\"rg8sint\"").unwrap(),
2378 TextureFormat::Rg8Sint
2379 );
2380 assert_eq!(
2381 serde_json::from_str::<TextureFormat>("\"r32uint\"").unwrap(),
2382 TextureFormat::R32Uint
2383 );
2384 assert_eq!(
2385 serde_json::from_str::<TextureFormat>("\"r32sint\"").unwrap(),
2386 TextureFormat::R32Sint
2387 );
2388 assert_eq!(
2389 serde_json::from_str::<TextureFormat>("\"r32float\"").unwrap(),
2390 TextureFormat::R32Float
2391 );
2392 assert_eq!(
2393 serde_json::from_str::<TextureFormat>("\"rg16uint\"").unwrap(),
2394 TextureFormat::Rg16Uint
2395 );
2396 assert_eq!(
2397 serde_json::from_str::<TextureFormat>("\"rg16sint\"").unwrap(),
2398 TextureFormat::Rg16Sint
2399 );
2400 assert_eq!(
2401 serde_json::from_str::<TextureFormat>("\"rg16unorm\"").unwrap(),
2402 TextureFormat::Rg16Unorm
2403 );
2404 assert_eq!(
2405 serde_json::from_str::<TextureFormat>("\"rg16snorm\"").unwrap(),
2406 TextureFormat::Rg16Snorm
2407 );
2408 assert_eq!(
2409 serde_json::from_str::<TextureFormat>("\"rg16float\"").unwrap(),
2410 TextureFormat::Rg16Float
2411 );
2412 assert_eq!(
2413 serde_json::from_str::<TextureFormat>("\"rgba8unorm\"").unwrap(),
2414 TextureFormat::Rgba8Unorm
2415 );
2416 assert_eq!(
2417 serde_json::from_str::<TextureFormat>("\"rgba8unorm-srgb\"").unwrap(),
2418 TextureFormat::Rgba8UnormSrgb
2419 );
2420 assert_eq!(
2421 serde_json::from_str::<TextureFormat>("\"rgba8snorm\"").unwrap(),
2422 TextureFormat::Rgba8Snorm
2423 );
2424 assert_eq!(
2425 serde_json::from_str::<TextureFormat>("\"rgba8uint\"").unwrap(),
2426 TextureFormat::Rgba8Uint
2427 );
2428 assert_eq!(
2429 serde_json::from_str::<TextureFormat>("\"rgba8sint\"").unwrap(),
2430 TextureFormat::Rgba8Sint
2431 );
2432 assert_eq!(
2433 serde_json::from_str::<TextureFormat>("\"bgra8unorm\"").unwrap(),
2434 TextureFormat::Bgra8Unorm
2435 );
2436 assert_eq!(
2437 serde_json::from_str::<TextureFormat>("\"bgra8unorm-srgb\"").unwrap(),
2438 TextureFormat::Bgra8UnormSrgb
2439 );
2440 assert_eq!(
2441 serde_json::from_str::<TextureFormat>("\"rgb10a2uint\"").unwrap(),
2442 TextureFormat::Rgb10a2Uint
2443 );
2444 assert_eq!(
2445 serde_json::from_str::<TextureFormat>("\"rgb10a2unorm\"").unwrap(),
2446 TextureFormat::Rgb10a2Unorm
2447 );
2448 assert_eq!(
2449 serde_json::from_str::<TextureFormat>("\"rg11b10ufloat\"").unwrap(),
2450 TextureFormat::Rg11b10Ufloat
2451 );
2452 assert_eq!(
2453 serde_json::from_str::<TextureFormat>("\"r64uint\"").unwrap(),
2454 TextureFormat::R64Uint
2455 );
2456 assert_eq!(
2457 serde_json::from_str::<TextureFormat>("\"rg32uint\"").unwrap(),
2458 TextureFormat::Rg32Uint
2459 );
2460 assert_eq!(
2461 serde_json::from_str::<TextureFormat>("\"rg32sint\"").unwrap(),
2462 TextureFormat::Rg32Sint
2463 );
2464 assert_eq!(
2465 serde_json::from_str::<TextureFormat>("\"rg32float\"").unwrap(),
2466 TextureFormat::Rg32Float
2467 );
2468 assert_eq!(
2469 serde_json::from_str::<TextureFormat>("\"rgba16uint\"").unwrap(),
2470 TextureFormat::Rgba16Uint
2471 );
2472 assert_eq!(
2473 serde_json::from_str::<TextureFormat>("\"rgba16sint\"").unwrap(),
2474 TextureFormat::Rgba16Sint
2475 );
2476 assert_eq!(
2477 serde_json::from_str::<TextureFormat>("\"rgba16unorm\"").unwrap(),
2478 TextureFormat::Rgba16Unorm
2479 );
2480 assert_eq!(
2481 serde_json::from_str::<TextureFormat>("\"rgba16snorm\"").unwrap(),
2482 TextureFormat::Rgba16Snorm
2483 );
2484 assert_eq!(
2485 serde_json::from_str::<TextureFormat>("\"rgba16float\"").unwrap(),
2486 TextureFormat::Rgba16Float
2487 );
2488 assert_eq!(
2489 serde_json::from_str::<TextureFormat>("\"rgba32uint\"").unwrap(),
2490 TextureFormat::Rgba32Uint
2491 );
2492 assert_eq!(
2493 serde_json::from_str::<TextureFormat>("\"rgba32sint\"").unwrap(),
2494 TextureFormat::Rgba32Sint
2495 );
2496 assert_eq!(
2497 serde_json::from_str::<TextureFormat>("\"rgba32float\"").unwrap(),
2498 TextureFormat::Rgba32Float
2499 );
2500 assert_eq!(
2501 serde_json::from_str::<TextureFormat>("\"stencil8\"").unwrap(),
2502 TextureFormat::Stencil8
2503 );
2504 assert_eq!(
2505 serde_json::from_str::<TextureFormat>("\"depth32float\"").unwrap(),
2506 TextureFormat::Depth32Float
2507 );
2508 assert_eq!(
2509 serde_json::from_str::<TextureFormat>("\"depth16unorm\"").unwrap(),
2510 TextureFormat::Depth16Unorm
2511 );
2512 assert_eq!(
2513 serde_json::from_str::<TextureFormat>("\"depth32float-stencil8\"").unwrap(),
2514 TextureFormat::Depth32FloatStencil8
2515 );
2516 assert_eq!(
2517 serde_json::from_str::<TextureFormat>("\"depth24plus\"").unwrap(),
2518 TextureFormat::Depth24Plus
2519 );
2520 assert_eq!(
2521 serde_json::from_str::<TextureFormat>("\"depth24plus-stencil8\"").unwrap(),
2522 TextureFormat::Depth24PlusStencil8
2523 );
2524 assert_eq!(
2525 serde_json::from_str::<TextureFormat>("\"rgb9e5ufloat\"").unwrap(),
2526 TextureFormat::Rgb9e5Ufloat
2527 );
2528 assert_eq!(
2529 serde_json::from_str::<TextureFormat>("\"bc1-rgba-unorm\"").unwrap(),
2530 TextureFormat::Bc1RgbaUnorm
2531 );
2532 assert_eq!(
2533 serde_json::from_str::<TextureFormat>("\"bc1-rgba-unorm-srgb\"").unwrap(),
2534 TextureFormat::Bc1RgbaUnormSrgb
2535 );
2536 assert_eq!(
2537 serde_json::from_str::<TextureFormat>("\"bc2-rgba-unorm\"").unwrap(),
2538 TextureFormat::Bc2RgbaUnorm
2539 );
2540 assert_eq!(
2541 serde_json::from_str::<TextureFormat>("\"bc2-rgba-unorm-srgb\"").unwrap(),
2542 TextureFormat::Bc2RgbaUnormSrgb
2543 );
2544 assert_eq!(
2545 serde_json::from_str::<TextureFormat>("\"bc3-rgba-unorm\"").unwrap(),
2546 TextureFormat::Bc3RgbaUnorm
2547 );
2548 assert_eq!(
2549 serde_json::from_str::<TextureFormat>("\"bc3-rgba-unorm-srgb\"").unwrap(),
2550 TextureFormat::Bc3RgbaUnormSrgb
2551 );
2552 assert_eq!(
2553 serde_json::from_str::<TextureFormat>("\"bc4-r-unorm\"").unwrap(),
2554 TextureFormat::Bc4RUnorm
2555 );
2556 assert_eq!(
2557 serde_json::from_str::<TextureFormat>("\"bc4-r-snorm\"").unwrap(),
2558 TextureFormat::Bc4RSnorm
2559 );
2560 assert_eq!(
2561 serde_json::from_str::<TextureFormat>("\"bc5-rg-unorm\"").unwrap(),
2562 TextureFormat::Bc5RgUnorm
2563 );
2564 assert_eq!(
2565 serde_json::from_str::<TextureFormat>("\"bc5-rg-snorm\"").unwrap(),
2566 TextureFormat::Bc5RgSnorm
2567 );
2568 assert_eq!(
2569 serde_json::from_str::<TextureFormat>("\"bc6h-rgb-ufloat\"").unwrap(),
2570 TextureFormat::Bc6hRgbUfloat
2571 );
2572 assert_eq!(
2573 serde_json::from_str::<TextureFormat>("\"bc6h-rgb-float\"").unwrap(),
2574 TextureFormat::Bc6hRgbFloat
2575 );
2576 assert_eq!(
2577 serde_json::from_str::<TextureFormat>("\"bc7-rgba-unorm\"").unwrap(),
2578 TextureFormat::Bc7RgbaUnorm
2579 );
2580 assert_eq!(
2581 serde_json::from_str::<TextureFormat>("\"bc7-rgba-unorm-srgb\"").unwrap(),
2582 TextureFormat::Bc7RgbaUnormSrgb
2583 );
2584 assert_eq!(
2585 serde_json::from_str::<TextureFormat>("\"etc2-rgb8unorm\"").unwrap(),
2586 TextureFormat::Etc2Rgb8Unorm
2587 );
2588 assert_eq!(
2589 serde_json::from_str::<TextureFormat>("\"etc2-rgb8unorm-srgb\"").unwrap(),
2590 TextureFormat::Etc2Rgb8UnormSrgb
2591 );
2592 assert_eq!(
2593 serde_json::from_str::<TextureFormat>("\"etc2-rgb8a1unorm\"").unwrap(),
2594 TextureFormat::Etc2Rgb8A1Unorm
2595 );
2596 assert_eq!(
2597 serde_json::from_str::<TextureFormat>("\"etc2-rgb8a1unorm-srgb\"").unwrap(),
2598 TextureFormat::Etc2Rgb8A1UnormSrgb
2599 );
2600 assert_eq!(
2601 serde_json::from_str::<TextureFormat>("\"etc2-rgba8unorm\"").unwrap(),
2602 TextureFormat::Etc2Rgba8Unorm
2603 );
2604 assert_eq!(
2605 serde_json::from_str::<TextureFormat>("\"etc2-rgba8unorm-srgb\"").unwrap(),
2606 TextureFormat::Etc2Rgba8UnormSrgb
2607 );
2608 assert_eq!(
2609 serde_json::from_str::<TextureFormat>("\"eac-r11unorm\"").unwrap(),
2610 TextureFormat::EacR11Unorm
2611 );
2612 assert_eq!(
2613 serde_json::from_str::<TextureFormat>("\"eac-r11snorm\"").unwrap(),
2614 TextureFormat::EacR11Snorm
2615 );
2616 assert_eq!(
2617 serde_json::from_str::<TextureFormat>("\"eac-rg11unorm\"").unwrap(),
2618 TextureFormat::EacRg11Unorm
2619 );
2620 assert_eq!(
2621 serde_json::from_str::<TextureFormat>("\"eac-rg11snorm\"").unwrap(),
2622 TextureFormat::EacRg11Snorm
2623 );
2624 }
2625
2626 #[test]
2628 fn is_depth_stencil_format() {
2629 let depth_stencil_formats: HashSet<TextureFormat> = HashSet::from([
2631 TextureFormat::Stencil8,
2632 TextureFormat::Depth16Unorm,
2633 TextureFormat::Depth24Plus,
2634 TextureFormat::Depth24PlusStencil8,
2635 TextureFormat::Depth32Float,
2636 TextureFormat::Depth32FloatStencil8,
2637 ]);
2638
2639 for format in TextureFormat::exhaust() {
2640 if depth_stencil_formats.contains(&format) {
2641 assert!(format.is_depth_stencil_format());
2642 } else {
2643 assert!(!format.is_depth_stencil_format());
2644 }
2645 }
2646 }
2647
2648 #[test]
2650 fn is_combined_depth_stencil_format() {
2651 let valid_formats = [
2653 TextureFormat::Depth24PlusStencil8,
2654 TextureFormat::Depth32FloatStencil8,
2655 ];
2656
2657 for format in TextureFormat::exhaust() {
2658 if valid_formats.contains(&format) {
2659 assert!(format.is_combined_depth_stencil_format());
2660 } else {
2661 assert!(!format.is_combined_depth_stencil_format());
2662 }
2663 }
2664 }
2665
2666 #[test]
2668 fn has_color_aspect() {
2669 let valid_formats: HashSet<TextureFormat> = HashSet::from([
2671 TextureFormat::R8Unorm,
2672 TextureFormat::R8Snorm,
2673 TextureFormat::R8Uint,
2674 TextureFormat::R8Sint,
2675 TextureFormat::R16Uint,
2676 TextureFormat::R16Sint,
2677 TextureFormat::R16Unorm,
2678 TextureFormat::R16Snorm,
2679 TextureFormat::R16Float,
2680 TextureFormat::Rg8Unorm,
2681 TextureFormat::Rg8Snorm,
2682 TextureFormat::Rg8Uint,
2683 TextureFormat::Rg8Sint,
2684 TextureFormat::R32Uint,
2685 TextureFormat::R32Sint,
2686 TextureFormat::R32Float,
2687 TextureFormat::Rg16Uint,
2688 TextureFormat::Rg16Sint,
2689 TextureFormat::Rg16Unorm,
2690 TextureFormat::Rg16Snorm,
2691 TextureFormat::Rg16Float,
2692 TextureFormat::Rgba8Unorm,
2693 TextureFormat::Rgba8UnormSrgb,
2694 TextureFormat::Rgba8Snorm,
2695 TextureFormat::Rgba8Uint,
2696 TextureFormat::Rgba8Sint,
2697 TextureFormat::Bgra8Unorm,
2698 TextureFormat::Bgra8UnormSrgb,
2699 TextureFormat::Rgb9e5Ufloat,
2700 TextureFormat::Rgb10a2Uint,
2701 TextureFormat::Rgb10a2Unorm,
2702 TextureFormat::Rg11b10Ufloat,
2703 TextureFormat::R64Uint,
2704 TextureFormat::Rg32Uint,
2705 TextureFormat::Rg32Sint,
2706 TextureFormat::Rg32Float,
2707 TextureFormat::Rgba16Uint,
2708 TextureFormat::Rgba16Sint,
2709 TextureFormat::Rgba16Unorm,
2710 TextureFormat::Rgba16Snorm,
2711 TextureFormat::Rgba16Float,
2712 TextureFormat::Rgba32Uint,
2713 TextureFormat::Rgba32Sint,
2714 TextureFormat::Rgba32Float,
2715 TextureFormat::Bc1RgbaUnorm,
2716 TextureFormat::Bc1RgbaUnormSrgb,
2717 TextureFormat::Bc2RgbaUnorm,
2718 TextureFormat::Bc2RgbaUnormSrgb,
2719 TextureFormat::Bc3RgbaUnorm,
2720 TextureFormat::Bc3RgbaUnormSrgb,
2721 TextureFormat::Bc4RUnorm,
2722 TextureFormat::Bc4RSnorm,
2723 TextureFormat::Bc5RgUnorm,
2724 TextureFormat::Bc5RgSnorm,
2725 TextureFormat::Bc6hRgbUfloat,
2726 TextureFormat::Bc6hRgbFloat,
2727 TextureFormat::Bc7RgbaUnorm,
2728 TextureFormat::Bc7RgbaUnormSrgb,
2729 TextureFormat::Etc2Rgb8Unorm,
2730 TextureFormat::Etc2Rgb8UnormSrgb,
2731 TextureFormat::Etc2Rgb8A1Unorm,
2732 TextureFormat::Etc2Rgb8A1UnormSrgb,
2733 TextureFormat::Etc2Rgba8Unorm,
2734 TextureFormat::Etc2Rgba8UnormSrgb,
2735 TextureFormat::EacR11Unorm,
2736 TextureFormat::EacR11Snorm,
2737 TextureFormat::EacRg11Unorm,
2738 TextureFormat::EacRg11Snorm,
2739 ]);
2740
2741 for format in TextureFormat::exhaust() {
2742 if let TextureFormat::Astc { .. } = format {
2743 assert!(format.has_color_aspect(), "{:?} failed", format);
2745 } else if valid_formats.contains(&format) {
2746 assert!(format.has_color_aspect(), "{:?} failed", format);
2747 } else {
2748 assert!(!format.has_color_aspect(), "{:?} failed", format);
2749 }
2750 }
2751 }
2752
2753 #[test]
2755 fn has_depth_aspect() {
2756 let valid_formats: HashSet<TextureFormat> = HashSet::from([
2758 TextureFormat::Depth16Unorm,
2759 TextureFormat::Depth24Plus,
2760 TextureFormat::Depth24PlusStencil8,
2761 TextureFormat::Depth32Float,
2762 TextureFormat::Depth32FloatStencil8,
2763 ]);
2764
2765 for format in TextureFormat::exhaust() {
2766 if valid_formats.contains(&format) {
2767 assert!(format.has_depth_aspect());
2768 } else {
2769 assert!(!format.has_depth_aspect());
2770 }
2771 }
2772 }
2773
2774 #[test]
2776 fn has_stencil_aspect() {
2777 let valid_formats: HashSet<TextureFormat> = HashSet::from([
2779 TextureFormat::Stencil8,
2780 TextureFormat::Depth24PlusStencil8,
2781 TextureFormat::Depth32FloatStencil8,
2782 ]);
2783
2784 for format in TextureFormat::exhaust() {
2785 if valid_formats.contains(&format) {
2786 assert!(format.has_stencil_aspect());
2787 } else {
2788 assert!(!format.has_stencil_aspect());
2789 }
2790 }
2791 }
2792}