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]
1573 pub fn remove_srgb_suffix(&self) -> TextureFormat {
1574 match *self {
1575 Self::Rgba8UnormSrgb => Self::Rgba8Unorm,
1576 Self::Bgra8UnormSrgb => Self::Bgra8Unorm,
1577 Self::Bc1RgbaUnormSrgb => Self::Bc1RgbaUnorm,
1578 Self::Bc2RgbaUnormSrgb => Self::Bc2RgbaUnorm,
1579 Self::Bc3RgbaUnormSrgb => Self::Bc3RgbaUnorm,
1580 Self::Bc7RgbaUnormSrgb => Self::Bc7RgbaUnorm,
1581 Self::Etc2Rgb8UnormSrgb => Self::Etc2Rgb8Unorm,
1582 Self::Etc2Rgb8A1UnormSrgb => Self::Etc2Rgb8A1Unorm,
1583 Self::Etc2Rgba8UnormSrgb => Self::Etc2Rgba8Unorm,
1584 Self::Astc {
1585 block,
1586 channel: AstcChannel::UnormSrgb,
1587 } => Self::Astc {
1588 block,
1589 channel: AstcChannel::Unorm,
1590 },
1591 _ => *self,
1592 }
1593 }
1594
1595 #[must_use]
1597 pub fn add_srgb_suffix(&self) -> TextureFormat {
1598 match *self {
1599 Self::Rgba8Unorm => Self::Rgba8UnormSrgb,
1600 Self::Bgra8Unorm => Self::Bgra8UnormSrgb,
1601 Self::Bc1RgbaUnorm => Self::Bc1RgbaUnormSrgb,
1602 Self::Bc2RgbaUnorm => Self::Bc2RgbaUnormSrgb,
1603 Self::Bc3RgbaUnorm => Self::Bc3RgbaUnormSrgb,
1604 Self::Bc7RgbaUnorm => Self::Bc7RgbaUnormSrgb,
1605 Self::Etc2Rgb8Unorm => Self::Etc2Rgb8UnormSrgb,
1606 Self::Etc2Rgb8A1Unorm => Self::Etc2Rgb8A1UnormSrgb,
1607 Self::Etc2Rgba8Unorm => Self::Etc2Rgba8UnormSrgb,
1608 Self::Astc {
1609 block,
1610 channel: AstcChannel::Unorm,
1611 } => Self::Astc {
1612 block,
1613 channel: AstcChannel::UnormSrgb,
1614 },
1615 _ => *self,
1616 }
1617 }
1618
1619 #[must_use]
1621 pub fn is_srgb(&self) -> bool {
1622 *self != self.remove_srgb_suffix()
1623 }
1624
1625 #[must_use]
1629 pub fn theoretical_memory_footprint(&self, size: crate::Extent3d) -> u64 {
1630 let (block_width, block_height) = self.block_dimensions();
1631
1632 let block_size = self.block_copy_size(None);
1633
1634 let approximate_block_size = match block_size {
1635 Some(size) => size,
1636 None => match self {
1637 Self::Depth16Unorm => 2,
1639 Self::Depth24Plus => 4,
1641 Self::Depth24PlusStencil8 => 4,
1643 Self::Depth32Float => 4,
1645 Self::Depth32FloatStencil8 => 8,
1647 Self::Stencil8 => 1,
1649 Self::NV12 => 3,
1651 Self::P010 => 6,
1653 f => {
1654 unimplemented!("Memory footprint for format {f:?} is not implemented");
1655 }
1656 },
1657 };
1658
1659 let width_blocks = size.width.div_ceil(block_width) as u64;
1660 let height_blocks = size.height.div_ceil(block_height) as u64;
1661
1662 let total_blocks = width_blocks * height_blocks * size.depth_or_array_layers as u64;
1663
1664 total_blocks * approximate_block_size as u64
1665 }
1666}
1667
1668#[cfg(any(feature = "serde", test))]
1669impl<'de> Deserialize<'de> for TextureFormat {
1670 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1671 where
1672 D: serde::Deserializer<'de>,
1673 {
1674 use serde::de::{self, Error, Unexpected};
1675
1676 struct TextureFormatVisitor;
1677
1678 impl de::Visitor<'_> for TextureFormatVisitor {
1679 type Value = TextureFormat;
1680
1681 fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
1682 formatter.write_str("a valid texture format")
1683 }
1684
1685 fn visit_str<E: Error>(self, s: &str) -> Result<Self::Value, E> {
1686 let format = match s {
1687 "r8unorm" => TextureFormat::R8Unorm,
1688 "r8snorm" => TextureFormat::R8Snorm,
1689 "r8uint" => TextureFormat::R8Uint,
1690 "r8sint" => TextureFormat::R8Sint,
1691 "r16uint" => TextureFormat::R16Uint,
1692 "r16sint" => TextureFormat::R16Sint,
1693 "r16unorm" => TextureFormat::R16Unorm,
1694 "r16snorm" => TextureFormat::R16Snorm,
1695 "r16float" => TextureFormat::R16Float,
1696 "rg8unorm" => TextureFormat::Rg8Unorm,
1697 "rg8snorm" => TextureFormat::Rg8Snorm,
1698 "rg8uint" => TextureFormat::Rg8Uint,
1699 "rg8sint" => TextureFormat::Rg8Sint,
1700 "r32uint" => TextureFormat::R32Uint,
1701 "r32sint" => TextureFormat::R32Sint,
1702 "r32float" => TextureFormat::R32Float,
1703 "rg16uint" => TextureFormat::Rg16Uint,
1704 "rg16sint" => TextureFormat::Rg16Sint,
1705 "rg16unorm" => TextureFormat::Rg16Unorm,
1706 "rg16snorm" => TextureFormat::Rg16Snorm,
1707 "rg16float" => TextureFormat::Rg16Float,
1708 "rgba8unorm" => TextureFormat::Rgba8Unorm,
1709 "rgba8unorm-srgb" => TextureFormat::Rgba8UnormSrgb,
1710 "rgba8snorm" => TextureFormat::Rgba8Snorm,
1711 "rgba8uint" => TextureFormat::Rgba8Uint,
1712 "rgba8sint" => TextureFormat::Rgba8Sint,
1713 "bgra8unorm" => TextureFormat::Bgra8Unorm,
1714 "bgra8unorm-srgb" => TextureFormat::Bgra8UnormSrgb,
1715 "rgb10a2uint" => TextureFormat::Rgb10a2Uint,
1716 "rgb10a2unorm" => TextureFormat::Rgb10a2Unorm,
1717 "rg11b10ufloat" => TextureFormat::Rg11b10Ufloat,
1718 "r64uint" => TextureFormat::R64Uint,
1719 "rg32uint" => TextureFormat::Rg32Uint,
1720 "rg32sint" => TextureFormat::Rg32Sint,
1721 "rg32float" => TextureFormat::Rg32Float,
1722 "rgba16uint" => TextureFormat::Rgba16Uint,
1723 "rgba16sint" => TextureFormat::Rgba16Sint,
1724 "rgba16unorm" => TextureFormat::Rgba16Unorm,
1725 "rgba16snorm" => TextureFormat::Rgba16Snorm,
1726 "rgba16float" => TextureFormat::Rgba16Float,
1727 "rgba32uint" => TextureFormat::Rgba32Uint,
1728 "rgba32sint" => TextureFormat::Rgba32Sint,
1729 "rgba32float" => TextureFormat::Rgba32Float,
1730 "stencil8" => TextureFormat::Stencil8,
1731 "depth32float" => TextureFormat::Depth32Float,
1732 "depth32float-stencil8" => TextureFormat::Depth32FloatStencil8,
1733 "depth16unorm" => TextureFormat::Depth16Unorm,
1734 "depth24plus" => TextureFormat::Depth24Plus,
1735 "depth24plus-stencil8" => TextureFormat::Depth24PlusStencil8,
1736 "nv12" => TextureFormat::NV12,
1737 "p010" => TextureFormat::P010,
1738 "rgb9e5ufloat" => TextureFormat::Rgb9e5Ufloat,
1739 "bc1-rgba-unorm" => TextureFormat::Bc1RgbaUnorm,
1740 "bc1-rgba-unorm-srgb" => TextureFormat::Bc1RgbaUnormSrgb,
1741 "bc2-rgba-unorm" => TextureFormat::Bc2RgbaUnorm,
1742 "bc2-rgba-unorm-srgb" => TextureFormat::Bc2RgbaUnormSrgb,
1743 "bc3-rgba-unorm" => TextureFormat::Bc3RgbaUnorm,
1744 "bc3-rgba-unorm-srgb" => TextureFormat::Bc3RgbaUnormSrgb,
1745 "bc4-r-unorm" => TextureFormat::Bc4RUnorm,
1746 "bc4-r-snorm" => TextureFormat::Bc4RSnorm,
1747 "bc5-rg-unorm" => TextureFormat::Bc5RgUnorm,
1748 "bc5-rg-snorm" => TextureFormat::Bc5RgSnorm,
1749 "bc6h-rgb-ufloat" => TextureFormat::Bc6hRgbUfloat,
1750 "bc6h-rgb-float" => TextureFormat::Bc6hRgbFloat,
1751 "bc7-rgba-unorm" => TextureFormat::Bc7RgbaUnorm,
1752 "bc7-rgba-unorm-srgb" => TextureFormat::Bc7RgbaUnormSrgb,
1753 "etc2-rgb8unorm" => TextureFormat::Etc2Rgb8Unorm,
1754 "etc2-rgb8unorm-srgb" => TextureFormat::Etc2Rgb8UnormSrgb,
1755 "etc2-rgb8a1unorm" => TextureFormat::Etc2Rgb8A1Unorm,
1756 "etc2-rgb8a1unorm-srgb" => TextureFormat::Etc2Rgb8A1UnormSrgb,
1757 "etc2-rgba8unorm" => TextureFormat::Etc2Rgba8Unorm,
1758 "etc2-rgba8unorm-srgb" => TextureFormat::Etc2Rgba8UnormSrgb,
1759 "eac-r11unorm" => TextureFormat::EacR11Unorm,
1760 "eac-r11snorm" => TextureFormat::EacR11Snorm,
1761 "eac-rg11unorm" => TextureFormat::EacRg11Unorm,
1762 "eac-rg11snorm" => TextureFormat::EacRg11Snorm,
1763 other => {
1764 if let Some(parts) = other.strip_prefix("astc-") {
1765 let (block, channel) = parts
1766 .split_once('-')
1767 .ok_or_else(|| E::invalid_value(Unexpected::Str(s), &self))?;
1768
1769 let block = match block {
1770 "4x4" => AstcBlock::B4x4,
1771 "5x4" => AstcBlock::B5x4,
1772 "5x5" => AstcBlock::B5x5,
1773 "6x5" => AstcBlock::B6x5,
1774 "6x6" => AstcBlock::B6x6,
1775 "8x5" => AstcBlock::B8x5,
1776 "8x6" => AstcBlock::B8x6,
1777 "8x8" => AstcBlock::B8x8,
1778 "10x5" => AstcBlock::B10x5,
1779 "10x6" => AstcBlock::B10x6,
1780 "10x8" => AstcBlock::B10x8,
1781 "10x10" => AstcBlock::B10x10,
1782 "12x10" => AstcBlock::B12x10,
1783 "12x12" => AstcBlock::B12x12,
1784 _ => return Err(E::invalid_value(Unexpected::Str(s), &self)),
1785 };
1786
1787 let channel = match channel {
1788 "unorm" => AstcChannel::Unorm,
1789 "unorm-srgb" => AstcChannel::UnormSrgb,
1790 "hdr" => AstcChannel::Hdr,
1791 _ => return Err(E::invalid_value(Unexpected::Str(s), &self)),
1792 };
1793
1794 TextureFormat::Astc { block, channel }
1795 } else {
1796 return Err(E::invalid_value(Unexpected::Str(s), &self));
1797 }
1798 }
1799 };
1800
1801 Ok(format)
1802 }
1803 }
1804
1805 deserializer.deserialize_str(TextureFormatVisitor)
1806 }
1807}
1808
1809#[cfg(any(feature = "serde", test))]
1810impl Serialize for TextureFormat {
1811 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1812 where
1813 S: serde::Serializer,
1814 {
1815 let s: alloc::string::String;
1816 let name = match *self {
1817 TextureFormat::R8Unorm => "r8unorm",
1818 TextureFormat::R8Snorm => "r8snorm",
1819 TextureFormat::R8Uint => "r8uint",
1820 TextureFormat::R8Sint => "r8sint",
1821 TextureFormat::R16Uint => "r16uint",
1822 TextureFormat::R16Sint => "r16sint",
1823 TextureFormat::R16Unorm => "r16unorm",
1824 TextureFormat::R16Snorm => "r16snorm",
1825 TextureFormat::R16Float => "r16float",
1826 TextureFormat::Rg8Unorm => "rg8unorm",
1827 TextureFormat::Rg8Snorm => "rg8snorm",
1828 TextureFormat::Rg8Uint => "rg8uint",
1829 TextureFormat::Rg8Sint => "rg8sint",
1830 TextureFormat::R32Uint => "r32uint",
1831 TextureFormat::R32Sint => "r32sint",
1832 TextureFormat::R32Float => "r32float",
1833 TextureFormat::Rg16Uint => "rg16uint",
1834 TextureFormat::Rg16Sint => "rg16sint",
1835 TextureFormat::Rg16Unorm => "rg16unorm",
1836 TextureFormat::Rg16Snorm => "rg16snorm",
1837 TextureFormat::Rg16Float => "rg16float",
1838 TextureFormat::Rgba8Unorm => "rgba8unorm",
1839 TextureFormat::Rgba8UnormSrgb => "rgba8unorm-srgb",
1840 TextureFormat::Rgba8Snorm => "rgba8snorm",
1841 TextureFormat::Rgba8Uint => "rgba8uint",
1842 TextureFormat::Rgba8Sint => "rgba8sint",
1843 TextureFormat::Bgra8Unorm => "bgra8unorm",
1844 TextureFormat::Bgra8UnormSrgb => "bgra8unorm-srgb",
1845 TextureFormat::Rgb10a2Uint => "rgb10a2uint",
1846 TextureFormat::Rgb10a2Unorm => "rgb10a2unorm",
1847 TextureFormat::Rg11b10Ufloat => "rg11b10ufloat",
1848 TextureFormat::R64Uint => "r64uint",
1849 TextureFormat::Rg32Uint => "rg32uint",
1850 TextureFormat::Rg32Sint => "rg32sint",
1851 TextureFormat::Rg32Float => "rg32float",
1852 TextureFormat::Rgba16Uint => "rgba16uint",
1853 TextureFormat::Rgba16Sint => "rgba16sint",
1854 TextureFormat::Rgba16Unorm => "rgba16unorm",
1855 TextureFormat::Rgba16Snorm => "rgba16snorm",
1856 TextureFormat::Rgba16Float => "rgba16float",
1857 TextureFormat::Rgba32Uint => "rgba32uint",
1858 TextureFormat::Rgba32Sint => "rgba32sint",
1859 TextureFormat::Rgba32Float => "rgba32float",
1860 TextureFormat::Stencil8 => "stencil8",
1861 TextureFormat::Depth32Float => "depth32float",
1862 TextureFormat::Depth16Unorm => "depth16unorm",
1863 TextureFormat::Depth32FloatStencil8 => "depth32float-stencil8",
1864 TextureFormat::Depth24Plus => "depth24plus",
1865 TextureFormat::Depth24PlusStencil8 => "depth24plus-stencil8",
1866 TextureFormat::NV12 => "nv12",
1867 TextureFormat::P010 => "p010",
1868 TextureFormat::Rgb9e5Ufloat => "rgb9e5ufloat",
1869 TextureFormat::Bc1RgbaUnorm => "bc1-rgba-unorm",
1870 TextureFormat::Bc1RgbaUnormSrgb => "bc1-rgba-unorm-srgb",
1871 TextureFormat::Bc2RgbaUnorm => "bc2-rgba-unorm",
1872 TextureFormat::Bc2RgbaUnormSrgb => "bc2-rgba-unorm-srgb",
1873 TextureFormat::Bc3RgbaUnorm => "bc3-rgba-unorm",
1874 TextureFormat::Bc3RgbaUnormSrgb => "bc3-rgba-unorm-srgb",
1875 TextureFormat::Bc4RUnorm => "bc4-r-unorm",
1876 TextureFormat::Bc4RSnorm => "bc4-r-snorm",
1877 TextureFormat::Bc5RgUnorm => "bc5-rg-unorm",
1878 TextureFormat::Bc5RgSnorm => "bc5-rg-snorm",
1879 TextureFormat::Bc6hRgbUfloat => "bc6h-rgb-ufloat",
1880 TextureFormat::Bc6hRgbFloat => "bc6h-rgb-float",
1881 TextureFormat::Bc7RgbaUnorm => "bc7-rgba-unorm",
1882 TextureFormat::Bc7RgbaUnormSrgb => "bc7-rgba-unorm-srgb",
1883 TextureFormat::Etc2Rgb8Unorm => "etc2-rgb8unorm",
1884 TextureFormat::Etc2Rgb8UnormSrgb => "etc2-rgb8unorm-srgb",
1885 TextureFormat::Etc2Rgb8A1Unorm => "etc2-rgb8a1unorm",
1886 TextureFormat::Etc2Rgb8A1UnormSrgb => "etc2-rgb8a1unorm-srgb",
1887 TextureFormat::Etc2Rgba8Unorm => "etc2-rgba8unorm",
1888 TextureFormat::Etc2Rgba8UnormSrgb => "etc2-rgba8unorm-srgb",
1889 TextureFormat::EacR11Unorm => "eac-r11unorm",
1890 TextureFormat::EacR11Snorm => "eac-r11snorm",
1891 TextureFormat::EacRg11Unorm => "eac-rg11unorm",
1892 TextureFormat::EacRg11Snorm => "eac-rg11snorm",
1893 TextureFormat::Astc { block, channel } => {
1894 let block = match block {
1895 AstcBlock::B4x4 => "4x4",
1896 AstcBlock::B5x4 => "5x4",
1897 AstcBlock::B5x5 => "5x5",
1898 AstcBlock::B6x5 => "6x5",
1899 AstcBlock::B6x6 => "6x6",
1900 AstcBlock::B8x5 => "8x5",
1901 AstcBlock::B8x6 => "8x6",
1902 AstcBlock::B8x8 => "8x8",
1903 AstcBlock::B10x5 => "10x5",
1904 AstcBlock::B10x6 => "10x6",
1905 AstcBlock::B10x8 => "10x8",
1906 AstcBlock::B10x10 => "10x10",
1907 AstcBlock::B12x10 => "12x10",
1908 AstcBlock::B12x12 => "12x12",
1909 };
1910
1911 let channel = match channel {
1912 AstcChannel::Unorm => "unorm",
1913 AstcChannel::UnormSrgb => "unorm-srgb",
1914 AstcChannel::Hdr => "hdr",
1915 };
1916
1917 s = alloc::format!("astc-{block}-{channel}");
1918 &s
1919 }
1920 };
1921 serializer.serialize_str(name)
1922 }
1923}
1924
1925bitflags::bitflags! {
1926 #[repr(transparent)]
1928 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1929 #[cfg_attr(feature = "serde", serde(transparent))]
1930 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1931 pub struct TextureFormatFeatureFlags: u32 {
1932 const FILTERABLE = 1 << 0;
1935 const MULTISAMPLE_X2 = 1 << 1;
1937 const MULTISAMPLE_X4 = 1 << 2 ;
1939 const MULTISAMPLE_X8 = 1 << 3 ;
1941 const MULTISAMPLE_X16 = 1 << 4;
1943 const MULTISAMPLE_RESOLVE = 1 << 5;
1946 const STORAGE_READ_ONLY = 1 << 6;
1949 const STORAGE_WRITE_ONLY = 1 << 7;
1952 const STORAGE_READ_WRITE = 1 << 8;
1955 const STORAGE_ATOMIC = 1 << 9;
1958 const BLENDABLE = 1 << 10;
1960 }
1961}
1962
1963impl TextureFormatFeatureFlags {
1964 #[must_use]
1968 pub fn sample_count_supported(&self, count: u32) -> bool {
1969 use TextureFormatFeatureFlags as tfsc;
1970
1971 match count {
1972 1 => true,
1973 2 => self.contains(tfsc::MULTISAMPLE_X2),
1974 4 => self.contains(tfsc::MULTISAMPLE_X4),
1975 8 => self.contains(tfsc::MULTISAMPLE_X8),
1976 16 => self.contains(tfsc::MULTISAMPLE_X16),
1977 _ => false,
1978 }
1979 }
1980
1981 #[must_use]
1983 pub fn supported_sample_counts(&self) -> Vec<u32> {
1984 let all_possible_sample_counts: [u32; 5] = [1, 2, 4, 8, 16];
1985 all_possible_sample_counts
1986 .into_iter()
1987 .filter(|&sc| self.sample_count_supported(sc))
1988 .collect()
1989 }
1990}
1991
1992#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
1996#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1997pub struct TextureFormatFeatures {
1998 pub allowed_usages: TextureUsages,
2000 pub flags: TextureFormatFeatureFlags,
2002}
2003
2004#[cfg(test)]
2005mod tests {
2006 use super::*;
2007 use exhaust::Exhaust;
2008 use hashbrown::HashSet;
2009
2010 #[test]
2011 fn texture_format_serialize() {
2012 use alloc::string::ToString;
2013
2014 assert_eq!(
2015 serde_json::to_string(&TextureFormat::R8Unorm).unwrap(),
2016 "\"r8unorm\"".to_string()
2017 );
2018 assert_eq!(
2019 serde_json::to_string(&TextureFormat::R8Snorm).unwrap(),
2020 "\"r8snorm\"".to_string()
2021 );
2022 assert_eq!(
2023 serde_json::to_string(&TextureFormat::R8Uint).unwrap(),
2024 "\"r8uint\"".to_string()
2025 );
2026 assert_eq!(
2027 serde_json::to_string(&TextureFormat::R8Sint).unwrap(),
2028 "\"r8sint\"".to_string()
2029 );
2030 assert_eq!(
2031 serde_json::to_string(&TextureFormat::R16Uint).unwrap(),
2032 "\"r16uint\"".to_string()
2033 );
2034 assert_eq!(
2035 serde_json::to_string(&TextureFormat::R16Sint).unwrap(),
2036 "\"r16sint\"".to_string()
2037 );
2038 assert_eq!(
2039 serde_json::to_string(&TextureFormat::R16Unorm).unwrap(),
2040 "\"r16unorm\"".to_string()
2041 );
2042 assert_eq!(
2043 serde_json::to_string(&TextureFormat::R16Snorm).unwrap(),
2044 "\"r16snorm\"".to_string()
2045 );
2046 assert_eq!(
2047 serde_json::to_string(&TextureFormat::R16Float).unwrap(),
2048 "\"r16float\"".to_string()
2049 );
2050 assert_eq!(
2051 serde_json::to_string(&TextureFormat::Rg8Unorm).unwrap(),
2052 "\"rg8unorm\"".to_string()
2053 );
2054 assert_eq!(
2055 serde_json::to_string(&TextureFormat::Rg8Snorm).unwrap(),
2056 "\"rg8snorm\"".to_string()
2057 );
2058 assert_eq!(
2059 serde_json::to_string(&TextureFormat::Rg8Uint).unwrap(),
2060 "\"rg8uint\"".to_string()
2061 );
2062 assert_eq!(
2063 serde_json::to_string(&TextureFormat::Rg8Sint).unwrap(),
2064 "\"rg8sint\"".to_string()
2065 );
2066 assert_eq!(
2067 serde_json::to_string(&TextureFormat::R32Uint).unwrap(),
2068 "\"r32uint\"".to_string()
2069 );
2070 assert_eq!(
2071 serde_json::to_string(&TextureFormat::R32Sint).unwrap(),
2072 "\"r32sint\"".to_string()
2073 );
2074 assert_eq!(
2075 serde_json::to_string(&TextureFormat::R32Float).unwrap(),
2076 "\"r32float\"".to_string()
2077 );
2078 assert_eq!(
2079 serde_json::to_string(&TextureFormat::Rg16Uint).unwrap(),
2080 "\"rg16uint\"".to_string()
2081 );
2082 assert_eq!(
2083 serde_json::to_string(&TextureFormat::Rg16Sint).unwrap(),
2084 "\"rg16sint\"".to_string()
2085 );
2086 assert_eq!(
2087 serde_json::to_string(&TextureFormat::Rg16Unorm).unwrap(),
2088 "\"rg16unorm\"".to_string()
2089 );
2090 assert_eq!(
2091 serde_json::to_string(&TextureFormat::Rg16Snorm).unwrap(),
2092 "\"rg16snorm\"".to_string()
2093 );
2094 assert_eq!(
2095 serde_json::to_string(&TextureFormat::Rg16Float).unwrap(),
2096 "\"rg16float\"".to_string()
2097 );
2098 assert_eq!(
2099 serde_json::to_string(&TextureFormat::Rgba8Unorm).unwrap(),
2100 "\"rgba8unorm\"".to_string()
2101 );
2102 assert_eq!(
2103 serde_json::to_string(&TextureFormat::Rgba8UnormSrgb).unwrap(),
2104 "\"rgba8unorm-srgb\"".to_string()
2105 );
2106 assert_eq!(
2107 serde_json::to_string(&TextureFormat::Rgba8Snorm).unwrap(),
2108 "\"rgba8snorm\"".to_string()
2109 );
2110 assert_eq!(
2111 serde_json::to_string(&TextureFormat::Rgba8Uint).unwrap(),
2112 "\"rgba8uint\"".to_string()
2113 );
2114 assert_eq!(
2115 serde_json::to_string(&TextureFormat::Rgba8Sint).unwrap(),
2116 "\"rgba8sint\"".to_string()
2117 );
2118 assert_eq!(
2119 serde_json::to_string(&TextureFormat::Bgra8Unorm).unwrap(),
2120 "\"bgra8unorm\"".to_string()
2121 );
2122 assert_eq!(
2123 serde_json::to_string(&TextureFormat::Bgra8UnormSrgb).unwrap(),
2124 "\"bgra8unorm-srgb\"".to_string()
2125 );
2126 assert_eq!(
2127 serde_json::to_string(&TextureFormat::Rgb10a2Uint).unwrap(),
2128 "\"rgb10a2uint\"".to_string()
2129 );
2130 assert_eq!(
2131 serde_json::to_string(&TextureFormat::Rgb10a2Unorm).unwrap(),
2132 "\"rgb10a2unorm\"".to_string()
2133 );
2134 assert_eq!(
2135 serde_json::to_string(&TextureFormat::Rg11b10Ufloat).unwrap(),
2136 "\"rg11b10ufloat\"".to_string()
2137 );
2138 assert_eq!(
2139 serde_json::to_string(&TextureFormat::R64Uint).unwrap(),
2140 "\"r64uint\"".to_string()
2141 );
2142 assert_eq!(
2143 serde_json::to_string(&TextureFormat::Rg32Uint).unwrap(),
2144 "\"rg32uint\"".to_string()
2145 );
2146 assert_eq!(
2147 serde_json::to_string(&TextureFormat::Rg32Sint).unwrap(),
2148 "\"rg32sint\"".to_string()
2149 );
2150 assert_eq!(
2151 serde_json::to_string(&TextureFormat::Rg32Float).unwrap(),
2152 "\"rg32float\"".to_string()
2153 );
2154 assert_eq!(
2155 serde_json::to_string(&TextureFormat::Rgba16Uint).unwrap(),
2156 "\"rgba16uint\"".to_string()
2157 );
2158 assert_eq!(
2159 serde_json::to_string(&TextureFormat::Rgba16Sint).unwrap(),
2160 "\"rgba16sint\"".to_string()
2161 );
2162 assert_eq!(
2163 serde_json::to_string(&TextureFormat::Rgba16Unorm).unwrap(),
2164 "\"rgba16unorm\"".to_string()
2165 );
2166 assert_eq!(
2167 serde_json::to_string(&TextureFormat::Rgba16Snorm).unwrap(),
2168 "\"rgba16snorm\"".to_string()
2169 );
2170 assert_eq!(
2171 serde_json::to_string(&TextureFormat::Rgba16Float).unwrap(),
2172 "\"rgba16float\"".to_string()
2173 );
2174 assert_eq!(
2175 serde_json::to_string(&TextureFormat::Rgba32Uint).unwrap(),
2176 "\"rgba32uint\"".to_string()
2177 );
2178 assert_eq!(
2179 serde_json::to_string(&TextureFormat::Rgba32Sint).unwrap(),
2180 "\"rgba32sint\"".to_string()
2181 );
2182 assert_eq!(
2183 serde_json::to_string(&TextureFormat::Rgba32Float).unwrap(),
2184 "\"rgba32float\"".to_string()
2185 );
2186 assert_eq!(
2187 serde_json::to_string(&TextureFormat::Stencil8).unwrap(),
2188 "\"stencil8\"".to_string()
2189 );
2190 assert_eq!(
2191 serde_json::to_string(&TextureFormat::Depth32Float).unwrap(),
2192 "\"depth32float\"".to_string()
2193 );
2194 assert_eq!(
2195 serde_json::to_string(&TextureFormat::Depth16Unorm).unwrap(),
2196 "\"depth16unorm\"".to_string()
2197 );
2198 assert_eq!(
2199 serde_json::to_string(&TextureFormat::Depth32FloatStencil8).unwrap(),
2200 "\"depth32float-stencil8\"".to_string()
2201 );
2202 assert_eq!(
2203 serde_json::to_string(&TextureFormat::Depth24Plus).unwrap(),
2204 "\"depth24plus\"".to_string()
2205 );
2206 assert_eq!(
2207 serde_json::to_string(&TextureFormat::Depth24PlusStencil8).unwrap(),
2208 "\"depth24plus-stencil8\"".to_string()
2209 );
2210 assert_eq!(
2211 serde_json::to_string(&TextureFormat::Rgb9e5Ufloat).unwrap(),
2212 "\"rgb9e5ufloat\"".to_string()
2213 );
2214 assert_eq!(
2215 serde_json::to_string(&TextureFormat::Bc1RgbaUnorm).unwrap(),
2216 "\"bc1-rgba-unorm\"".to_string()
2217 );
2218 assert_eq!(
2219 serde_json::to_string(&TextureFormat::Bc1RgbaUnormSrgb).unwrap(),
2220 "\"bc1-rgba-unorm-srgb\"".to_string()
2221 );
2222 assert_eq!(
2223 serde_json::to_string(&TextureFormat::Bc2RgbaUnorm).unwrap(),
2224 "\"bc2-rgba-unorm\"".to_string()
2225 );
2226 assert_eq!(
2227 serde_json::to_string(&TextureFormat::Bc2RgbaUnormSrgb).unwrap(),
2228 "\"bc2-rgba-unorm-srgb\"".to_string()
2229 );
2230 assert_eq!(
2231 serde_json::to_string(&TextureFormat::Bc3RgbaUnorm).unwrap(),
2232 "\"bc3-rgba-unorm\"".to_string()
2233 );
2234 assert_eq!(
2235 serde_json::to_string(&TextureFormat::Bc3RgbaUnormSrgb).unwrap(),
2236 "\"bc3-rgba-unorm-srgb\"".to_string()
2237 );
2238 assert_eq!(
2239 serde_json::to_string(&TextureFormat::Bc4RUnorm).unwrap(),
2240 "\"bc4-r-unorm\"".to_string()
2241 );
2242 assert_eq!(
2243 serde_json::to_string(&TextureFormat::Bc4RSnorm).unwrap(),
2244 "\"bc4-r-snorm\"".to_string()
2245 );
2246 assert_eq!(
2247 serde_json::to_string(&TextureFormat::Bc5RgUnorm).unwrap(),
2248 "\"bc5-rg-unorm\"".to_string()
2249 );
2250 assert_eq!(
2251 serde_json::to_string(&TextureFormat::Bc5RgSnorm).unwrap(),
2252 "\"bc5-rg-snorm\"".to_string()
2253 );
2254 assert_eq!(
2255 serde_json::to_string(&TextureFormat::Bc6hRgbUfloat).unwrap(),
2256 "\"bc6h-rgb-ufloat\"".to_string()
2257 );
2258 assert_eq!(
2259 serde_json::to_string(&TextureFormat::Bc6hRgbFloat).unwrap(),
2260 "\"bc6h-rgb-float\"".to_string()
2261 );
2262 assert_eq!(
2263 serde_json::to_string(&TextureFormat::Bc7RgbaUnorm).unwrap(),
2264 "\"bc7-rgba-unorm\"".to_string()
2265 );
2266 assert_eq!(
2267 serde_json::to_string(&TextureFormat::Bc7RgbaUnormSrgb).unwrap(),
2268 "\"bc7-rgba-unorm-srgb\"".to_string()
2269 );
2270 assert_eq!(
2271 serde_json::to_string(&TextureFormat::Etc2Rgb8Unorm).unwrap(),
2272 "\"etc2-rgb8unorm\"".to_string()
2273 );
2274 assert_eq!(
2275 serde_json::to_string(&TextureFormat::Etc2Rgb8UnormSrgb).unwrap(),
2276 "\"etc2-rgb8unorm-srgb\"".to_string()
2277 );
2278 assert_eq!(
2279 serde_json::to_string(&TextureFormat::Etc2Rgb8A1Unorm).unwrap(),
2280 "\"etc2-rgb8a1unorm\"".to_string()
2281 );
2282 assert_eq!(
2283 serde_json::to_string(&TextureFormat::Etc2Rgb8A1UnormSrgb).unwrap(),
2284 "\"etc2-rgb8a1unorm-srgb\"".to_string()
2285 );
2286 assert_eq!(
2287 serde_json::to_string(&TextureFormat::Etc2Rgba8Unorm).unwrap(),
2288 "\"etc2-rgba8unorm\"".to_string()
2289 );
2290 assert_eq!(
2291 serde_json::to_string(&TextureFormat::Etc2Rgba8UnormSrgb).unwrap(),
2292 "\"etc2-rgba8unorm-srgb\"".to_string()
2293 );
2294 assert_eq!(
2295 serde_json::to_string(&TextureFormat::EacR11Unorm).unwrap(),
2296 "\"eac-r11unorm\"".to_string()
2297 );
2298 assert_eq!(
2299 serde_json::to_string(&TextureFormat::EacR11Snorm).unwrap(),
2300 "\"eac-r11snorm\"".to_string()
2301 );
2302 assert_eq!(
2303 serde_json::to_string(&TextureFormat::EacRg11Unorm).unwrap(),
2304 "\"eac-rg11unorm\"".to_string()
2305 );
2306 assert_eq!(
2307 serde_json::to_string(&TextureFormat::EacRg11Snorm).unwrap(),
2308 "\"eac-rg11snorm\"".to_string()
2309 );
2310 }
2311
2312 #[test]
2313 fn texture_format_deserialize() {
2314 assert_eq!(
2315 serde_json::from_str::<TextureFormat>("\"r8unorm\"").unwrap(),
2316 TextureFormat::R8Unorm
2317 );
2318 assert_eq!(
2319 serde_json::from_str::<TextureFormat>("\"r8snorm\"").unwrap(),
2320 TextureFormat::R8Snorm
2321 );
2322 assert_eq!(
2323 serde_json::from_str::<TextureFormat>("\"r8uint\"").unwrap(),
2324 TextureFormat::R8Uint
2325 );
2326 assert_eq!(
2327 serde_json::from_str::<TextureFormat>("\"r8sint\"").unwrap(),
2328 TextureFormat::R8Sint
2329 );
2330 assert_eq!(
2331 serde_json::from_str::<TextureFormat>("\"r16uint\"").unwrap(),
2332 TextureFormat::R16Uint
2333 );
2334 assert_eq!(
2335 serde_json::from_str::<TextureFormat>("\"r16sint\"").unwrap(),
2336 TextureFormat::R16Sint
2337 );
2338 assert_eq!(
2339 serde_json::from_str::<TextureFormat>("\"r16unorm\"").unwrap(),
2340 TextureFormat::R16Unorm
2341 );
2342 assert_eq!(
2343 serde_json::from_str::<TextureFormat>("\"r16snorm\"").unwrap(),
2344 TextureFormat::R16Snorm
2345 );
2346 assert_eq!(
2347 serde_json::from_str::<TextureFormat>("\"r16float\"").unwrap(),
2348 TextureFormat::R16Float
2349 );
2350 assert_eq!(
2351 serde_json::from_str::<TextureFormat>("\"rg8unorm\"").unwrap(),
2352 TextureFormat::Rg8Unorm
2353 );
2354 assert_eq!(
2355 serde_json::from_str::<TextureFormat>("\"rg8snorm\"").unwrap(),
2356 TextureFormat::Rg8Snorm
2357 );
2358 assert_eq!(
2359 serde_json::from_str::<TextureFormat>("\"rg8uint\"").unwrap(),
2360 TextureFormat::Rg8Uint
2361 );
2362 assert_eq!(
2363 serde_json::from_str::<TextureFormat>("\"rg8sint\"").unwrap(),
2364 TextureFormat::Rg8Sint
2365 );
2366 assert_eq!(
2367 serde_json::from_str::<TextureFormat>("\"r32uint\"").unwrap(),
2368 TextureFormat::R32Uint
2369 );
2370 assert_eq!(
2371 serde_json::from_str::<TextureFormat>("\"r32sint\"").unwrap(),
2372 TextureFormat::R32Sint
2373 );
2374 assert_eq!(
2375 serde_json::from_str::<TextureFormat>("\"r32float\"").unwrap(),
2376 TextureFormat::R32Float
2377 );
2378 assert_eq!(
2379 serde_json::from_str::<TextureFormat>("\"rg16uint\"").unwrap(),
2380 TextureFormat::Rg16Uint
2381 );
2382 assert_eq!(
2383 serde_json::from_str::<TextureFormat>("\"rg16sint\"").unwrap(),
2384 TextureFormat::Rg16Sint
2385 );
2386 assert_eq!(
2387 serde_json::from_str::<TextureFormat>("\"rg16unorm\"").unwrap(),
2388 TextureFormat::Rg16Unorm
2389 );
2390 assert_eq!(
2391 serde_json::from_str::<TextureFormat>("\"rg16snorm\"").unwrap(),
2392 TextureFormat::Rg16Snorm
2393 );
2394 assert_eq!(
2395 serde_json::from_str::<TextureFormat>("\"rg16float\"").unwrap(),
2396 TextureFormat::Rg16Float
2397 );
2398 assert_eq!(
2399 serde_json::from_str::<TextureFormat>("\"rgba8unorm\"").unwrap(),
2400 TextureFormat::Rgba8Unorm
2401 );
2402 assert_eq!(
2403 serde_json::from_str::<TextureFormat>("\"rgba8unorm-srgb\"").unwrap(),
2404 TextureFormat::Rgba8UnormSrgb
2405 );
2406 assert_eq!(
2407 serde_json::from_str::<TextureFormat>("\"rgba8snorm\"").unwrap(),
2408 TextureFormat::Rgba8Snorm
2409 );
2410 assert_eq!(
2411 serde_json::from_str::<TextureFormat>("\"rgba8uint\"").unwrap(),
2412 TextureFormat::Rgba8Uint
2413 );
2414 assert_eq!(
2415 serde_json::from_str::<TextureFormat>("\"rgba8sint\"").unwrap(),
2416 TextureFormat::Rgba8Sint
2417 );
2418 assert_eq!(
2419 serde_json::from_str::<TextureFormat>("\"bgra8unorm\"").unwrap(),
2420 TextureFormat::Bgra8Unorm
2421 );
2422 assert_eq!(
2423 serde_json::from_str::<TextureFormat>("\"bgra8unorm-srgb\"").unwrap(),
2424 TextureFormat::Bgra8UnormSrgb
2425 );
2426 assert_eq!(
2427 serde_json::from_str::<TextureFormat>("\"rgb10a2uint\"").unwrap(),
2428 TextureFormat::Rgb10a2Uint
2429 );
2430 assert_eq!(
2431 serde_json::from_str::<TextureFormat>("\"rgb10a2unorm\"").unwrap(),
2432 TextureFormat::Rgb10a2Unorm
2433 );
2434 assert_eq!(
2435 serde_json::from_str::<TextureFormat>("\"rg11b10ufloat\"").unwrap(),
2436 TextureFormat::Rg11b10Ufloat
2437 );
2438 assert_eq!(
2439 serde_json::from_str::<TextureFormat>("\"r64uint\"").unwrap(),
2440 TextureFormat::R64Uint
2441 );
2442 assert_eq!(
2443 serde_json::from_str::<TextureFormat>("\"rg32uint\"").unwrap(),
2444 TextureFormat::Rg32Uint
2445 );
2446 assert_eq!(
2447 serde_json::from_str::<TextureFormat>("\"rg32sint\"").unwrap(),
2448 TextureFormat::Rg32Sint
2449 );
2450 assert_eq!(
2451 serde_json::from_str::<TextureFormat>("\"rg32float\"").unwrap(),
2452 TextureFormat::Rg32Float
2453 );
2454 assert_eq!(
2455 serde_json::from_str::<TextureFormat>("\"rgba16uint\"").unwrap(),
2456 TextureFormat::Rgba16Uint
2457 );
2458 assert_eq!(
2459 serde_json::from_str::<TextureFormat>("\"rgba16sint\"").unwrap(),
2460 TextureFormat::Rgba16Sint
2461 );
2462 assert_eq!(
2463 serde_json::from_str::<TextureFormat>("\"rgba16unorm\"").unwrap(),
2464 TextureFormat::Rgba16Unorm
2465 );
2466 assert_eq!(
2467 serde_json::from_str::<TextureFormat>("\"rgba16snorm\"").unwrap(),
2468 TextureFormat::Rgba16Snorm
2469 );
2470 assert_eq!(
2471 serde_json::from_str::<TextureFormat>("\"rgba16float\"").unwrap(),
2472 TextureFormat::Rgba16Float
2473 );
2474 assert_eq!(
2475 serde_json::from_str::<TextureFormat>("\"rgba32uint\"").unwrap(),
2476 TextureFormat::Rgba32Uint
2477 );
2478 assert_eq!(
2479 serde_json::from_str::<TextureFormat>("\"rgba32sint\"").unwrap(),
2480 TextureFormat::Rgba32Sint
2481 );
2482 assert_eq!(
2483 serde_json::from_str::<TextureFormat>("\"rgba32float\"").unwrap(),
2484 TextureFormat::Rgba32Float
2485 );
2486 assert_eq!(
2487 serde_json::from_str::<TextureFormat>("\"stencil8\"").unwrap(),
2488 TextureFormat::Stencil8
2489 );
2490 assert_eq!(
2491 serde_json::from_str::<TextureFormat>("\"depth32float\"").unwrap(),
2492 TextureFormat::Depth32Float
2493 );
2494 assert_eq!(
2495 serde_json::from_str::<TextureFormat>("\"depth16unorm\"").unwrap(),
2496 TextureFormat::Depth16Unorm
2497 );
2498 assert_eq!(
2499 serde_json::from_str::<TextureFormat>("\"depth32float-stencil8\"").unwrap(),
2500 TextureFormat::Depth32FloatStencil8
2501 );
2502 assert_eq!(
2503 serde_json::from_str::<TextureFormat>("\"depth24plus\"").unwrap(),
2504 TextureFormat::Depth24Plus
2505 );
2506 assert_eq!(
2507 serde_json::from_str::<TextureFormat>("\"depth24plus-stencil8\"").unwrap(),
2508 TextureFormat::Depth24PlusStencil8
2509 );
2510 assert_eq!(
2511 serde_json::from_str::<TextureFormat>("\"rgb9e5ufloat\"").unwrap(),
2512 TextureFormat::Rgb9e5Ufloat
2513 );
2514 assert_eq!(
2515 serde_json::from_str::<TextureFormat>("\"bc1-rgba-unorm\"").unwrap(),
2516 TextureFormat::Bc1RgbaUnorm
2517 );
2518 assert_eq!(
2519 serde_json::from_str::<TextureFormat>("\"bc1-rgba-unorm-srgb\"").unwrap(),
2520 TextureFormat::Bc1RgbaUnormSrgb
2521 );
2522 assert_eq!(
2523 serde_json::from_str::<TextureFormat>("\"bc2-rgba-unorm\"").unwrap(),
2524 TextureFormat::Bc2RgbaUnorm
2525 );
2526 assert_eq!(
2527 serde_json::from_str::<TextureFormat>("\"bc2-rgba-unorm-srgb\"").unwrap(),
2528 TextureFormat::Bc2RgbaUnormSrgb
2529 );
2530 assert_eq!(
2531 serde_json::from_str::<TextureFormat>("\"bc3-rgba-unorm\"").unwrap(),
2532 TextureFormat::Bc3RgbaUnorm
2533 );
2534 assert_eq!(
2535 serde_json::from_str::<TextureFormat>("\"bc3-rgba-unorm-srgb\"").unwrap(),
2536 TextureFormat::Bc3RgbaUnormSrgb
2537 );
2538 assert_eq!(
2539 serde_json::from_str::<TextureFormat>("\"bc4-r-unorm\"").unwrap(),
2540 TextureFormat::Bc4RUnorm
2541 );
2542 assert_eq!(
2543 serde_json::from_str::<TextureFormat>("\"bc4-r-snorm\"").unwrap(),
2544 TextureFormat::Bc4RSnorm
2545 );
2546 assert_eq!(
2547 serde_json::from_str::<TextureFormat>("\"bc5-rg-unorm\"").unwrap(),
2548 TextureFormat::Bc5RgUnorm
2549 );
2550 assert_eq!(
2551 serde_json::from_str::<TextureFormat>("\"bc5-rg-snorm\"").unwrap(),
2552 TextureFormat::Bc5RgSnorm
2553 );
2554 assert_eq!(
2555 serde_json::from_str::<TextureFormat>("\"bc6h-rgb-ufloat\"").unwrap(),
2556 TextureFormat::Bc6hRgbUfloat
2557 );
2558 assert_eq!(
2559 serde_json::from_str::<TextureFormat>("\"bc6h-rgb-float\"").unwrap(),
2560 TextureFormat::Bc6hRgbFloat
2561 );
2562 assert_eq!(
2563 serde_json::from_str::<TextureFormat>("\"bc7-rgba-unorm\"").unwrap(),
2564 TextureFormat::Bc7RgbaUnorm
2565 );
2566 assert_eq!(
2567 serde_json::from_str::<TextureFormat>("\"bc7-rgba-unorm-srgb\"").unwrap(),
2568 TextureFormat::Bc7RgbaUnormSrgb
2569 );
2570 assert_eq!(
2571 serde_json::from_str::<TextureFormat>("\"etc2-rgb8unorm\"").unwrap(),
2572 TextureFormat::Etc2Rgb8Unorm
2573 );
2574 assert_eq!(
2575 serde_json::from_str::<TextureFormat>("\"etc2-rgb8unorm-srgb\"").unwrap(),
2576 TextureFormat::Etc2Rgb8UnormSrgb
2577 );
2578 assert_eq!(
2579 serde_json::from_str::<TextureFormat>("\"etc2-rgb8a1unorm\"").unwrap(),
2580 TextureFormat::Etc2Rgb8A1Unorm
2581 );
2582 assert_eq!(
2583 serde_json::from_str::<TextureFormat>("\"etc2-rgb8a1unorm-srgb\"").unwrap(),
2584 TextureFormat::Etc2Rgb8A1UnormSrgb
2585 );
2586 assert_eq!(
2587 serde_json::from_str::<TextureFormat>("\"etc2-rgba8unorm\"").unwrap(),
2588 TextureFormat::Etc2Rgba8Unorm
2589 );
2590 assert_eq!(
2591 serde_json::from_str::<TextureFormat>("\"etc2-rgba8unorm-srgb\"").unwrap(),
2592 TextureFormat::Etc2Rgba8UnormSrgb
2593 );
2594 assert_eq!(
2595 serde_json::from_str::<TextureFormat>("\"eac-r11unorm\"").unwrap(),
2596 TextureFormat::EacR11Unorm
2597 );
2598 assert_eq!(
2599 serde_json::from_str::<TextureFormat>("\"eac-r11snorm\"").unwrap(),
2600 TextureFormat::EacR11Snorm
2601 );
2602 assert_eq!(
2603 serde_json::from_str::<TextureFormat>("\"eac-rg11unorm\"").unwrap(),
2604 TextureFormat::EacRg11Unorm
2605 );
2606 assert_eq!(
2607 serde_json::from_str::<TextureFormat>("\"eac-rg11snorm\"").unwrap(),
2608 TextureFormat::EacRg11Snorm
2609 );
2610 }
2611
2612 #[test]
2614 fn is_depth_stencil_format() {
2615 let depth_stencil_formats: HashSet<TextureFormat> = HashSet::from([
2617 TextureFormat::Stencil8,
2618 TextureFormat::Depth16Unorm,
2619 TextureFormat::Depth24Plus,
2620 TextureFormat::Depth24PlusStencil8,
2621 TextureFormat::Depth32Float,
2622 TextureFormat::Depth32FloatStencil8,
2623 ]);
2624
2625 for format in TextureFormat::exhaust() {
2626 if depth_stencil_formats.contains(&format) {
2627 assert!(format.is_depth_stencil_format());
2628 } else {
2629 assert!(!format.is_depth_stencil_format());
2630 }
2631 }
2632 }
2633
2634 #[test]
2636 fn is_combined_depth_stencil_format() {
2637 let valid_formats = [
2639 TextureFormat::Depth24PlusStencil8,
2640 TextureFormat::Depth32FloatStencil8,
2641 ];
2642
2643 for format in TextureFormat::exhaust() {
2644 if valid_formats.contains(&format) {
2645 assert!(format.is_combined_depth_stencil_format());
2646 } else {
2647 assert!(!format.is_combined_depth_stencil_format());
2648 }
2649 }
2650 }
2651
2652 #[test]
2654 fn has_color_aspect() {
2655 let valid_formats: HashSet<TextureFormat> = HashSet::from([
2657 TextureFormat::R8Unorm,
2658 TextureFormat::R8Snorm,
2659 TextureFormat::R8Uint,
2660 TextureFormat::R8Sint,
2661 TextureFormat::R16Uint,
2662 TextureFormat::R16Sint,
2663 TextureFormat::R16Unorm,
2664 TextureFormat::R16Snorm,
2665 TextureFormat::R16Float,
2666 TextureFormat::Rg8Unorm,
2667 TextureFormat::Rg8Snorm,
2668 TextureFormat::Rg8Uint,
2669 TextureFormat::Rg8Sint,
2670 TextureFormat::R32Uint,
2671 TextureFormat::R32Sint,
2672 TextureFormat::R32Float,
2673 TextureFormat::Rg16Uint,
2674 TextureFormat::Rg16Sint,
2675 TextureFormat::Rg16Unorm,
2676 TextureFormat::Rg16Snorm,
2677 TextureFormat::Rg16Float,
2678 TextureFormat::Rgba8Unorm,
2679 TextureFormat::Rgba8UnormSrgb,
2680 TextureFormat::Rgba8Snorm,
2681 TextureFormat::Rgba8Uint,
2682 TextureFormat::Rgba8Sint,
2683 TextureFormat::Bgra8Unorm,
2684 TextureFormat::Bgra8UnormSrgb,
2685 TextureFormat::Rgb9e5Ufloat,
2686 TextureFormat::Rgb10a2Uint,
2687 TextureFormat::Rgb10a2Unorm,
2688 TextureFormat::Rg11b10Ufloat,
2689 TextureFormat::R64Uint,
2690 TextureFormat::Rg32Uint,
2691 TextureFormat::Rg32Sint,
2692 TextureFormat::Rg32Float,
2693 TextureFormat::Rgba16Uint,
2694 TextureFormat::Rgba16Sint,
2695 TextureFormat::Rgba16Unorm,
2696 TextureFormat::Rgba16Snorm,
2697 TextureFormat::Rgba16Float,
2698 TextureFormat::Rgba32Uint,
2699 TextureFormat::Rgba32Sint,
2700 TextureFormat::Rgba32Float,
2701 TextureFormat::Bc1RgbaUnorm,
2702 TextureFormat::Bc1RgbaUnormSrgb,
2703 TextureFormat::Bc2RgbaUnorm,
2704 TextureFormat::Bc2RgbaUnormSrgb,
2705 TextureFormat::Bc3RgbaUnorm,
2706 TextureFormat::Bc3RgbaUnormSrgb,
2707 TextureFormat::Bc4RUnorm,
2708 TextureFormat::Bc4RSnorm,
2709 TextureFormat::Bc5RgUnorm,
2710 TextureFormat::Bc5RgSnorm,
2711 TextureFormat::Bc6hRgbUfloat,
2712 TextureFormat::Bc6hRgbFloat,
2713 TextureFormat::Bc7RgbaUnorm,
2714 TextureFormat::Bc7RgbaUnormSrgb,
2715 TextureFormat::Etc2Rgb8Unorm,
2716 TextureFormat::Etc2Rgb8UnormSrgb,
2717 TextureFormat::Etc2Rgb8A1Unorm,
2718 TextureFormat::Etc2Rgb8A1UnormSrgb,
2719 TextureFormat::Etc2Rgba8Unorm,
2720 TextureFormat::Etc2Rgba8UnormSrgb,
2721 TextureFormat::EacR11Unorm,
2722 TextureFormat::EacR11Snorm,
2723 TextureFormat::EacRg11Unorm,
2724 TextureFormat::EacRg11Snorm,
2725 ]);
2726
2727 for format in TextureFormat::exhaust() {
2728 if let TextureFormat::Astc { .. } = format {
2729 assert!(format.has_color_aspect(), "{:?} failed", format);
2731 } else if valid_formats.contains(&format) {
2732 assert!(format.has_color_aspect(), "{:?} failed", format);
2733 } else {
2734 assert!(!format.has_color_aspect(), "{:?} failed", format);
2735 }
2736 }
2737 }
2738
2739 #[test]
2741 fn has_depth_aspect() {
2742 let valid_formats: HashSet<TextureFormat> = HashSet::from([
2744 TextureFormat::Depth16Unorm,
2745 TextureFormat::Depth24Plus,
2746 TextureFormat::Depth24PlusStencil8,
2747 TextureFormat::Depth32Float,
2748 TextureFormat::Depth32FloatStencil8,
2749 ]);
2750
2751 for format in TextureFormat::exhaust() {
2752 if valid_formats.contains(&format) {
2753 assert!(format.has_depth_aspect());
2754 } else {
2755 assert!(!format.has_depth_aspect());
2756 }
2757 }
2758 }
2759
2760 #[test]
2762 fn has_stencil_aspect() {
2763 let valid_formats: HashSet<TextureFormat> = HashSet::from([
2765 TextureFormat::Stencil8,
2766 TextureFormat::Depth24PlusStencil8,
2767 TextureFormat::Depth32FloatStencil8,
2768 ]);
2769
2770 for format in TextureFormat::exhaust() {
2771 if valid_formats.contains(&format) {
2772 assert!(format.has_stencil_aspect());
2773 } else {
2774 assert!(!format.has_stencil_aspect());
2775 }
2776 }
2777 }
2778}