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 = basic | TextureUsages::RENDER_ATTACHMENT | TextureUsages::TRANSIENT;
928 let storage = basic | TextureUsages::STORAGE_BINDING;
929 let binding = TextureUsages::TEXTURE_BINDING;
930 let all_flags = attachment | storage | binding;
931 let atomic_64 = if device_features.contains(Features::TEXTURE_ATOMIC) {
932 storage | binding | TextureUsages::STORAGE_ATOMIC
933 } else {
934 storage | binding
935 };
936 let atomic = attachment | atomic_64;
937 let (rg11b10f_f, rg11b10f_u) =
938 if device_features.contains(Features::RG11B10UFLOAT_RENDERABLE) {
939 (msaa_resolve, attachment)
940 } else {
941 (msaa, basic)
942 };
943 let (bgra8unorm_f, bgra8unorm) = if device_features.contains(Features::BGRA8UNORM_STORAGE) {
944 (
945 msaa_resolve | TextureFormatFeatureFlags::STORAGE_WRITE_ONLY,
946 attachment | TextureUsages::STORAGE_BINDING,
947 )
948 } else {
949 (msaa_resolve, attachment)
950 };
951
952 #[rustfmt::skip] let (
954 mut flags,
955 allowed_usages,
956 ) = match *self {
957 Self::R8Unorm => (msaa_resolve, attachment),
958 Self::R8Snorm => ( none, basic),
959 Self::R8Uint => ( msaa, attachment),
960 Self::R8Sint => ( msaa, attachment),
961 Self::R16Uint => ( msaa, attachment),
962 Self::R16Sint => ( msaa, attachment),
963 Self::R16Float => (msaa_resolve, attachment),
964 Self::Rg8Unorm => (msaa_resolve, attachment),
965 Self::Rg8Snorm => ( none, basic),
966 Self::Rg8Uint => ( msaa, attachment),
967 Self::Rg8Sint => ( msaa, attachment),
968 Self::R32Uint => ( s_all, atomic),
969 Self::R32Sint => ( s_all, atomic),
970 Self::R32Float => (msaa | s_all, all_flags),
971 Self::Rg16Uint => ( msaa, attachment),
972 Self::Rg16Sint => ( msaa, attachment),
973 Self::Rg16Float => (msaa_resolve, attachment),
974 Self::Rgba8Unorm => (msaa_resolve | s_ro_wo, all_flags),
975 Self::Rgba8UnormSrgb => (msaa_resolve, attachment),
976 Self::Rgba8Snorm => ( s_ro_wo, storage),
977 Self::Rgba8Uint => ( msaa | s_ro_wo, all_flags),
978 Self::Rgba8Sint => ( msaa | s_ro_wo, all_flags),
979 Self::Bgra8Unorm => (bgra8unorm_f, bgra8unorm),
980 Self::Bgra8UnormSrgb => (msaa_resolve, attachment),
981 Self::Rgb10a2Uint => ( msaa, attachment),
982 Self::Rgb10a2Unorm => (msaa_resolve, attachment),
983 Self::Rg11b10Ufloat => ( rg11b10f_f, rg11b10f_u),
984 Self::R64Uint => ( s_ro_wo, atomic_64),
985 Self::Rg32Uint => ( s_ro_wo, all_flags),
986 Self::Rg32Sint => ( s_ro_wo, all_flags),
987 Self::Rg32Float => ( s_ro_wo, all_flags),
988 Self::Rgba16Uint => ( msaa | s_ro_wo, all_flags),
989 Self::Rgba16Sint => ( msaa | s_ro_wo, all_flags),
990 Self::Rgba16Float => (msaa_resolve | s_ro_wo, all_flags),
991 Self::Rgba32Uint => ( s_ro_wo, all_flags),
992 Self::Rgba32Sint => ( s_ro_wo, all_flags),
993 Self::Rgba32Float => ( s_ro_wo, all_flags),
994
995 Self::Stencil8 => ( msaa, attachment),
996 Self::Depth16Unorm => ( msaa, attachment),
997 Self::Depth24Plus => ( msaa, attachment),
998 Self::Depth24PlusStencil8 => ( msaa, attachment),
999 Self::Depth32Float => ( msaa, attachment),
1000 Self::Depth32FloatStencil8 => ( msaa, attachment),
1001
1002 Self::NV12 => ( none, binding),
1005 Self::P010 => ( none, binding),
1006
1007 Self::R16Unorm => ( msaa | s_ro_wo, storage),
1008 Self::R16Snorm => ( msaa | s_ro_wo, storage),
1009 Self::Rg16Unorm => ( msaa | s_ro_wo, storage),
1010 Self::Rg16Snorm => ( msaa | s_ro_wo, storage),
1011 Self::Rgba16Unorm => ( msaa | s_ro_wo, storage),
1012 Self::Rgba16Snorm => ( msaa | s_ro_wo, storage),
1013
1014 Self::Rgb9e5Ufloat => ( none, basic),
1015
1016 Self::Bc1RgbaUnorm => ( none, basic),
1017 Self::Bc1RgbaUnormSrgb => ( none, basic),
1018 Self::Bc2RgbaUnorm => ( none, basic),
1019 Self::Bc2RgbaUnormSrgb => ( none, basic),
1020 Self::Bc3RgbaUnorm => ( none, basic),
1021 Self::Bc3RgbaUnormSrgb => ( none, basic),
1022 Self::Bc4RUnorm => ( none, basic),
1023 Self::Bc4RSnorm => ( none, basic),
1024 Self::Bc5RgUnorm => ( none, basic),
1025 Self::Bc5RgSnorm => ( none, basic),
1026 Self::Bc6hRgbUfloat => ( none, basic),
1027 Self::Bc6hRgbFloat => ( none, basic),
1028 Self::Bc7RgbaUnorm => ( none, basic),
1029 Self::Bc7RgbaUnormSrgb => ( none, basic),
1030
1031 Self::Etc2Rgb8Unorm => ( none, basic),
1032 Self::Etc2Rgb8UnormSrgb => ( none, basic),
1033 Self::Etc2Rgb8A1Unorm => ( none, basic),
1034 Self::Etc2Rgb8A1UnormSrgb => ( none, basic),
1035 Self::Etc2Rgba8Unorm => ( none, basic),
1036 Self::Etc2Rgba8UnormSrgb => ( none, basic),
1037 Self::EacR11Unorm => ( none, basic),
1038 Self::EacR11Snorm => ( none, basic),
1039 Self::EacRg11Unorm => ( none, basic),
1040 Self::EacRg11Snorm => ( none, basic),
1041
1042 Self::Astc { .. } => ( none, basic),
1043 };
1044
1045 let sample_type1 = self.sample_type(None, Some(device_features));
1047 let is_filterable = sample_type1 == Some(TextureSampleType::Float { filterable: true });
1048
1049 let sample_type2 = self.sample_type(None, None);
1051 let is_blendable = sample_type2 == Some(TextureSampleType::Float { filterable: true })
1052 || device_features.contains(Features::FLOAT32_BLENDABLE)
1053 && matches!(self, Self::R32Float | Self::Rg32Float | Self::Rgba32Float);
1054
1055 flags.set(TextureFormatFeatureFlags::FILTERABLE, is_filterable);
1056 flags.set(TextureFormatFeatureFlags::BLENDABLE, is_blendable);
1057 flags.set(
1058 TextureFormatFeatureFlags::STORAGE_ATOMIC,
1059 allowed_usages.contains(TextureUsages::STORAGE_ATOMIC),
1060 );
1061
1062 TextureFormatFeatures {
1063 allowed_usages,
1064 flags,
1065 }
1066 }
1067
1068 #[must_use]
1073 pub fn sample_type(
1074 &self,
1075 aspect: Option<TextureAspect>,
1076 device_features: Option<Features>,
1077 ) -> Option<TextureSampleType> {
1078 let float = TextureSampleType::Float { filterable: true };
1079 let unfilterable_float = TextureSampleType::Float { filterable: false };
1080 let float32_sample_type = TextureSampleType::Float {
1081 filterable: device_features
1082 .unwrap_or(Features::empty())
1083 .contains(Features::FLOAT32_FILTERABLE),
1084 };
1085 let depth = TextureSampleType::Depth;
1086 let uint = TextureSampleType::Uint;
1087 let sint = TextureSampleType::Sint;
1088
1089 match *self {
1090 Self::R8Unorm
1091 | Self::R8Snorm
1092 | Self::Rg8Unorm
1093 | Self::Rg8Snorm
1094 | Self::Rgba8Unorm
1095 | Self::Rgba8UnormSrgb
1096 | Self::Rgba8Snorm
1097 | Self::Bgra8Unorm
1098 | Self::Bgra8UnormSrgb
1099 | Self::R16Float
1100 | Self::Rg16Float
1101 | Self::Rgba16Float
1102 | Self::Rgb10a2Unorm
1103 | Self::Rg11b10Ufloat => Some(float),
1104
1105 Self::R32Float | Self::Rg32Float | Self::Rgba32Float => Some(float32_sample_type),
1106
1107 Self::R8Uint
1108 | Self::Rg8Uint
1109 | Self::Rgba8Uint
1110 | Self::R16Uint
1111 | Self::Rg16Uint
1112 | Self::Rgba16Uint
1113 | Self::R32Uint
1114 | Self::R64Uint
1115 | Self::Rg32Uint
1116 | Self::Rgba32Uint
1117 | Self::Rgb10a2Uint => Some(uint),
1118
1119 Self::R8Sint
1120 | Self::Rg8Sint
1121 | Self::Rgba8Sint
1122 | Self::R16Sint
1123 | Self::Rg16Sint
1124 | Self::Rgba16Sint
1125 | Self::R32Sint
1126 | Self::Rg32Sint
1127 | Self::Rgba32Sint => Some(sint),
1128
1129 Self::Stencil8 => Some(uint),
1130 Self::Depth16Unorm | Self::Depth24Plus | Self::Depth32Float => Some(depth),
1131 Self::Depth24PlusStencil8 | Self::Depth32FloatStencil8 => match aspect {
1132 Some(TextureAspect::DepthOnly) => Some(depth),
1133 Some(TextureAspect::StencilOnly) => Some(uint),
1134 _ => None,
1135 },
1136
1137 Self::NV12 | Self::P010 => match aspect {
1138 Some(TextureAspect::Plane0) | Some(TextureAspect::Plane1) => {
1139 Some(unfilterable_float)
1140 }
1141 _ => None,
1142 },
1143
1144 Self::R16Unorm
1145 | Self::R16Snorm
1146 | Self::Rg16Unorm
1147 | Self::Rg16Snorm
1148 | Self::Rgba16Unorm
1149 | Self::Rgba16Snorm => Some(float),
1150
1151 Self::Rgb9e5Ufloat => Some(float),
1152
1153 Self::Bc1RgbaUnorm
1154 | Self::Bc1RgbaUnormSrgb
1155 | Self::Bc2RgbaUnorm
1156 | Self::Bc2RgbaUnormSrgb
1157 | Self::Bc3RgbaUnorm
1158 | Self::Bc3RgbaUnormSrgb
1159 | Self::Bc4RUnorm
1160 | Self::Bc4RSnorm
1161 | Self::Bc5RgUnorm
1162 | Self::Bc5RgSnorm
1163 | Self::Bc6hRgbUfloat
1164 | Self::Bc6hRgbFloat
1165 | Self::Bc7RgbaUnorm
1166 | Self::Bc7RgbaUnormSrgb => Some(float),
1167
1168 Self::Etc2Rgb8Unorm
1169 | Self::Etc2Rgb8UnormSrgb
1170 | Self::Etc2Rgb8A1Unorm
1171 | Self::Etc2Rgb8A1UnormSrgb
1172 | Self::Etc2Rgba8Unorm
1173 | Self::Etc2Rgba8UnormSrgb
1174 | Self::EacR11Unorm
1175 | Self::EacR11Snorm
1176 | Self::EacRg11Unorm
1177 | Self::EacRg11Snorm => Some(float),
1178
1179 Self::Astc { .. } => Some(float),
1180 }
1181 }
1182
1183 #[deprecated(since = "0.19.0", note = "Use `block_copy_size` instead.")]
1196 #[must_use]
1197 pub fn block_size(&self, aspect: Option<TextureAspect>) -> Option<u32> {
1198 self.block_copy_size(aspect)
1199 }
1200
1201 #[must_use]
1214 pub fn block_copy_size(&self, aspect: Option<TextureAspect>) -> Option<u32> {
1215 match *self {
1216 Self::R8Unorm | Self::R8Snorm | Self::R8Uint | Self::R8Sint => Some(1),
1217
1218 Self::Rg8Unorm | Self::Rg8Snorm | Self::Rg8Uint | Self::Rg8Sint => Some(2),
1219 Self::R16Unorm | Self::R16Snorm | Self::R16Uint | Self::R16Sint | Self::R16Float => {
1220 Some(2)
1221 }
1222
1223 Self::Rgba8Unorm
1224 | Self::Rgba8UnormSrgb
1225 | Self::Rgba8Snorm
1226 | Self::Rgba8Uint
1227 | Self::Rgba8Sint
1228 | Self::Bgra8Unorm
1229 | Self::Bgra8UnormSrgb => Some(4),
1230 Self::Rg16Unorm
1231 | Self::Rg16Snorm
1232 | Self::Rg16Uint
1233 | Self::Rg16Sint
1234 | Self::Rg16Float => Some(4),
1235 Self::R32Uint | Self::R32Sint | Self::R32Float => Some(4),
1236 Self::Rgb9e5Ufloat | Self::Rgb10a2Uint | Self::Rgb10a2Unorm | Self::Rg11b10Ufloat => {
1237 Some(4)
1238 }
1239
1240 Self::Rgba16Unorm
1241 | Self::Rgba16Snorm
1242 | Self::Rgba16Uint
1243 | Self::Rgba16Sint
1244 | Self::Rgba16Float => Some(8),
1245 Self::R64Uint | Self::Rg32Uint | Self::Rg32Sint | Self::Rg32Float => Some(8),
1246
1247 Self::Rgba32Uint | Self::Rgba32Sint | Self::Rgba32Float => Some(16),
1248
1249 Self::Stencil8 => Some(1),
1250 Self::Depth16Unorm => Some(2),
1251 Self::Depth32Float => Some(4),
1252 Self::Depth24Plus => None,
1253 Self::Depth24PlusStencil8 => match aspect {
1254 Some(TextureAspect::DepthOnly) => None,
1255 Some(TextureAspect::StencilOnly) => Some(1),
1256 _ => None,
1257 },
1258 Self::Depth32FloatStencil8 => match aspect {
1259 Some(TextureAspect::DepthOnly) => Some(4),
1260 Some(TextureAspect::StencilOnly) => Some(1),
1261 _ => None,
1262 },
1263
1264 Self::NV12 => match aspect {
1265 Some(TextureAspect::Plane0) => Some(1),
1266 Some(TextureAspect::Plane1) => Some(2),
1267 _ => None,
1268 },
1269
1270 Self::P010 => match aspect {
1271 Some(TextureAspect::Plane0) => Some(2),
1272 Some(TextureAspect::Plane1) => Some(4),
1273 _ => None,
1274 },
1275
1276 Self::Bc1RgbaUnorm | Self::Bc1RgbaUnormSrgb | Self::Bc4RUnorm | Self::Bc4RSnorm => {
1277 Some(8)
1278 }
1279 Self::Bc2RgbaUnorm
1280 | Self::Bc2RgbaUnormSrgb
1281 | Self::Bc3RgbaUnorm
1282 | Self::Bc3RgbaUnormSrgb
1283 | Self::Bc5RgUnorm
1284 | Self::Bc5RgSnorm
1285 | Self::Bc6hRgbUfloat
1286 | Self::Bc6hRgbFloat
1287 | Self::Bc7RgbaUnorm
1288 | Self::Bc7RgbaUnormSrgb => Some(16),
1289
1290 Self::Etc2Rgb8Unorm
1291 | Self::Etc2Rgb8UnormSrgb
1292 | Self::Etc2Rgb8A1Unorm
1293 | Self::Etc2Rgb8A1UnormSrgb
1294 | Self::EacR11Unorm
1295 | Self::EacR11Snorm => Some(8),
1296 Self::Etc2Rgba8Unorm
1297 | Self::Etc2Rgba8UnormSrgb
1298 | Self::EacRg11Unorm
1299 | Self::EacRg11Snorm => Some(16),
1300
1301 Self::Astc { .. } => Some(16),
1302 }
1303 }
1304
1305 pub const MAX_TARGET_PIXEL_BYTE_COST: u32 = 16;
1307
1308 #[must_use]
1311 pub fn target_pixel_byte_cost(&self) -> Option<u32> {
1312 match *self {
1313 Self::R8Unorm | Self::R8Snorm | Self::R8Uint | Self::R8Sint => Some(1),
1314 Self::Rg8Unorm
1315 | Self::Rg8Snorm
1316 | Self::Rg8Uint
1317 | Self::Rg8Sint
1318 | Self::R16Uint
1319 | Self::R16Sint
1320 | Self::R16Unorm
1321 | Self::R16Snorm
1322 | Self::R16Float => Some(2),
1323 Self::Rgba8Uint
1324 | Self::Rgba8Sint
1325 | Self::Rg16Uint
1326 | Self::Rg16Sint
1327 | Self::Rg16Unorm
1328 | Self::Rg16Snorm
1329 | Self::Rg16Float
1330 | Self::R32Uint
1331 | Self::R32Sint
1332 | Self::R32Float => Some(4),
1333 Self::Rgba8Unorm
1335 | Self::Rgba8UnormSrgb
1336 | Self::Rgba8Snorm
1337 | Self::Bgra8Unorm
1338 | Self::Bgra8UnormSrgb
1339 | Self::Rgba16Uint
1341 | Self::Rgba16Sint
1342 | Self::Rgba16Unorm
1343 | Self::Rgba16Snorm
1344 | Self::Rgba16Float
1345 | Self::R64Uint
1346 | Self::Rg32Uint
1347 | Self::Rg32Sint
1348 | Self::Rg32Float
1349 | Self::Rgb10a2Uint
1350 | Self::Rgb10a2Unorm
1351 | Self::Rg11b10Ufloat => Some(8),
1352 Self::Rgba32Uint | Self::Rgba32Sint | Self::Rgba32Float => Some(16),
1353 Self::Stencil8
1355 | Self::Depth16Unorm
1356 | Self::Depth24Plus
1357 | Self::Depth24PlusStencil8
1358 | Self::Depth32Float
1359 | Self::Depth32FloatStencil8
1360 | Self::NV12
1361 | Self::P010
1362 | Self::Rgb9e5Ufloat
1363 | Self::Bc1RgbaUnorm
1364 | Self::Bc1RgbaUnormSrgb
1365 | Self::Bc2RgbaUnorm
1366 | Self::Bc2RgbaUnormSrgb
1367 | Self::Bc3RgbaUnorm
1368 | Self::Bc3RgbaUnormSrgb
1369 | Self::Bc4RUnorm
1370 | Self::Bc4RSnorm
1371 | Self::Bc5RgUnorm
1372 | Self::Bc5RgSnorm
1373 | Self::Bc6hRgbUfloat
1374 | Self::Bc6hRgbFloat
1375 | Self::Bc7RgbaUnorm
1376 | Self::Bc7RgbaUnormSrgb
1377 | Self::Etc2Rgb8Unorm
1378 | Self::Etc2Rgb8UnormSrgb
1379 | Self::Etc2Rgb8A1Unorm
1380 | Self::Etc2Rgb8A1UnormSrgb
1381 | Self::Etc2Rgba8Unorm
1382 | Self::Etc2Rgba8UnormSrgb
1383 | Self::EacR11Unorm
1384 | Self::EacR11Snorm
1385 | Self::EacRg11Unorm
1386 | Self::EacRg11Snorm
1387 | Self::Astc { .. } => None,
1388 }
1389 }
1390
1391 #[must_use]
1393 pub fn target_component_alignment(&self) -> Option<u32> {
1394 match *self {
1395 Self::R8Unorm
1396 | Self::R8Snorm
1397 | Self::R8Uint
1398 | Self::R8Sint
1399 | Self::Rg8Unorm
1400 | Self::Rg8Snorm
1401 | Self::Rg8Uint
1402 | Self::Rg8Sint
1403 | Self::Rgba8Unorm
1404 | Self::Rgba8UnormSrgb
1405 | Self::Rgba8Snorm
1406 | Self::Rgba8Uint
1407 | Self::Rgba8Sint
1408 | Self::Bgra8Unorm
1409 | Self::Bgra8UnormSrgb => Some(1),
1410 Self::R16Uint
1411 | Self::R16Sint
1412 | Self::R16Unorm
1413 | Self::R16Snorm
1414 | Self::R16Float
1415 | Self::Rg16Uint
1416 | Self::Rg16Sint
1417 | Self::Rg16Unorm
1418 | Self::Rg16Snorm
1419 | Self::Rg16Float
1420 | Self::Rgba16Uint
1421 | Self::Rgba16Sint
1422 | Self::Rgba16Unorm
1423 | Self::Rgba16Snorm
1424 | Self::Rgba16Float => Some(2),
1425 Self::R32Uint
1426 | Self::R32Sint
1427 | Self::R32Float
1428 | Self::R64Uint
1429 | Self::Rg32Uint
1430 | Self::Rg32Sint
1431 | Self::Rg32Float
1432 | Self::Rgba32Uint
1433 | Self::Rgba32Sint
1434 | Self::Rgba32Float
1435 | Self::Rgb10a2Uint
1436 | Self::Rgb10a2Unorm
1437 | Self::Rg11b10Ufloat => Some(4),
1438 Self::Stencil8
1439 | Self::Depth16Unorm
1440 | Self::Depth24Plus
1441 | Self::Depth24PlusStencil8
1442 | Self::Depth32Float
1443 | Self::Depth32FloatStencil8
1444 | Self::NV12
1445 | Self::P010
1446 | Self::Rgb9e5Ufloat
1447 | Self::Bc1RgbaUnorm
1448 | Self::Bc1RgbaUnormSrgb
1449 | Self::Bc2RgbaUnorm
1450 | Self::Bc2RgbaUnormSrgb
1451 | Self::Bc3RgbaUnorm
1452 | Self::Bc3RgbaUnormSrgb
1453 | Self::Bc4RUnorm
1454 | Self::Bc4RSnorm
1455 | Self::Bc5RgUnorm
1456 | Self::Bc5RgSnorm
1457 | Self::Bc6hRgbUfloat
1458 | Self::Bc6hRgbFloat
1459 | Self::Bc7RgbaUnorm
1460 | Self::Bc7RgbaUnormSrgb
1461 | Self::Etc2Rgb8Unorm
1462 | Self::Etc2Rgb8UnormSrgb
1463 | Self::Etc2Rgb8A1Unorm
1464 | Self::Etc2Rgb8A1UnormSrgb
1465 | Self::Etc2Rgba8Unorm
1466 | Self::Etc2Rgba8UnormSrgb
1467 | Self::EacR11Unorm
1468 | Self::EacR11Snorm
1469 | Self::EacRg11Unorm
1470 | Self::EacRg11Snorm
1471 | Self::Astc { .. } => None,
1472 }
1473 }
1474
1475 #[must_use]
1477 pub fn components(&self) -> u8 {
1478 self.components_with_aspect(TextureAspect::All)
1479 }
1480
1481 #[must_use]
1485 pub fn components_with_aspect(&self, aspect: TextureAspect) -> u8 {
1486 match *self {
1487 Self::R8Unorm
1488 | Self::R8Snorm
1489 | Self::R8Uint
1490 | Self::R8Sint
1491 | Self::R16Unorm
1492 | Self::R16Snorm
1493 | Self::R16Uint
1494 | Self::R16Sint
1495 | Self::R16Float
1496 | Self::R32Uint
1497 | Self::R32Sint
1498 | Self::R32Float
1499 | Self::R64Uint => 1,
1500
1501 Self::Rg8Unorm
1502 | Self::Rg8Snorm
1503 | Self::Rg8Uint
1504 | Self::Rg8Sint
1505 | Self::Rg16Unorm
1506 | Self::Rg16Snorm
1507 | Self::Rg16Uint
1508 | Self::Rg16Sint
1509 | Self::Rg16Float
1510 | Self::Rg32Uint
1511 | Self::Rg32Sint
1512 | Self::Rg32Float => 2,
1513
1514 Self::Rgba8Unorm
1515 | Self::Rgba8UnormSrgb
1516 | Self::Rgba8Snorm
1517 | Self::Rgba8Uint
1518 | Self::Rgba8Sint
1519 | Self::Bgra8Unorm
1520 | Self::Bgra8UnormSrgb
1521 | Self::Rgba16Unorm
1522 | Self::Rgba16Snorm
1523 | Self::Rgba16Uint
1524 | Self::Rgba16Sint
1525 | Self::Rgba16Float
1526 | Self::Rgba32Uint
1527 | Self::Rgba32Sint
1528 | Self::Rgba32Float => 4,
1529
1530 Self::Rgb9e5Ufloat | Self::Rg11b10Ufloat => 3,
1531 Self::Rgb10a2Uint | Self::Rgb10a2Unorm => 4,
1532
1533 Self::Stencil8 | Self::Depth16Unorm | Self::Depth24Plus | Self::Depth32Float => 1,
1534
1535 Self::Depth24PlusStencil8 | Self::Depth32FloatStencil8 => match aspect {
1536 TextureAspect::DepthOnly | TextureAspect::StencilOnly => 1,
1537 _ => 2,
1538 },
1539
1540 Self::NV12 | Self::P010 => match aspect {
1541 TextureAspect::Plane0 => 1,
1542 TextureAspect::Plane1 => 2,
1543 _ => 3,
1544 },
1545
1546 Self::Bc4RUnorm | Self::Bc4RSnorm => 1,
1547 Self::Bc5RgUnorm | Self::Bc5RgSnorm => 2,
1548 Self::Bc6hRgbUfloat | Self::Bc6hRgbFloat => 3,
1549 Self::Bc1RgbaUnorm
1550 | Self::Bc1RgbaUnormSrgb
1551 | Self::Bc2RgbaUnorm
1552 | Self::Bc2RgbaUnormSrgb
1553 | Self::Bc3RgbaUnorm
1554 | Self::Bc3RgbaUnormSrgb
1555 | Self::Bc7RgbaUnorm
1556 | Self::Bc7RgbaUnormSrgb => 4,
1557
1558 Self::EacR11Unorm | Self::EacR11Snorm => 1,
1559 Self::EacRg11Unorm | Self::EacRg11Snorm => 2,
1560 Self::Etc2Rgb8Unorm | Self::Etc2Rgb8UnormSrgb => 3,
1561 Self::Etc2Rgb8A1Unorm
1562 | Self::Etc2Rgb8A1UnormSrgb
1563 | Self::Etc2Rgba8Unorm
1564 | Self::Etc2Rgba8UnormSrgb => 4,
1565
1566 Self::Astc { .. } => 4,
1567 }
1568 }
1569
1570 #[must_use]
1572 pub fn remove_srgb_suffix(&self) -> TextureFormat {
1573 match *self {
1574 Self::Rgba8UnormSrgb => Self::Rgba8Unorm,
1575 Self::Bgra8UnormSrgb => Self::Bgra8Unorm,
1576 Self::Bc1RgbaUnormSrgb => Self::Bc1RgbaUnorm,
1577 Self::Bc2RgbaUnormSrgb => Self::Bc2RgbaUnorm,
1578 Self::Bc3RgbaUnormSrgb => Self::Bc3RgbaUnorm,
1579 Self::Bc7RgbaUnormSrgb => Self::Bc7RgbaUnorm,
1580 Self::Etc2Rgb8UnormSrgb => Self::Etc2Rgb8Unorm,
1581 Self::Etc2Rgb8A1UnormSrgb => Self::Etc2Rgb8A1Unorm,
1582 Self::Etc2Rgba8UnormSrgb => Self::Etc2Rgba8Unorm,
1583 Self::Astc {
1584 block,
1585 channel: AstcChannel::UnormSrgb,
1586 } => Self::Astc {
1587 block,
1588 channel: AstcChannel::Unorm,
1589 },
1590 _ => *self,
1591 }
1592 }
1593
1594 #[must_use]
1596 pub fn add_srgb_suffix(&self) -> TextureFormat {
1597 match *self {
1598 Self::Rgba8Unorm => Self::Rgba8UnormSrgb,
1599 Self::Bgra8Unorm => Self::Bgra8UnormSrgb,
1600 Self::Bc1RgbaUnorm => Self::Bc1RgbaUnormSrgb,
1601 Self::Bc2RgbaUnorm => Self::Bc2RgbaUnormSrgb,
1602 Self::Bc3RgbaUnorm => Self::Bc3RgbaUnormSrgb,
1603 Self::Bc7RgbaUnorm => Self::Bc7RgbaUnormSrgb,
1604 Self::Etc2Rgb8Unorm => Self::Etc2Rgb8UnormSrgb,
1605 Self::Etc2Rgb8A1Unorm => Self::Etc2Rgb8A1UnormSrgb,
1606 Self::Etc2Rgba8Unorm => Self::Etc2Rgba8UnormSrgb,
1607 Self::Astc {
1608 block,
1609 channel: AstcChannel::Unorm,
1610 } => Self::Astc {
1611 block,
1612 channel: AstcChannel::UnormSrgb,
1613 },
1614 _ => *self,
1615 }
1616 }
1617
1618 #[must_use]
1620 pub fn is_srgb(&self) -> bool {
1621 *self != self.remove_srgb_suffix()
1622 }
1623
1624 #[must_use]
1628 pub fn theoretical_memory_footprint(&self, size: crate::Extent3d) -> u64 {
1629 let (block_width, block_height) = self.block_dimensions();
1630
1631 let block_size = self.block_copy_size(None);
1632
1633 let approximate_block_size = match block_size {
1634 Some(size) => size,
1635 None => match self {
1636 Self::Depth16Unorm => 2,
1638 Self::Depth24Plus => 4,
1640 Self::Depth24PlusStencil8 => 4,
1642 Self::Depth32Float => 4,
1644 Self::Depth32FloatStencil8 => 8,
1646 Self::Stencil8 => 1,
1648 Self::NV12 => 3,
1650 Self::P010 => 6,
1652 f => {
1653 unimplemented!("Memory footprint for format {f:?} is not implemented");
1654 }
1655 },
1656 };
1657
1658 let width_blocks = size.width.div_ceil(block_width) as u64;
1659 let height_blocks = size.height.div_ceil(block_height) as u64;
1660
1661 let total_blocks = width_blocks * height_blocks * size.depth_or_array_layers as u64;
1662
1663 total_blocks * approximate_block_size as u64
1664 }
1665}
1666
1667#[cfg(any(feature = "serde", test))]
1668impl<'de> Deserialize<'de> for TextureFormat {
1669 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1670 where
1671 D: serde::Deserializer<'de>,
1672 {
1673 use serde::de::{self, Error, Unexpected};
1674
1675 struct TextureFormatVisitor;
1676
1677 impl de::Visitor<'_> for TextureFormatVisitor {
1678 type Value = TextureFormat;
1679
1680 fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
1681 formatter.write_str("a valid texture format")
1682 }
1683
1684 fn visit_str<E: Error>(self, s: &str) -> Result<Self::Value, E> {
1685 let format = match s {
1686 "r8unorm" => TextureFormat::R8Unorm,
1687 "r8snorm" => TextureFormat::R8Snorm,
1688 "r8uint" => TextureFormat::R8Uint,
1689 "r8sint" => TextureFormat::R8Sint,
1690 "r16uint" => TextureFormat::R16Uint,
1691 "r16sint" => TextureFormat::R16Sint,
1692 "r16unorm" => TextureFormat::R16Unorm,
1693 "r16snorm" => TextureFormat::R16Snorm,
1694 "r16float" => TextureFormat::R16Float,
1695 "rg8unorm" => TextureFormat::Rg8Unorm,
1696 "rg8snorm" => TextureFormat::Rg8Snorm,
1697 "rg8uint" => TextureFormat::Rg8Uint,
1698 "rg8sint" => TextureFormat::Rg8Sint,
1699 "r32uint" => TextureFormat::R32Uint,
1700 "r32sint" => TextureFormat::R32Sint,
1701 "r32float" => TextureFormat::R32Float,
1702 "rg16uint" => TextureFormat::Rg16Uint,
1703 "rg16sint" => TextureFormat::Rg16Sint,
1704 "rg16unorm" => TextureFormat::Rg16Unorm,
1705 "rg16snorm" => TextureFormat::Rg16Snorm,
1706 "rg16float" => TextureFormat::Rg16Float,
1707 "rgba8unorm" => TextureFormat::Rgba8Unorm,
1708 "rgba8unorm-srgb" => TextureFormat::Rgba8UnormSrgb,
1709 "rgba8snorm" => TextureFormat::Rgba8Snorm,
1710 "rgba8uint" => TextureFormat::Rgba8Uint,
1711 "rgba8sint" => TextureFormat::Rgba8Sint,
1712 "bgra8unorm" => TextureFormat::Bgra8Unorm,
1713 "bgra8unorm-srgb" => TextureFormat::Bgra8UnormSrgb,
1714 "rgb10a2uint" => TextureFormat::Rgb10a2Uint,
1715 "rgb10a2unorm" => TextureFormat::Rgb10a2Unorm,
1716 "rg11b10ufloat" => TextureFormat::Rg11b10Ufloat,
1717 "r64uint" => TextureFormat::R64Uint,
1718 "rg32uint" => TextureFormat::Rg32Uint,
1719 "rg32sint" => TextureFormat::Rg32Sint,
1720 "rg32float" => TextureFormat::Rg32Float,
1721 "rgba16uint" => TextureFormat::Rgba16Uint,
1722 "rgba16sint" => TextureFormat::Rgba16Sint,
1723 "rgba16unorm" => TextureFormat::Rgba16Unorm,
1724 "rgba16snorm" => TextureFormat::Rgba16Snorm,
1725 "rgba16float" => TextureFormat::Rgba16Float,
1726 "rgba32uint" => TextureFormat::Rgba32Uint,
1727 "rgba32sint" => TextureFormat::Rgba32Sint,
1728 "rgba32float" => TextureFormat::Rgba32Float,
1729 "stencil8" => TextureFormat::Stencil8,
1730 "depth32float" => TextureFormat::Depth32Float,
1731 "depth32float-stencil8" => TextureFormat::Depth32FloatStencil8,
1732 "depth16unorm" => TextureFormat::Depth16Unorm,
1733 "depth24plus" => TextureFormat::Depth24Plus,
1734 "depth24plus-stencil8" => TextureFormat::Depth24PlusStencil8,
1735 "nv12" => TextureFormat::NV12,
1736 "p010" => TextureFormat::P010,
1737 "rgb9e5ufloat" => TextureFormat::Rgb9e5Ufloat,
1738 "bc1-rgba-unorm" => TextureFormat::Bc1RgbaUnorm,
1739 "bc1-rgba-unorm-srgb" => TextureFormat::Bc1RgbaUnormSrgb,
1740 "bc2-rgba-unorm" => TextureFormat::Bc2RgbaUnorm,
1741 "bc2-rgba-unorm-srgb" => TextureFormat::Bc2RgbaUnormSrgb,
1742 "bc3-rgba-unorm" => TextureFormat::Bc3RgbaUnorm,
1743 "bc3-rgba-unorm-srgb" => TextureFormat::Bc3RgbaUnormSrgb,
1744 "bc4-r-unorm" => TextureFormat::Bc4RUnorm,
1745 "bc4-r-snorm" => TextureFormat::Bc4RSnorm,
1746 "bc5-rg-unorm" => TextureFormat::Bc5RgUnorm,
1747 "bc5-rg-snorm" => TextureFormat::Bc5RgSnorm,
1748 "bc6h-rgb-ufloat" => TextureFormat::Bc6hRgbUfloat,
1749 "bc6h-rgb-float" => TextureFormat::Bc6hRgbFloat,
1750 "bc7-rgba-unorm" => TextureFormat::Bc7RgbaUnorm,
1751 "bc7-rgba-unorm-srgb" => TextureFormat::Bc7RgbaUnormSrgb,
1752 "etc2-rgb8unorm" => TextureFormat::Etc2Rgb8Unorm,
1753 "etc2-rgb8unorm-srgb" => TextureFormat::Etc2Rgb8UnormSrgb,
1754 "etc2-rgb8a1unorm" => TextureFormat::Etc2Rgb8A1Unorm,
1755 "etc2-rgb8a1unorm-srgb" => TextureFormat::Etc2Rgb8A1UnormSrgb,
1756 "etc2-rgba8unorm" => TextureFormat::Etc2Rgba8Unorm,
1757 "etc2-rgba8unorm-srgb" => TextureFormat::Etc2Rgba8UnormSrgb,
1758 "eac-r11unorm" => TextureFormat::EacR11Unorm,
1759 "eac-r11snorm" => TextureFormat::EacR11Snorm,
1760 "eac-rg11unorm" => TextureFormat::EacRg11Unorm,
1761 "eac-rg11snorm" => TextureFormat::EacRg11Snorm,
1762 other => {
1763 if let Some(parts) = other.strip_prefix("astc-") {
1764 let (block, channel) = parts
1765 .split_once('-')
1766 .ok_or_else(|| E::invalid_value(Unexpected::Str(s), &self))?;
1767
1768 let block = match block {
1769 "4x4" => AstcBlock::B4x4,
1770 "5x4" => AstcBlock::B5x4,
1771 "5x5" => AstcBlock::B5x5,
1772 "6x5" => AstcBlock::B6x5,
1773 "6x6" => AstcBlock::B6x6,
1774 "8x5" => AstcBlock::B8x5,
1775 "8x6" => AstcBlock::B8x6,
1776 "8x8" => AstcBlock::B8x8,
1777 "10x5" => AstcBlock::B10x5,
1778 "10x6" => AstcBlock::B10x6,
1779 "10x8" => AstcBlock::B10x8,
1780 "10x10" => AstcBlock::B10x10,
1781 "12x10" => AstcBlock::B12x10,
1782 "12x12" => AstcBlock::B12x12,
1783 _ => return Err(E::invalid_value(Unexpected::Str(s), &self)),
1784 };
1785
1786 let channel = match channel {
1787 "unorm" => AstcChannel::Unorm,
1788 "unorm-srgb" => AstcChannel::UnormSrgb,
1789 "hdr" => AstcChannel::Hdr,
1790 _ => return Err(E::invalid_value(Unexpected::Str(s), &self)),
1791 };
1792
1793 TextureFormat::Astc { block, channel }
1794 } else {
1795 return Err(E::invalid_value(Unexpected::Str(s), &self));
1796 }
1797 }
1798 };
1799
1800 Ok(format)
1801 }
1802 }
1803
1804 deserializer.deserialize_str(TextureFormatVisitor)
1805 }
1806}
1807
1808#[cfg(any(feature = "serde", test))]
1809impl Serialize for TextureFormat {
1810 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1811 where
1812 S: serde::Serializer,
1813 {
1814 let s: alloc::string::String;
1815 let name = match *self {
1816 TextureFormat::R8Unorm => "r8unorm",
1817 TextureFormat::R8Snorm => "r8snorm",
1818 TextureFormat::R8Uint => "r8uint",
1819 TextureFormat::R8Sint => "r8sint",
1820 TextureFormat::R16Uint => "r16uint",
1821 TextureFormat::R16Sint => "r16sint",
1822 TextureFormat::R16Unorm => "r16unorm",
1823 TextureFormat::R16Snorm => "r16snorm",
1824 TextureFormat::R16Float => "r16float",
1825 TextureFormat::Rg8Unorm => "rg8unorm",
1826 TextureFormat::Rg8Snorm => "rg8snorm",
1827 TextureFormat::Rg8Uint => "rg8uint",
1828 TextureFormat::Rg8Sint => "rg8sint",
1829 TextureFormat::R32Uint => "r32uint",
1830 TextureFormat::R32Sint => "r32sint",
1831 TextureFormat::R32Float => "r32float",
1832 TextureFormat::Rg16Uint => "rg16uint",
1833 TextureFormat::Rg16Sint => "rg16sint",
1834 TextureFormat::Rg16Unorm => "rg16unorm",
1835 TextureFormat::Rg16Snorm => "rg16snorm",
1836 TextureFormat::Rg16Float => "rg16float",
1837 TextureFormat::Rgba8Unorm => "rgba8unorm",
1838 TextureFormat::Rgba8UnormSrgb => "rgba8unorm-srgb",
1839 TextureFormat::Rgba8Snorm => "rgba8snorm",
1840 TextureFormat::Rgba8Uint => "rgba8uint",
1841 TextureFormat::Rgba8Sint => "rgba8sint",
1842 TextureFormat::Bgra8Unorm => "bgra8unorm",
1843 TextureFormat::Bgra8UnormSrgb => "bgra8unorm-srgb",
1844 TextureFormat::Rgb10a2Uint => "rgb10a2uint",
1845 TextureFormat::Rgb10a2Unorm => "rgb10a2unorm",
1846 TextureFormat::Rg11b10Ufloat => "rg11b10ufloat",
1847 TextureFormat::R64Uint => "r64uint",
1848 TextureFormat::Rg32Uint => "rg32uint",
1849 TextureFormat::Rg32Sint => "rg32sint",
1850 TextureFormat::Rg32Float => "rg32float",
1851 TextureFormat::Rgba16Uint => "rgba16uint",
1852 TextureFormat::Rgba16Sint => "rgba16sint",
1853 TextureFormat::Rgba16Unorm => "rgba16unorm",
1854 TextureFormat::Rgba16Snorm => "rgba16snorm",
1855 TextureFormat::Rgba16Float => "rgba16float",
1856 TextureFormat::Rgba32Uint => "rgba32uint",
1857 TextureFormat::Rgba32Sint => "rgba32sint",
1858 TextureFormat::Rgba32Float => "rgba32float",
1859 TextureFormat::Stencil8 => "stencil8",
1860 TextureFormat::Depth32Float => "depth32float",
1861 TextureFormat::Depth16Unorm => "depth16unorm",
1862 TextureFormat::Depth32FloatStencil8 => "depth32float-stencil8",
1863 TextureFormat::Depth24Plus => "depth24plus",
1864 TextureFormat::Depth24PlusStencil8 => "depth24plus-stencil8",
1865 TextureFormat::NV12 => "nv12",
1866 TextureFormat::P010 => "p010",
1867 TextureFormat::Rgb9e5Ufloat => "rgb9e5ufloat",
1868 TextureFormat::Bc1RgbaUnorm => "bc1-rgba-unorm",
1869 TextureFormat::Bc1RgbaUnormSrgb => "bc1-rgba-unorm-srgb",
1870 TextureFormat::Bc2RgbaUnorm => "bc2-rgba-unorm",
1871 TextureFormat::Bc2RgbaUnormSrgb => "bc2-rgba-unorm-srgb",
1872 TextureFormat::Bc3RgbaUnorm => "bc3-rgba-unorm",
1873 TextureFormat::Bc3RgbaUnormSrgb => "bc3-rgba-unorm-srgb",
1874 TextureFormat::Bc4RUnorm => "bc4-r-unorm",
1875 TextureFormat::Bc4RSnorm => "bc4-r-snorm",
1876 TextureFormat::Bc5RgUnorm => "bc5-rg-unorm",
1877 TextureFormat::Bc5RgSnorm => "bc5-rg-snorm",
1878 TextureFormat::Bc6hRgbUfloat => "bc6h-rgb-ufloat",
1879 TextureFormat::Bc6hRgbFloat => "bc6h-rgb-float",
1880 TextureFormat::Bc7RgbaUnorm => "bc7-rgba-unorm",
1881 TextureFormat::Bc7RgbaUnormSrgb => "bc7-rgba-unorm-srgb",
1882 TextureFormat::Etc2Rgb8Unorm => "etc2-rgb8unorm",
1883 TextureFormat::Etc2Rgb8UnormSrgb => "etc2-rgb8unorm-srgb",
1884 TextureFormat::Etc2Rgb8A1Unorm => "etc2-rgb8a1unorm",
1885 TextureFormat::Etc2Rgb8A1UnormSrgb => "etc2-rgb8a1unorm-srgb",
1886 TextureFormat::Etc2Rgba8Unorm => "etc2-rgba8unorm",
1887 TextureFormat::Etc2Rgba8UnormSrgb => "etc2-rgba8unorm-srgb",
1888 TextureFormat::EacR11Unorm => "eac-r11unorm",
1889 TextureFormat::EacR11Snorm => "eac-r11snorm",
1890 TextureFormat::EacRg11Unorm => "eac-rg11unorm",
1891 TextureFormat::EacRg11Snorm => "eac-rg11snorm",
1892 TextureFormat::Astc { block, channel } => {
1893 let block = match block {
1894 AstcBlock::B4x4 => "4x4",
1895 AstcBlock::B5x4 => "5x4",
1896 AstcBlock::B5x5 => "5x5",
1897 AstcBlock::B6x5 => "6x5",
1898 AstcBlock::B6x6 => "6x6",
1899 AstcBlock::B8x5 => "8x5",
1900 AstcBlock::B8x6 => "8x6",
1901 AstcBlock::B8x8 => "8x8",
1902 AstcBlock::B10x5 => "10x5",
1903 AstcBlock::B10x6 => "10x6",
1904 AstcBlock::B10x8 => "10x8",
1905 AstcBlock::B10x10 => "10x10",
1906 AstcBlock::B12x10 => "12x10",
1907 AstcBlock::B12x12 => "12x12",
1908 };
1909
1910 let channel = match channel {
1911 AstcChannel::Unorm => "unorm",
1912 AstcChannel::UnormSrgb => "unorm-srgb",
1913 AstcChannel::Hdr => "hdr",
1914 };
1915
1916 s = alloc::format!("astc-{block}-{channel}");
1917 &s
1918 }
1919 };
1920 serializer.serialize_str(name)
1921 }
1922}
1923
1924bitflags::bitflags! {
1925 #[repr(transparent)]
1927 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1928 #[cfg_attr(feature = "serde", serde(transparent))]
1929 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1930 pub struct TextureFormatFeatureFlags: u32 {
1931 const FILTERABLE = 1 << 0;
1934 const MULTISAMPLE_X2 = 1 << 1;
1936 const MULTISAMPLE_X4 = 1 << 2 ;
1938 const MULTISAMPLE_X8 = 1 << 3 ;
1940 const MULTISAMPLE_X16 = 1 << 4;
1942 const MULTISAMPLE_RESOLVE = 1 << 5;
1945 const STORAGE_READ_ONLY = 1 << 6;
1948 const STORAGE_WRITE_ONLY = 1 << 7;
1951 const STORAGE_READ_WRITE = 1 << 8;
1954 const STORAGE_ATOMIC = 1 << 9;
1957 const BLENDABLE = 1 << 10;
1959 }
1960}
1961
1962impl TextureFormatFeatureFlags {
1963 #[must_use]
1967 pub fn sample_count_supported(&self, count: u32) -> bool {
1968 use TextureFormatFeatureFlags as tfsc;
1969
1970 match count {
1971 1 => true,
1972 2 => self.contains(tfsc::MULTISAMPLE_X2),
1973 4 => self.contains(tfsc::MULTISAMPLE_X4),
1974 8 => self.contains(tfsc::MULTISAMPLE_X8),
1975 16 => self.contains(tfsc::MULTISAMPLE_X16),
1976 _ => false,
1977 }
1978 }
1979
1980 #[must_use]
1982 pub fn supported_sample_counts(&self) -> Vec<u32> {
1983 let all_possible_sample_counts: [u32; 5] = [1, 2, 4, 8, 16];
1984 all_possible_sample_counts
1985 .into_iter()
1986 .filter(|&sc| self.sample_count_supported(sc))
1987 .collect()
1988 }
1989}
1990
1991#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
1995#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1996pub struct TextureFormatFeatures {
1997 pub allowed_usages: TextureUsages,
1999 pub flags: TextureFormatFeatureFlags,
2001}
2002
2003#[cfg(test)]
2004mod tests {
2005 use super::*;
2006 use exhaust::Exhaust;
2007 use hashbrown::HashSet;
2008
2009 #[test]
2010 fn texture_format_serialize() {
2011 use alloc::string::ToString;
2012
2013 assert_eq!(
2014 serde_json::to_string(&TextureFormat::R8Unorm).unwrap(),
2015 "\"r8unorm\"".to_string()
2016 );
2017 assert_eq!(
2018 serde_json::to_string(&TextureFormat::R8Snorm).unwrap(),
2019 "\"r8snorm\"".to_string()
2020 );
2021 assert_eq!(
2022 serde_json::to_string(&TextureFormat::R8Uint).unwrap(),
2023 "\"r8uint\"".to_string()
2024 );
2025 assert_eq!(
2026 serde_json::to_string(&TextureFormat::R8Sint).unwrap(),
2027 "\"r8sint\"".to_string()
2028 );
2029 assert_eq!(
2030 serde_json::to_string(&TextureFormat::R16Uint).unwrap(),
2031 "\"r16uint\"".to_string()
2032 );
2033 assert_eq!(
2034 serde_json::to_string(&TextureFormat::R16Sint).unwrap(),
2035 "\"r16sint\"".to_string()
2036 );
2037 assert_eq!(
2038 serde_json::to_string(&TextureFormat::R16Unorm).unwrap(),
2039 "\"r16unorm\"".to_string()
2040 );
2041 assert_eq!(
2042 serde_json::to_string(&TextureFormat::R16Snorm).unwrap(),
2043 "\"r16snorm\"".to_string()
2044 );
2045 assert_eq!(
2046 serde_json::to_string(&TextureFormat::R16Float).unwrap(),
2047 "\"r16float\"".to_string()
2048 );
2049 assert_eq!(
2050 serde_json::to_string(&TextureFormat::Rg8Unorm).unwrap(),
2051 "\"rg8unorm\"".to_string()
2052 );
2053 assert_eq!(
2054 serde_json::to_string(&TextureFormat::Rg8Snorm).unwrap(),
2055 "\"rg8snorm\"".to_string()
2056 );
2057 assert_eq!(
2058 serde_json::to_string(&TextureFormat::Rg8Uint).unwrap(),
2059 "\"rg8uint\"".to_string()
2060 );
2061 assert_eq!(
2062 serde_json::to_string(&TextureFormat::Rg8Sint).unwrap(),
2063 "\"rg8sint\"".to_string()
2064 );
2065 assert_eq!(
2066 serde_json::to_string(&TextureFormat::R32Uint).unwrap(),
2067 "\"r32uint\"".to_string()
2068 );
2069 assert_eq!(
2070 serde_json::to_string(&TextureFormat::R32Sint).unwrap(),
2071 "\"r32sint\"".to_string()
2072 );
2073 assert_eq!(
2074 serde_json::to_string(&TextureFormat::R32Float).unwrap(),
2075 "\"r32float\"".to_string()
2076 );
2077 assert_eq!(
2078 serde_json::to_string(&TextureFormat::Rg16Uint).unwrap(),
2079 "\"rg16uint\"".to_string()
2080 );
2081 assert_eq!(
2082 serde_json::to_string(&TextureFormat::Rg16Sint).unwrap(),
2083 "\"rg16sint\"".to_string()
2084 );
2085 assert_eq!(
2086 serde_json::to_string(&TextureFormat::Rg16Unorm).unwrap(),
2087 "\"rg16unorm\"".to_string()
2088 );
2089 assert_eq!(
2090 serde_json::to_string(&TextureFormat::Rg16Snorm).unwrap(),
2091 "\"rg16snorm\"".to_string()
2092 );
2093 assert_eq!(
2094 serde_json::to_string(&TextureFormat::Rg16Float).unwrap(),
2095 "\"rg16float\"".to_string()
2096 );
2097 assert_eq!(
2098 serde_json::to_string(&TextureFormat::Rgba8Unorm).unwrap(),
2099 "\"rgba8unorm\"".to_string()
2100 );
2101 assert_eq!(
2102 serde_json::to_string(&TextureFormat::Rgba8UnormSrgb).unwrap(),
2103 "\"rgba8unorm-srgb\"".to_string()
2104 );
2105 assert_eq!(
2106 serde_json::to_string(&TextureFormat::Rgba8Snorm).unwrap(),
2107 "\"rgba8snorm\"".to_string()
2108 );
2109 assert_eq!(
2110 serde_json::to_string(&TextureFormat::Rgba8Uint).unwrap(),
2111 "\"rgba8uint\"".to_string()
2112 );
2113 assert_eq!(
2114 serde_json::to_string(&TextureFormat::Rgba8Sint).unwrap(),
2115 "\"rgba8sint\"".to_string()
2116 );
2117 assert_eq!(
2118 serde_json::to_string(&TextureFormat::Bgra8Unorm).unwrap(),
2119 "\"bgra8unorm\"".to_string()
2120 );
2121 assert_eq!(
2122 serde_json::to_string(&TextureFormat::Bgra8UnormSrgb).unwrap(),
2123 "\"bgra8unorm-srgb\"".to_string()
2124 );
2125 assert_eq!(
2126 serde_json::to_string(&TextureFormat::Rgb10a2Uint).unwrap(),
2127 "\"rgb10a2uint\"".to_string()
2128 );
2129 assert_eq!(
2130 serde_json::to_string(&TextureFormat::Rgb10a2Unorm).unwrap(),
2131 "\"rgb10a2unorm\"".to_string()
2132 );
2133 assert_eq!(
2134 serde_json::to_string(&TextureFormat::Rg11b10Ufloat).unwrap(),
2135 "\"rg11b10ufloat\"".to_string()
2136 );
2137 assert_eq!(
2138 serde_json::to_string(&TextureFormat::R64Uint).unwrap(),
2139 "\"r64uint\"".to_string()
2140 );
2141 assert_eq!(
2142 serde_json::to_string(&TextureFormat::Rg32Uint).unwrap(),
2143 "\"rg32uint\"".to_string()
2144 );
2145 assert_eq!(
2146 serde_json::to_string(&TextureFormat::Rg32Sint).unwrap(),
2147 "\"rg32sint\"".to_string()
2148 );
2149 assert_eq!(
2150 serde_json::to_string(&TextureFormat::Rg32Float).unwrap(),
2151 "\"rg32float\"".to_string()
2152 );
2153 assert_eq!(
2154 serde_json::to_string(&TextureFormat::Rgba16Uint).unwrap(),
2155 "\"rgba16uint\"".to_string()
2156 );
2157 assert_eq!(
2158 serde_json::to_string(&TextureFormat::Rgba16Sint).unwrap(),
2159 "\"rgba16sint\"".to_string()
2160 );
2161 assert_eq!(
2162 serde_json::to_string(&TextureFormat::Rgba16Unorm).unwrap(),
2163 "\"rgba16unorm\"".to_string()
2164 );
2165 assert_eq!(
2166 serde_json::to_string(&TextureFormat::Rgba16Snorm).unwrap(),
2167 "\"rgba16snorm\"".to_string()
2168 );
2169 assert_eq!(
2170 serde_json::to_string(&TextureFormat::Rgba16Float).unwrap(),
2171 "\"rgba16float\"".to_string()
2172 );
2173 assert_eq!(
2174 serde_json::to_string(&TextureFormat::Rgba32Uint).unwrap(),
2175 "\"rgba32uint\"".to_string()
2176 );
2177 assert_eq!(
2178 serde_json::to_string(&TextureFormat::Rgba32Sint).unwrap(),
2179 "\"rgba32sint\"".to_string()
2180 );
2181 assert_eq!(
2182 serde_json::to_string(&TextureFormat::Rgba32Float).unwrap(),
2183 "\"rgba32float\"".to_string()
2184 );
2185 assert_eq!(
2186 serde_json::to_string(&TextureFormat::Stencil8).unwrap(),
2187 "\"stencil8\"".to_string()
2188 );
2189 assert_eq!(
2190 serde_json::to_string(&TextureFormat::Depth32Float).unwrap(),
2191 "\"depth32float\"".to_string()
2192 );
2193 assert_eq!(
2194 serde_json::to_string(&TextureFormat::Depth16Unorm).unwrap(),
2195 "\"depth16unorm\"".to_string()
2196 );
2197 assert_eq!(
2198 serde_json::to_string(&TextureFormat::Depth32FloatStencil8).unwrap(),
2199 "\"depth32float-stencil8\"".to_string()
2200 );
2201 assert_eq!(
2202 serde_json::to_string(&TextureFormat::Depth24Plus).unwrap(),
2203 "\"depth24plus\"".to_string()
2204 );
2205 assert_eq!(
2206 serde_json::to_string(&TextureFormat::Depth24PlusStencil8).unwrap(),
2207 "\"depth24plus-stencil8\"".to_string()
2208 );
2209 assert_eq!(
2210 serde_json::to_string(&TextureFormat::Rgb9e5Ufloat).unwrap(),
2211 "\"rgb9e5ufloat\"".to_string()
2212 );
2213 assert_eq!(
2214 serde_json::to_string(&TextureFormat::Bc1RgbaUnorm).unwrap(),
2215 "\"bc1-rgba-unorm\"".to_string()
2216 );
2217 assert_eq!(
2218 serde_json::to_string(&TextureFormat::Bc1RgbaUnormSrgb).unwrap(),
2219 "\"bc1-rgba-unorm-srgb\"".to_string()
2220 );
2221 assert_eq!(
2222 serde_json::to_string(&TextureFormat::Bc2RgbaUnorm).unwrap(),
2223 "\"bc2-rgba-unorm\"".to_string()
2224 );
2225 assert_eq!(
2226 serde_json::to_string(&TextureFormat::Bc2RgbaUnormSrgb).unwrap(),
2227 "\"bc2-rgba-unorm-srgb\"".to_string()
2228 );
2229 assert_eq!(
2230 serde_json::to_string(&TextureFormat::Bc3RgbaUnorm).unwrap(),
2231 "\"bc3-rgba-unorm\"".to_string()
2232 );
2233 assert_eq!(
2234 serde_json::to_string(&TextureFormat::Bc3RgbaUnormSrgb).unwrap(),
2235 "\"bc3-rgba-unorm-srgb\"".to_string()
2236 );
2237 assert_eq!(
2238 serde_json::to_string(&TextureFormat::Bc4RUnorm).unwrap(),
2239 "\"bc4-r-unorm\"".to_string()
2240 );
2241 assert_eq!(
2242 serde_json::to_string(&TextureFormat::Bc4RSnorm).unwrap(),
2243 "\"bc4-r-snorm\"".to_string()
2244 );
2245 assert_eq!(
2246 serde_json::to_string(&TextureFormat::Bc5RgUnorm).unwrap(),
2247 "\"bc5-rg-unorm\"".to_string()
2248 );
2249 assert_eq!(
2250 serde_json::to_string(&TextureFormat::Bc5RgSnorm).unwrap(),
2251 "\"bc5-rg-snorm\"".to_string()
2252 );
2253 assert_eq!(
2254 serde_json::to_string(&TextureFormat::Bc6hRgbUfloat).unwrap(),
2255 "\"bc6h-rgb-ufloat\"".to_string()
2256 );
2257 assert_eq!(
2258 serde_json::to_string(&TextureFormat::Bc6hRgbFloat).unwrap(),
2259 "\"bc6h-rgb-float\"".to_string()
2260 );
2261 assert_eq!(
2262 serde_json::to_string(&TextureFormat::Bc7RgbaUnorm).unwrap(),
2263 "\"bc7-rgba-unorm\"".to_string()
2264 );
2265 assert_eq!(
2266 serde_json::to_string(&TextureFormat::Bc7RgbaUnormSrgb).unwrap(),
2267 "\"bc7-rgba-unorm-srgb\"".to_string()
2268 );
2269 assert_eq!(
2270 serde_json::to_string(&TextureFormat::Etc2Rgb8Unorm).unwrap(),
2271 "\"etc2-rgb8unorm\"".to_string()
2272 );
2273 assert_eq!(
2274 serde_json::to_string(&TextureFormat::Etc2Rgb8UnormSrgb).unwrap(),
2275 "\"etc2-rgb8unorm-srgb\"".to_string()
2276 );
2277 assert_eq!(
2278 serde_json::to_string(&TextureFormat::Etc2Rgb8A1Unorm).unwrap(),
2279 "\"etc2-rgb8a1unorm\"".to_string()
2280 );
2281 assert_eq!(
2282 serde_json::to_string(&TextureFormat::Etc2Rgb8A1UnormSrgb).unwrap(),
2283 "\"etc2-rgb8a1unorm-srgb\"".to_string()
2284 );
2285 assert_eq!(
2286 serde_json::to_string(&TextureFormat::Etc2Rgba8Unorm).unwrap(),
2287 "\"etc2-rgba8unorm\"".to_string()
2288 );
2289 assert_eq!(
2290 serde_json::to_string(&TextureFormat::Etc2Rgba8UnormSrgb).unwrap(),
2291 "\"etc2-rgba8unorm-srgb\"".to_string()
2292 );
2293 assert_eq!(
2294 serde_json::to_string(&TextureFormat::EacR11Unorm).unwrap(),
2295 "\"eac-r11unorm\"".to_string()
2296 );
2297 assert_eq!(
2298 serde_json::to_string(&TextureFormat::EacR11Snorm).unwrap(),
2299 "\"eac-r11snorm\"".to_string()
2300 );
2301 assert_eq!(
2302 serde_json::to_string(&TextureFormat::EacRg11Unorm).unwrap(),
2303 "\"eac-rg11unorm\"".to_string()
2304 );
2305 assert_eq!(
2306 serde_json::to_string(&TextureFormat::EacRg11Snorm).unwrap(),
2307 "\"eac-rg11snorm\"".to_string()
2308 );
2309 }
2310
2311 #[test]
2312 fn texture_format_deserialize() {
2313 assert_eq!(
2314 serde_json::from_str::<TextureFormat>("\"r8unorm\"").unwrap(),
2315 TextureFormat::R8Unorm
2316 );
2317 assert_eq!(
2318 serde_json::from_str::<TextureFormat>("\"r8snorm\"").unwrap(),
2319 TextureFormat::R8Snorm
2320 );
2321 assert_eq!(
2322 serde_json::from_str::<TextureFormat>("\"r8uint\"").unwrap(),
2323 TextureFormat::R8Uint
2324 );
2325 assert_eq!(
2326 serde_json::from_str::<TextureFormat>("\"r8sint\"").unwrap(),
2327 TextureFormat::R8Sint
2328 );
2329 assert_eq!(
2330 serde_json::from_str::<TextureFormat>("\"r16uint\"").unwrap(),
2331 TextureFormat::R16Uint
2332 );
2333 assert_eq!(
2334 serde_json::from_str::<TextureFormat>("\"r16sint\"").unwrap(),
2335 TextureFormat::R16Sint
2336 );
2337 assert_eq!(
2338 serde_json::from_str::<TextureFormat>("\"r16unorm\"").unwrap(),
2339 TextureFormat::R16Unorm
2340 );
2341 assert_eq!(
2342 serde_json::from_str::<TextureFormat>("\"r16snorm\"").unwrap(),
2343 TextureFormat::R16Snorm
2344 );
2345 assert_eq!(
2346 serde_json::from_str::<TextureFormat>("\"r16float\"").unwrap(),
2347 TextureFormat::R16Float
2348 );
2349 assert_eq!(
2350 serde_json::from_str::<TextureFormat>("\"rg8unorm\"").unwrap(),
2351 TextureFormat::Rg8Unorm
2352 );
2353 assert_eq!(
2354 serde_json::from_str::<TextureFormat>("\"rg8snorm\"").unwrap(),
2355 TextureFormat::Rg8Snorm
2356 );
2357 assert_eq!(
2358 serde_json::from_str::<TextureFormat>("\"rg8uint\"").unwrap(),
2359 TextureFormat::Rg8Uint
2360 );
2361 assert_eq!(
2362 serde_json::from_str::<TextureFormat>("\"rg8sint\"").unwrap(),
2363 TextureFormat::Rg8Sint
2364 );
2365 assert_eq!(
2366 serde_json::from_str::<TextureFormat>("\"r32uint\"").unwrap(),
2367 TextureFormat::R32Uint
2368 );
2369 assert_eq!(
2370 serde_json::from_str::<TextureFormat>("\"r32sint\"").unwrap(),
2371 TextureFormat::R32Sint
2372 );
2373 assert_eq!(
2374 serde_json::from_str::<TextureFormat>("\"r32float\"").unwrap(),
2375 TextureFormat::R32Float
2376 );
2377 assert_eq!(
2378 serde_json::from_str::<TextureFormat>("\"rg16uint\"").unwrap(),
2379 TextureFormat::Rg16Uint
2380 );
2381 assert_eq!(
2382 serde_json::from_str::<TextureFormat>("\"rg16sint\"").unwrap(),
2383 TextureFormat::Rg16Sint
2384 );
2385 assert_eq!(
2386 serde_json::from_str::<TextureFormat>("\"rg16unorm\"").unwrap(),
2387 TextureFormat::Rg16Unorm
2388 );
2389 assert_eq!(
2390 serde_json::from_str::<TextureFormat>("\"rg16snorm\"").unwrap(),
2391 TextureFormat::Rg16Snorm
2392 );
2393 assert_eq!(
2394 serde_json::from_str::<TextureFormat>("\"rg16float\"").unwrap(),
2395 TextureFormat::Rg16Float
2396 );
2397 assert_eq!(
2398 serde_json::from_str::<TextureFormat>("\"rgba8unorm\"").unwrap(),
2399 TextureFormat::Rgba8Unorm
2400 );
2401 assert_eq!(
2402 serde_json::from_str::<TextureFormat>("\"rgba8unorm-srgb\"").unwrap(),
2403 TextureFormat::Rgba8UnormSrgb
2404 );
2405 assert_eq!(
2406 serde_json::from_str::<TextureFormat>("\"rgba8snorm\"").unwrap(),
2407 TextureFormat::Rgba8Snorm
2408 );
2409 assert_eq!(
2410 serde_json::from_str::<TextureFormat>("\"rgba8uint\"").unwrap(),
2411 TextureFormat::Rgba8Uint
2412 );
2413 assert_eq!(
2414 serde_json::from_str::<TextureFormat>("\"rgba8sint\"").unwrap(),
2415 TextureFormat::Rgba8Sint
2416 );
2417 assert_eq!(
2418 serde_json::from_str::<TextureFormat>("\"bgra8unorm\"").unwrap(),
2419 TextureFormat::Bgra8Unorm
2420 );
2421 assert_eq!(
2422 serde_json::from_str::<TextureFormat>("\"bgra8unorm-srgb\"").unwrap(),
2423 TextureFormat::Bgra8UnormSrgb
2424 );
2425 assert_eq!(
2426 serde_json::from_str::<TextureFormat>("\"rgb10a2uint\"").unwrap(),
2427 TextureFormat::Rgb10a2Uint
2428 );
2429 assert_eq!(
2430 serde_json::from_str::<TextureFormat>("\"rgb10a2unorm\"").unwrap(),
2431 TextureFormat::Rgb10a2Unorm
2432 );
2433 assert_eq!(
2434 serde_json::from_str::<TextureFormat>("\"rg11b10ufloat\"").unwrap(),
2435 TextureFormat::Rg11b10Ufloat
2436 );
2437 assert_eq!(
2438 serde_json::from_str::<TextureFormat>("\"r64uint\"").unwrap(),
2439 TextureFormat::R64Uint
2440 );
2441 assert_eq!(
2442 serde_json::from_str::<TextureFormat>("\"rg32uint\"").unwrap(),
2443 TextureFormat::Rg32Uint
2444 );
2445 assert_eq!(
2446 serde_json::from_str::<TextureFormat>("\"rg32sint\"").unwrap(),
2447 TextureFormat::Rg32Sint
2448 );
2449 assert_eq!(
2450 serde_json::from_str::<TextureFormat>("\"rg32float\"").unwrap(),
2451 TextureFormat::Rg32Float
2452 );
2453 assert_eq!(
2454 serde_json::from_str::<TextureFormat>("\"rgba16uint\"").unwrap(),
2455 TextureFormat::Rgba16Uint
2456 );
2457 assert_eq!(
2458 serde_json::from_str::<TextureFormat>("\"rgba16sint\"").unwrap(),
2459 TextureFormat::Rgba16Sint
2460 );
2461 assert_eq!(
2462 serde_json::from_str::<TextureFormat>("\"rgba16unorm\"").unwrap(),
2463 TextureFormat::Rgba16Unorm
2464 );
2465 assert_eq!(
2466 serde_json::from_str::<TextureFormat>("\"rgba16snorm\"").unwrap(),
2467 TextureFormat::Rgba16Snorm
2468 );
2469 assert_eq!(
2470 serde_json::from_str::<TextureFormat>("\"rgba16float\"").unwrap(),
2471 TextureFormat::Rgba16Float
2472 );
2473 assert_eq!(
2474 serde_json::from_str::<TextureFormat>("\"rgba32uint\"").unwrap(),
2475 TextureFormat::Rgba32Uint
2476 );
2477 assert_eq!(
2478 serde_json::from_str::<TextureFormat>("\"rgba32sint\"").unwrap(),
2479 TextureFormat::Rgba32Sint
2480 );
2481 assert_eq!(
2482 serde_json::from_str::<TextureFormat>("\"rgba32float\"").unwrap(),
2483 TextureFormat::Rgba32Float
2484 );
2485 assert_eq!(
2486 serde_json::from_str::<TextureFormat>("\"stencil8\"").unwrap(),
2487 TextureFormat::Stencil8
2488 );
2489 assert_eq!(
2490 serde_json::from_str::<TextureFormat>("\"depth32float\"").unwrap(),
2491 TextureFormat::Depth32Float
2492 );
2493 assert_eq!(
2494 serde_json::from_str::<TextureFormat>("\"depth16unorm\"").unwrap(),
2495 TextureFormat::Depth16Unorm
2496 );
2497 assert_eq!(
2498 serde_json::from_str::<TextureFormat>("\"depth32float-stencil8\"").unwrap(),
2499 TextureFormat::Depth32FloatStencil8
2500 );
2501 assert_eq!(
2502 serde_json::from_str::<TextureFormat>("\"depth24plus\"").unwrap(),
2503 TextureFormat::Depth24Plus
2504 );
2505 assert_eq!(
2506 serde_json::from_str::<TextureFormat>("\"depth24plus-stencil8\"").unwrap(),
2507 TextureFormat::Depth24PlusStencil8
2508 );
2509 assert_eq!(
2510 serde_json::from_str::<TextureFormat>("\"rgb9e5ufloat\"").unwrap(),
2511 TextureFormat::Rgb9e5Ufloat
2512 );
2513 assert_eq!(
2514 serde_json::from_str::<TextureFormat>("\"bc1-rgba-unorm\"").unwrap(),
2515 TextureFormat::Bc1RgbaUnorm
2516 );
2517 assert_eq!(
2518 serde_json::from_str::<TextureFormat>("\"bc1-rgba-unorm-srgb\"").unwrap(),
2519 TextureFormat::Bc1RgbaUnormSrgb
2520 );
2521 assert_eq!(
2522 serde_json::from_str::<TextureFormat>("\"bc2-rgba-unorm\"").unwrap(),
2523 TextureFormat::Bc2RgbaUnorm
2524 );
2525 assert_eq!(
2526 serde_json::from_str::<TextureFormat>("\"bc2-rgba-unorm-srgb\"").unwrap(),
2527 TextureFormat::Bc2RgbaUnormSrgb
2528 );
2529 assert_eq!(
2530 serde_json::from_str::<TextureFormat>("\"bc3-rgba-unorm\"").unwrap(),
2531 TextureFormat::Bc3RgbaUnorm
2532 );
2533 assert_eq!(
2534 serde_json::from_str::<TextureFormat>("\"bc3-rgba-unorm-srgb\"").unwrap(),
2535 TextureFormat::Bc3RgbaUnormSrgb
2536 );
2537 assert_eq!(
2538 serde_json::from_str::<TextureFormat>("\"bc4-r-unorm\"").unwrap(),
2539 TextureFormat::Bc4RUnorm
2540 );
2541 assert_eq!(
2542 serde_json::from_str::<TextureFormat>("\"bc4-r-snorm\"").unwrap(),
2543 TextureFormat::Bc4RSnorm
2544 );
2545 assert_eq!(
2546 serde_json::from_str::<TextureFormat>("\"bc5-rg-unorm\"").unwrap(),
2547 TextureFormat::Bc5RgUnorm
2548 );
2549 assert_eq!(
2550 serde_json::from_str::<TextureFormat>("\"bc5-rg-snorm\"").unwrap(),
2551 TextureFormat::Bc5RgSnorm
2552 );
2553 assert_eq!(
2554 serde_json::from_str::<TextureFormat>("\"bc6h-rgb-ufloat\"").unwrap(),
2555 TextureFormat::Bc6hRgbUfloat
2556 );
2557 assert_eq!(
2558 serde_json::from_str::<TextureFormat>("\"bc6h-rgb-float\"").unwrap(),
2559 TextureFormat::Bc6hRgbFloat
2560 );
2561 assert_eq!(
2562 serde_json::from_str::<TextureFormat>("\"bc7-rgba-unorm\"").unwrap(),
2563 TextureFormat::Bc7RgbaUnorm
2564 );
2565 assert_eq!(
2566 serde_json::from_str::<TextureFormat>("\"bc7-rgba-unorm-srgb\"").unwrap(),
2567 TextureFormat::Bc7RgbaUnormSrgb
2568 );
2569 assert_eq!(
2570 serde_json::from_str::<TextureFormat>("\"etc2-rgb8unorm\"").unwrap(),
2571 TextureFormat::Etc2Rgb8Unorm
2572 );
2573 assert_eq!(
2574 serde_json::from_str::<TextureFormat>("\"etc2-rgb8unorm-srgb\"").unwrap(),
2575 TextureFormat::Etc2Rgb8UnormSrgb
2576 );
2577 assert_eq!(
2578 serde_json::from_str::<TextureFormat>("\"etc2-rgb8a1unorm\"").unwrap(),
2579 TextureFormat::Etc2Rgb8A1Unorm
2580 );
2581 assert_eq!(
2582 serde_json::from_str::<TextureFormat>("\"etc2-rgb8a1unorm-srgb\"").unwrap(),
2583 TextureFormat::Etc2Rgb8A1UnormSrgb
2584 );
2585 assert_eq!(
2586 serde_json::from_str::<TextureFormat>("\"etc2-rgba8unorm\"").unwrap(),
2587 TextureFormat::Etc2Rgba8Unorm
2588 );
2589 assert_eq!(
2590 serde_json::from_str::<TextureFormat>("\"etc2-rgba8unorm-srgb\"").unwrap(),
2591 TextureFormat::Etc2Rgba8UnormSrgb
2592 );
2593 assert_eq!(
2594 serde_json::from_str::<TextureFormat>("\"eac-r11unorm\"").unwrap(),
2595 TextureFormat::EacR11Unorm
2596 );
2597 assert_eq!(
2598 serde_json::from_str::<TextureFormat>("\"eac-r11snorm\"").unwrap(),
2599 TextureFormat::EacR11Snorm
2600 );
2601 assert_eq!(
2602 serde_json::from_str::<TextureFormat>("\"eac-rg11unorm\"").unwrap(),
2603 TextureFormat::EacRg11Unorm
2604 );
2605 assert_eq!(
2606 serde_json::from_str::<TextureFormat>("\"eac-rg11snorm\"").unwrap(),
2607 TextureFormat::EacRg11Snorm
2608 );
2609 }
2610
2611 #[test]
2613 fn is_depth_stencil_format() {
2614 let depth_stencil_formats: HashSet<TextureFormat> = HashSet::from([
2616 TextureFormat::Stencil8,
2617 TextureFormat::Depth16Unorm,
2618 TextureFormat::Depth24Plus,
2619 TextureFormat::Depth24PlusStencil8,
2620 TextureFormat::Depth32Float,
2621 TextureFormat::Depth32FloatStencil8,
2622 ]);
2623
2624 for format in TextureFormat::exhaust() {
2625 if depth_stencil_formats.contains(&format) {
2626 assert!(format.is_depth_stencil_format());
2627 } else {
2628 assert!(!format.is_depth_stencil_format());
2629 }
2630 }
2631 }
2632
2633 #[test]
2635 fn is_combined_depth_stencil_format() {
2636 let valid_formats = [
2638 TextureFormat::Depth24PlusStencil8,
2639 TextureFormat::Depth32FloatStencil8,
2640 ];
2641
2642 for format in TextureFormat::exhaust() {
2643 if valid_formats.contains(&format) {
2644 assert!(format.is_combined_depth_stencil_format());
2645 } else {
2646 assert!(!format.is_combined_depth_stencil_format());
2647 }
2648 }
2649 }
2650
2651 #[test]
2653 fn has_color_aspect() {
2654 let valid_formats: HashSet<TextureFormat> = HashSet::from([
2656 TextureFormat::R8Unorm,
2657 TextureFormat::R8Snorm,
2658 TextureFormat::R8Uint,
2659 TextureFormat::R8Sint,
2660 TextureFormat::R16Uint,
2661 TextureFormat::R16Sint,
2662 TextureFormat::R16Unorm,
2663 TextureFormat::R16Snorm,
2664 TextureFormat::R16Float,
2665 TextureFormat::Rg8Unorm,
2666 TextureFormat::Rg8Snorm,
2667 TextureFormat::Rg8Uint,
2668 TextureFormat::Rg8Sint,
2669 TextureFormat::R32Uint,
2670 TextureFormat::R32Sint,
2671 TextureFormat::R32Float,
2672 TextureFormat::Rg16Uint,
2673 TextureFormat::Rg16Sint,
2674 TextureFormat::Rg16Unorm,
2675 TextureFormat::Rg16Snorm,
2676 TextureFormat::Rg16Float,
2677 TextureFormat::Rgba8Unorm,
2678 TextureFormat::Rgba8UnormSrgb,
2679 TextureFormat::Rgba8Snorm,
2680 TextureFormat::Rgba8Uint,
2681 TextureFormat::Rgba8Sint,
2682 TextureFormat::Bgra8Unorm,
2683 TextureFormat::Bgra8UnormSrgb,
2684 TextureFormat::Rgb9e5Ufloat,
2685 TextureFormat::Rgb10a2Uint,
2686 TextureFormat::Rgb10a2Unorm,
2687 TextureFormat::Rg11b10Ufloat,
2688 TextureFormat::R64Uint,
2689 TextureFormat::Rg32Uint,
2690 TextureFormat::Rg32Sint,
2691 TextureFormat::Rg32Float,
2692 TextureFormat::Rgba16Uint,
2693 TextureFormat::Rgba16Sint,
2694 TextureFormat::Rgba16Unorm,
2695 TextureFormat::Rgba16Snorm,
2696 TextureFormat::Rgba16Float,
2697 TextureFormat::Rgba32Uint,
2698 TextureFormat::Rgba32Sint,
2699 TextureFormat::Rgba32Float,
2700 TextureFormat::Bc1RgbaUnorm,
2701 TextureFormat::Bc1RgbaUnormSrgb,
2702 TextureFormat::Bc2RgbaUnorm,
2703 TextureFormat::Bc2RgbaUnormSrgb,
2704 TextureFormat::Bc3RgbaUnorm,
2705 TextureFormat::Bc3RgbaUnormSrgb,
2706 TextureFormat::Bc4RUnorm,
2707 TextureFormat::Bc4RSnorm,
2708 TextureFormat::Bc5RgUnorm,
2709 TextureFormat::Bc5RgSnorm,
2710 TextureFormat::Bc6hRgbUfloat,
2711 TextureFormat::Bc6hRgbFloat,
2712 TextureFormat::Bc7RgbaUnorm,
2713 TextureFormat::Bc7RgbaUnormSrgb,
2714 TextureFormat::Etc2Rgb8Unorm,
2715 TextureFormat::Etc2Rgb8UnormSrgb,
2716 TextureFormat::Etc2Rgb8A1Unorm,
2717 TextureFormat::Etc2Rgb8A1UnormSrgb,
2718 TextureFormat::Etc2Rgba8Unorm,
2719 TextureFormat::Etc2Rgba8UnormSrgb,
2720 TextureFormat::EacR11Unorm,
2721 TextureFormat::EacR11Snorm,
2722 TextureFormat::EacRg11Unorm,
2723 TextureFormat::EacRg11Snorm,
2724 ]);
2725
2726 for format in TextureFormat::exhaust() {
2727 if let TextureFormat::Astc { .. } = format {
2728 assert!(format.has_color_aspect(), "{:?} failed", format);
2730 } else if valid_formats.contains(&format) {
2731 assert!(format.has_color_aspect(), "{:?} failed", format);
2732 } else {
2733 assert!(!format.has_color_aspect(), "{:?} failed", format);
2734 }
2735 }
2736 }
2737
2738 #[test]
2740 fn has_depth_aspect() {
2741 let valid_formats: HashSet<TextureFormat> = HashSet::from([
2743 TextureFormat::Depth16Unorm,
2744 TextureFormat::Depth24Plus,
2745 TextureFormat::Depth24PlusStencil8,
2746 TextureFormat::Depth32Float,
2747 TextureFormat::Depth32FloatStencil8,
2748 ]);
2749
2750 for format in TextureFormat::exhaust() {
2751 if valid_formats.contains(&format) {
2752 assert!(format.has_depth_aspect());
2753 } else {
2754 assert!(!format.has_depth_aspect());
2755 }
2756 }
2757 }
2758
2759 #[test]
2761 fn has_stencil_aspect() {
2762 let valid_formats: HashSet<TextureFormat> = HashSet::from([
2764 TextureFormat::Stencil8,
2765 TextureFormat::Depth24PlusStencil8,
2766 TextureFormat::Depth32FloatStencil8,
2767 ]);
2768
2769 for format in TextureFormat::exhaust() {
2770 if valid_formats.contains(&format) {
2771 assert!(format.has_stencil_aspect());
2772 } else {
2773 assert!(!format.has_stencil_aspect());
2774 }
2775 }
2776 }
2777}