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))]
12pub enum AstcBlock {
13 B4x4,
15 B5x4,
17 B5x5,
19 B6x5,
21 B6x6,
23 B8x5,
25 B8x6,
27 B8x8,
29 B10x5,
31 B10x6,
33 B10x8,
35 B10x10,
37 B12x10,
39 B12x12,
41}
42
43#[repr(C)]
45#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
46#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
47pub enum AstcChannel {
48 Unorm,
52 UnormSrgb,
56 Hdr,
60}
61
62#[repr(C)]
85#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
86pub enum TextureFormat {
87 R8Unorm,
90 R8Snorm,
92 R8Uint,
94 R8Sint,
96
97 R16Uint,
100 R16Sint,
102 R16Unorm,
106 R16Snorm,
110 R16Float,
112 Rg8Unorm,
114 Rg8Snorm,
116 Rg8Uint,
118 Rg8Sint,
120
121 R32Uint,
124 R32Sint,
126 R32Float,
128 Rg16Uint,
130 Rg16Sint,
132 Rg16Unorm,
136 Rg16Snorm,
140 Rg16Float,
142 Rgba8Unorm,
144 Rgba8UnormSrgb,
146 Rgba8Snorm,
148 Rgba8Uint,
150 Rgba8Sint,
152 Bgra8Unorm,
154 Bgra8UnormSrgb,
156
157 Rgb9e5Ufloat,
160 Rgb10a2Uint,
162 Rgb10a2Unorm,
164 Rg11b10Ufloat,
166
167 R64Uint,
172 Rg32Uint,
174 Rg32Sint,
176 Rg32Float,
178 Rgba16Uint,
180 Rgba16Sint,
182 Rgba16Unorm,
186 Rgba16Snorm,
190 Rgba16Float,
192
193 Rgba32Uint,
196 Rgba32Sint,
198 Rgba32Float,
200
201 Stencil8,
204 Depth16Unorm,
206 Depth24Plus,
208 Depth24PlusStencil8,
210 Depth32Float,
212 Depth32FloatStencil8,
216
217 NV12,
231
232 P010,
248
249 Bc1RgbaUnorm,
258 Bc1RgbaUnormSrgb,
266 Bc2RgbaUnorm,
274 Bc2RgbaUnormSrgb,
282 Bc3RgbaUnorm,
290 Bc3RgbaUnormSrgb,
298 Bc4RUnorm,
306 Bc4RSnorm,
314 Bc5RgUnorm,
322 Bc5RgSnorm,
330 Bc6hRgbUfloat,
337 Bc6hRgbFloat,
344 Bc7RgbaUnorm,
352 Bc7RgbaUnormSrgb,
360 Etc2Rgb8Unorm,
365 Etc2Rgb8UnormSrgb,
370 Etc2Rgb8A1Unorm,
375 Etc2Rgb8A1UnormSrgb,
380 Etc2Rgba8Unorm,
385 Etc2Rgba8UnormSrgb,
390 EacR11Unorm,
395 EacR11Snorm,
400 EacRg11Unorm,
405 EacRg11Snorm,
410 Astc {
418 block: AstcBlock,
420 channel: AstcChannel,
422 },
423}
424
425impl TextureFormat {
428 #[must_use]
432 pub fn aspect_specific_format(&self, aspect: TextureAspect) -> Option<Self> {
433 match (*self, aspect) {
434 (Self::Stencil8, TextureAspect::StencilOnly) => Some(*self),
435 (
436 Self::Depth16Unorm | Self::Depth24Plus | Self::Depth32Float,
437 TextureAspect::DepthOnly,
438 ) => Some(*self),
439 (
440 Self::Depth24PlusStencil8 | Self::Depth32FloatStencil8,
441 TextureAspect::StencilOnly,
442 ) => Some(Self::Stencil8),
443 (Self::Depth24PlusStencil8, TextureAspect::DepthOnly) => Some(Self::Depth24Plus),
444 (Self::Depth32FloatStencil8, TextureAspect::DepthOnly) => Some(Self::Depth32Float),
445 (Self::NV12, TextureAspect::Plane0) => Some(Self::R8Unorm),
446 (Self::NV12, TextureAspect::Plane1) => Some(Self::Rg8Unorm),
447 (Self::P010, TextureAspect::Plane0) => Some(Self::R16Unorm),
448 (Self::P010, TextureAspect::Plane1) => Some(Self::Rg16Unorm),
449 (format, TextureAspect::All) if !format.is_multi_planar_format() => Some(format),
451 _ => None,
452 }
453 }
454
455 #[must_use]
458 pub fn is_depth_stencil_component(&self, combined_format: Self) -> bool {
459 match (combined_format, *self) {
460 (Self::Depth24PlusStencil8, Self::Depth24Plus | Self::Stencil8)
461 | (Self::Depth32FloatStencil8, Self::Depth32Float | Self::Stencil8) => true,
462 _ => false,
463 }
464 }
465
466 #[must_use]
470 pub fn is_depth_stencil_format(&self) -> bool {
471 match *self {
472 Self::Stencil8
473 | Self::Depth16Unorm
474 | Self::Depth24Plus
475 | Self::Depth24PlusStencil8
476 | Self::Depth32Float
477 | Self::Depth32FloatStencil8 => true,
478 _ => false,
479 }
480 }
481
482 #[must_use]
486 pub fn is_combined_depth_stencil_format(&self) -> bool {
487 match *self {
488 Self::Depth24PlusStencil8 | Self::Depth32FloatStencil8 => true,
489 _ => false,
490 }
491 }
492
493 #[must_use]
495 pub fn is_multi_planar_format(&self) -> bool {
496 self.planes().is_some()
497 }
498
499 #[must_use]
501 pub fn planes(&self) -> Option<u32> {
502 match *self {
503 Self::NV12 => Some(2),
504 Self::P010 => Some(2),
505 _ => None,
506 }
507 }
508
509 #[must_use]
511 pub fn subsampling_factors(&self, plane: Option<u32>) -> (u32, u32) {
512 match *self {
513 Self::NV12 | Self::P010 => match plane {
514 Some(0) => (1, 1),
515 Some(1) => (2, 2),
516 Some(plane) => unreachable!("plane {plane} is not valid for {self:?}"),
517 None => unreachable!("the plane must be specified for multi-planar formats"),
518 },
519 _ => (1, 1),
520 }
521 }
522
523 #[must_use]
525 pub fn has_color_aspect(&self) -> bool {
526 !self.is_depth_stencil_format()
527 }
528
529 #[must_use]
531 pub fn has_depth_aspect(&self) -> bool {
532 match *self {
533 Self::Depth16Unorm
534 | Self::Depth24Plus
535 | Self::Depth24PlusStencil8
536 | Self::Depth32Float
537 | Self::Depth32FloatStencil8 => true,
538 _ => false,
539 }
540 }
541
542 #[must_use]
544 pub fn has_stencil_aspect(&self) -> bool {
545 match *self {
546 Self::Stencil8 | Self::Depth24PlusStencil8 | Self::Depth32FloatStencil8 => true,
547 _ => false,
548 }
549 }
550
551 #[must_use]
557 pub fn size_multiple_requirement(&self) -> (u32, u32) {
558 match *self {
559 Self::NV12 => (2, 2),
560 Self::P010 => (2, 2),
561 _ => self.block_dimensions(),
562 }
563 }
564
565 #[must_use]
569 pub fn block_dimensions(&self) -> (u32, u32) {
570 match *self {
571 Self::R8Unorm
572 | Self::R8Snorm
573 | Self::R8Uint
574 | Self::R8Sint
575 | Self::R16Uint
576 | Self::R16Sint
577 | Self::R16Unorm
578 | Self::R16Snorm
579 | Self::R16Float
580 | Self::Rg8Unorm
581 | Self::Rg8Snorm
582 | Self::Rg8Uint
583 | Self::Rg8Sint
584 | Self::R32Uint
585 | Self::R32Sint
586 | Self::R32Float
587 | Self::Rg16Uint
588 | Self::Rg16Sint
589 | Self::Rg16Unorm
590 | Self::Rg16Snorm
591 | Self::Rg16Float
592 | Self::Rgba8Unorm
593 | Self::Rgba8UnormSrgb
594 | Self::Rgba8Snorm
595 | Self::Rgba8Uint
596 | Self::Rgba8Sint
597 | Self::Bgra8Unorm
598 | Self::Bgra8UnormSrgb
599 | Self::Rgb9e5Ufloat
600 | Self::Rgb10a2Uint
601 | Self::Rgb10a2Unorm
602 | Self::Rg11b10Ufloat
603 | Self::R64Uint
604 | Self::Rg32Uint
605 | Self::Rg32Sint
606 | Self::Rg32Float
607 | Self::Rgba16Uint
608 | Self::Rgba16Sint
609 | Self::Rgba16Unorm
610 | Self::Rgba16Snorm
611 | Self::Rgba16Float
612 | Self::Rgba32Uint
613 | Self::Rgba32Sint
614 | Self::Rgba32Float
615 | Self::Stencil8
616 | Self::Depth16Unorm
617 | Self::Depth24Plus
618 | Self::Depth24PlusStencil8
619 | Self::Depth32Float
620 | Self::Depth32FloatStencil8
621 | Self::NV12
622 | Self::P010 => (1, 1),
623
624 Self::Bc1RgbaUnorm
625 | Self::Bc1RgbaUnormSrgb
626 | Self::Bc2RgbaUnorm
627 | Self::Bc2RgbaUnormSrgb
628 | Self::Bc3RgbaUnorm
629 | Self::Bc3RgbaUnormSrgb
630 | Self::Bc4RUnorm
631 | Self::Bc4RSnorm
632 | Self::Bc5RgUnorm
633 | Self::Bc5RgSnorm
634 | Self::Bc6hRgbUfloat
635 | Self::Bc6hRgbFloat
636 | Self::Bc7RgbaUnorm
637 | Self::Bc7RgbaUnormSrgb => (4, 4),
638
639 Self::Etc2Rgb8Unorm
640 | Self::Etc2Rgb8UnormSrgb
641 | Self::Etc2Rgb8A1Unorm
642 | Self::Etc2Rgb8A1UnormSrgb
643 | Self::Etc2Rgba8Unorm
644 | Self::Etc2Rgba8UnormSrgb
645 | Self::EacR11Unorm
646 | Self::EacR11Snorm
647 | Self::EacRg11Unorm
648 | Self::EacRg11Snorm => (4, 4),
649
650 Self::Astc { block, .. } => match block {
651 AstcBlock::B4x4 => (4, 4),
652 AstcBlock::B5x4 => (5, 4),
653 AstcBlock::B5x5 => (5, 5),
654 AstcBlock::B6x5 => (6, 5),
655 AstcBlock::B6x6 => (6, 6),
656 AstcBlock::B8x5 => (8, 5),
657 AstcBlock::B8x6 => (8, 6),
658 AstcBlock::B8x8 => (8, 8),
659 AstcBlock::B10x5 => (10, 5),
660 AstcBlock::B10x6 => (10, 6),
661 AstcBlock::B10x8 => (10, 8),
662 AstcBlock::B10x10 => (10, 10),
663 AstcBlock::B12x10 => (12, 10),
664 AstcBlock::B12x12 => (12, 12),
665 },
666 }
667 }
668
669 #[must_use]
671 pub fn is_compressed(&self) -> bool {
672 self.block_dimensions() != (1, 1)
673 }
674
675 #[must_use]
677 pub fn is_bcn(&self) -> bool {
678 self.required_features() == Features::TEXTURE_COMPRESSION_BC
679 }
680
681 #[must_use]
683 pub fn is_astc(&self) -> bool {
684 self.required_features() == Features::TEXTURE_COMPRESSION_ASTC
685 || self.required_features() == Features::TEXTURE_COMPRESSION_ASTC_HDR
686 }
687
688 #[must_use]
690 pub fn required_features(&self) -> Features {
691 match *self {
692 Self::R8Unorm
693 | Self::R8Snorm
694 | Self::R8Uint
695 | Self::R8Sint
696 | Self::R16Uint
697 | Self::R16Sint
698 | Self::R16Float
699 | Self::Rg8Unorm
700 | Self::Rg8Snorm
701 | Self::Rg8Uint
702 | Self::Rg8Sint
703 | Self::R32Uint
704 | Self::R32Sint
705 | Self::R32Float
706 | Self::Rg16Uint
707 | Self::Rg16Sint
708 | Self::Rg16Float
709 | Self::Rgba8Unorm
710 | Self::Rgba8UnormSrgb
711 | Self::Rgba8Snorm
712 | Self::Rgba8Uint
713 | Self::Rgba8Sint
714 | Self::Bgra8Unorm
715 | Self::Bgra8UnormSrgb
716 | Self::Rgb9e5Ufloat
717 | Self::Rgb10a2Uint
718 | Self::Rgb10a2Unorm
719 | Self::Rg11b10Ufloat
720 | Self::Rg32Uint
721 | Self::Rg32Sint
722 | Self::Rg32Float
723 | Self::Rgba16Uint
724 | Self::Rgba16Sint
725 | Self::Rgba16Float
726 | Self::Rgba32Uint
727 | Self::Rgba32Sint
728 | Self::Rgba32Float
729 | Self::Stencil8
730 | Self::Depth16Unorm
731 | Self::Depth24Plus
732 | Self::Depth24PlusStencil8
733 | Self::Depth32Float => Features::empty(),
734
735 Self::R64Uint => Features::TEXTURE_INT64_ATOMIC,
736
737 Self::Depth32FloatStencil8 => Features::DEPTH32FLOAT_STENCIL8,
738
739 Self::NV12 => Features::TEXTURE_FORMAT_NV12,
740 Self::P010 => Features::TEXTURE_FORMAT_P010,
741
742 Self::R16Unorm
743 | Self::R16Snorm
744 | Self::Rg16Unorm
745 | Self::Rg16Snorm
746 | Self::Rgba16Unorm
747 | Self::Rgba16Snorm => Features::TEXTURE_FORMAT_16BIT_NORM,
748
749 Self::Bc1RgbaUnorm
750 | Self::Bc1RgbaUnormSrgb
751 | Self::Bc2RgbaUnorm
752 | Self::Bc2RgbaUnormSrgb
753 | Self::Bc3RgbaUnorm
754 | Self::Bc3RgbaUnormSrgb
755 | Self::Bc4RUnorm
756 | Self::Bc4RSnorm
757 | Self::Bc5RgUnorm
758 | Self::Bc5RgSnorm
759 | Self::Bc6hRgbUfloat
760 | Self::Bc6hRgbFloat
761 | Self::Bc7RgbaUnorm
762 | Self::Bc7RgbaUnormSrgb => Features::TEXTURE_COMPRESSION_BC,
763
764 Self::Etc2Rgb8Unorm
765 | Self::Etc2Rgb8UnormSrgb
766 | Self::Etc2Rgb8A1Unorm
767 | Self::Etc2Rgb8A1UnormSrgb
768 | Self::Etc2Rgba8Unorm
769 | Self::Etc2Rgba8UnormSrgb
770 | Self::EacR11Unorm
771 | Self::EacR11Snorm
772 | Self::EacRg11Unorm
773 | Self::EacRg11Snorm => Features::TEXTURE_COMPRESSION_ETC2,
774
775 Self::Astc { channel, .. } => match channel {
776 AstcChannel::Hdr => Features::TEXTURE_COMPRESSION_ASTC_HDR,
777 AstcChannel::Unorm | AstcChannel::UnormSrgb => Features::TEXTURE_COMPRESSION_ASTC,
778 },
779 }
780 }
781
782 #[must_use]
786 pub fn guaranteed_format_features(&self, device_features: Features) -> TextureFormatFeatures {
787 let none = TextureFormatFeatureFlags::empty();
789 let msaa = TextureFormatFeatureFlags::MULTISAMPLE_X4;
790 let msaa_resolve = msaa | TextureFormatFeatureFlags::MULTISAMPLE_RESOLVE;
791
792 let s_ro_wo = TextureFormatFeatureFlags::STORAGE_READ_ONLY
793 | TextureFormatFeatureFlags::STORAGE_WRITE_ONLY;
794 let s_all = s_ro_wo | TextureFormatFeatureFlags::STORAGE_READ_WRITE;
795
796 let basic =
798 TextureUsages::COPY_SRC | TextureUsages::COPY_DST | TextureUsages::TEXTURE_BINDING;
799 let attachment = basic | TextureUsages::RENDER_ATTACHMENT | TextureUsages::TRANSIENT;
800 let storage = basic | TextureUsages::STORAGE_BINDING;
801 let binding = TextureUsages::TEXTURE_BINDING;
802 let all_flags = attachment | storage | binding;
803 let atomic_64 = if device_features.contains(Features::TEXTURE_ATOMIC) {
804 storage | binding | TextureUsages::STORAGE_ATOMIC
805 } else {
806 storage | binding
807 };
808 let atomic = attachment | atomic_64;
809 let (rg11b10f_f, rg11b10f_u) =
810 if device_features.contains(Features::RG11B10UFLOAT_RENDERABLE) {
811 (msaa_resolve, attachment)
812 } else {
813 (msaa, basic)
814 };
815 let (bgra8unorm_f, bgra8unorm) = if device_features.contains(Features::BGRA8UNORM_STORAGE) {
816 (
817 msaa_resolve | TextureFormatFeatureFlags::STORAGE_WRITE_ONLY,
818 attachment | TextureUsages::STORAGE_BINDING,
819 )
820 } else {
821 (msaa_resolve, attachment)
822 };
823
824 #[rustfmt::skip] let (
826 mut flags,
827 allowed_usages,
828 ) = match *self {
829 Self::R8Unorm => (msaa_resolve, attachment),
830 Self::R8Snorm => ( none, basic),
831 Self::R8Uint => ( msaa, attachment),
832 Self::R8Sint => ( msaa, attachment),
833 Self::R16Uint => ( msaa, attachment),
834 Self::R16Sint => ( msaa, attachment),
835 Self::R16Float => (msaa_resolve, attachment),
836 Self::Rg8Unorm => (msaa_resolve, attachment),
837 Self::Rg8Snorm => ( none, basic),
838 Self::Rg8Uint => ( msaa, attachment),
839 Self::Rg8Sint => ( msaa, attachment),
840 Self::R32Uint => ( s_all, atomic),
841 Self::R32Sint => ( s_all, atomic),
842 Self::R32Float => (msaa | s_all, all_flags),
843 Self::Rg16Uint => ( msaa, attachment),
844 Self::Rg16Sint => ( msaa, attachment),
845 Self::Rg16Float => (msaa_resolve, attachment),
846 Self::Rgba8Unorm => (msaa_resolve | s_ro_wo, all_flags),
847 Self::Rgba8UnormSrgb => (msaa_resolve, attachment),
848 Self::Rgba8Snorm => ( s_ro_wo, storage),
849 Self::Rgba8Uint => ( msaa | s_ro_wo, all_flags),
850 Self::Rgba8Sint => ( msaa | s_ro_wo, all_flags),
851 Self::Bgra8Unorm => (bgra8unorm_f, bgra8unorm),
852 Self::Bgra8UnormSrgb => (msaa_resolve, attachment),
853 Self::Rgb10a2Uint => ( msaa, attachment),
854 Self::Rgb10a2Unorm => (msaa_resolve, attachment),
855 Self::Rg11b10Ufloat => ( rg11b10f_f, rg11b10f_u),
856 Self::R64Uint => ( s_ro_wo, atomic_64),
857 Self::Rg32Uint => ( s_ro_wo, all_flags),
858 Self::Rg32Sint => ( s_ro_wo, all_flags),
859 Self::Rg32Float => ( s_ro_wo, all_flags),
860 Self::Rgba16Uint => ( msaa | s_ro_wo, all_flags),
861 Self::Rgba16Sint => ( msaa | s_ro_wo, all_flags),
862 Self::Rgba16Float => (msaa_resolve | s_ro_wo, all_flags),
863 Self::Rgba32Uint => ( s_ro_wo, all_flags),
864 Self::Rgba32Sint => ( s_ro_wo, all_flags),
865 Self::Rgba32Float => ( s_ro_wo, all_flags),
866
867 Self::Stencil8 => ( msaa, attachment),
868 Self::Depth16Unorm => ( msaa, attachment),
869 Self::Depth24Plus => ( msaa, attachment),
870 Self::Depth24PlusStencil8 => ( msaa, attachment),
871 Self::Depth32Float => ( msaa, attachment),
872 Self::Depth32FloatStencil8 => ( msaa, attachment),
873
874 Self::NV12 => ( none, binding),
877 Self::P010 => ( none, binding),
878
879 Self::R16Unorm => ( msaa | s_ro_wo, storage),
880 Self::R16Snorm => ( msaa | s_ro_wo, storage),
881 Self::Rg16Unorm => ( msaa | s_ro_wo, storage),
882 Self::Rg16Snorm => ( msaa | s_ro_wo, storage),
883 Self::Rgba16Unorm => ( msaa | s_ro_wo, storage),
884 Self::Rgba16Snorm => ( msaa | s_ro_wo, storage),
885
886 Self::Rgb9e5Ufloat => ( none, basic),
887
888 Self::Bc1RgbaUnorm => ( none, basic),
889 Self::Bc1RgbaUnormSrgb => ( none, basic),
890 Self::Bc2RgbaUnorm => ( none, basic),
891 Self::Bc2RgbaUnormSrgb => ( none, basic),
892 Self::Bc3RgbaUnorm => ( none, basic),
893 Self::Bc3RgbaUnormSrgb => ( none, basic),
894 Self::Bc4RUnorm => ( none, basic),
895 Self::Bc4RSnorm => ( none, basic),
896 Self::Bc5RgUnorm => ( none, basic),
897 Self::Bc5RgSnorm => ( none, basic),
898 Self::Bc6hRgbUfloat => ( none, basic),
899 Self::Bc6hRgbFloat => ( none, basic),
900 Self::Bc7RgbaUnorm => ( none, basic),
901 Self::Bc7RgbaUnormSrgb => ( none, basic),
902
903 Self::Etc2Rgb8Unorm => ( none, basic),
904 Self::Etc2Rgb8UnormSrgb => ( none, basic),
905 Self::Etc2Rgb8A1Unorm => ( none, basic),
906 Self::Etc2Rgb8A1UnormSrgb => ( none, basic),
907 Self::Etc2Rgba8Unorm => ( none, basic),
908 Self::Etc2Rgba8UnormSrgb => ( none, basic),
909 Self::EacR11Unorm => ( none, basic),
910 Self::EacR11Snorm => ( none, basic),
911 Self::EacRg11Unorm => ( none, basic),
912 Self::EacRg11Snorm => ( none, basic),
913
914 Self::Astc { .. } => ( none, basic),
915 };
916
917 let sample_type1 = self.sample_type(None, Some(device_features));
919 let is_filterable = sample_type1 == Some(TextureSampleType::Float { filterable: true });
920
921 let sample_type2 = self.sample_type(None, None);
923 let is_blendable = sample_type2 == Some(TextureSampleType::Float { filterable: true })
924 || device_features.contains(Features::FLOAT32_BLENDABLE)
925 && matches!(self, Self::R32Float | Self::Rg32Float | Self::Rgba32Float);
926
927 flags.set(TextureFormatFeatureFlags::FILTERABLE, is_filterable);
928 flags.set(TextureFormatFeatureFlags::BLENDABLE, is_blendable);
929 flags.set(
930 TextureFormatFeatureFlags::STORAGE_ATOMIC,
931 allowed_usages.contains(TextureUsages::STORAGE_ATOMIC),
932 );
933
934 TextureFormatFeatures {
935 allowed_usages,
936 flags,
937 }
938 }
939
940 #[must_use]
945 pub fn sample_type(
946 &self,
947 aspect: Option<TextureAspect>,
948 device_features: Option<Features>,
949 ) -> Option<TextureSampleType> {
950 let float = TextureSampleType::Float { filterable: true };
951 let unfilterable_float = TextureSampleType::Float { filterable: false };
952 let float32_sample_type = TextureSampleType::Float {
953 filterable: device_features
954 .unwrap_or(Features::empty())
955 .contains(Features::FLOAT32_FILTERABLE),
956 };
957 let depth = TextureSampleType::Depth;
958 let uint = TextureSampleType::Uint;
959 let sint = TextureSampleType::Sint;
960
961 match *self {
962 Self::R8Unorm
963 | Self::R8Snorm
964 | Self::Rg8Unorm
965 | Self::Rg8Snorm
966 | Self::Rgba8Unorm
967 | Self::Rgba8UnormSrgb
968 | Self::Rgba8Snorm
969 | Self::Bgra8Unorm
970 | Self::Bgra8UnormSrgb
971 | Self::R16Float
972 | Self::Rg16Float
973 | Self::Rgba16Float
974 | Self::Rgb10a2Unorm
975 | Self::Rg11b10Ufloat => Some(float),
976
977 Self::R32Float | Self::Rg32Float | Self::Rgba32Float => Some(float32_sample_type),
978
979 Self::R8Uint
980 | Self::Rg8Uint
981 | Self::Rgba8Uint
982 | Self::R16Uint
983 | Self::Rg16Uint
984 | Self::Rgba16Uint
985 | Self::R32Uint
986 | Self::R64Uint
987 | Self::Rg32Uint
988 | Self::Rgba32Uint
989 | Self::Rgb10a2Uint => Some(uint),
990
991 Self::R8Sint
992 | Self::Rg8Sint
993 | Self::Rgba8Sint
994 | Self::R16Sint
995 | Self::Rg16Sint
996 | Self::Rgba16Sint
997 | Self::R32Sint
998 | Self::Rg32Sint
999 | Self::Rgba32Sint => Some(sint),
1000
1001 Self::Stencil8 => Some(uint),
1002 Self::Depth16Unorm | Self::Depth24Plus | Self::Depth32Float => Some(depth),
1003 Self::Depth24PlusStencil8 | Self::Depth32FloatStencil8 => match aspect {
1004 Some(TextureAspect::DepthOnly) => Some(depth),
1005 Some(TextureAspect::StencilOnly) => Some(uint),
1006 _ => None,
1007 },
1008
1009 Self::NV12 | Self::P010 => match aspect {
1010 Some(TextureAspect::Plane0) | Some(TextureAspect::Plane1) => {
1011 Some(unfilterable_float)
1012 }
1013 _ => None,
1014 },
1015
1016 Self::R16Unorm
1017 | Self::R16Snorm
1018 | Self::Rg16Unorm
1019 | Self::Rg16Snorm
1020 | Self::Rgba16Unorm
1021 | Self::Rgba16Snorm => Some(float),
1022
1023 Self::Rgb9e5Ufloat => Some(float),
1024
1025 Self::Bc1RgbaUnorm
1026 | Self::Bc1RgbaUnormSrgb
1027 | Self::Bc2RgbaUnorm
1028 | Self::Bc2RgbaUnormSrgb
1029 | Self::Bc3RgbaUnorm
1030 | Self::Bc3RgbaUnormSrgb
1031 | Self::Bc4RUnorm
1032 | Self::Bc4RSnorm
1033 | Self::Bc5RgUnorm
1034 | Self::Bc5RgSnorm
1035 | Self::Bc6hRgbUfloat
1036 | Self::Bc6hRgbFloat
1037 | Self::Bc7RgbaUnorm
1038 | Self::Bc7RgbaUnormSrgb => Some(float),
1039
1040 Self::Etc2Rgb8Unorm
1041 | Self::Etc2Rgb8UnormSrgb
1042 | Self::Etc2Rgb8A1Unorm
1043 | Self::Etc2Rgb8A1UnormSrgb
1044 | Self::Etc2Rgba8Unorm
1045 | Self::Etc2Rgba8UnormSrgb
1046 | Self::EacR11Unorm
1047 | Self::EacR11Snorm
1048 | Self::EacRg11Unorm
1049 | Self::EacRg11Snorm => Some(float),
1050
1051 Self::Astc { .. } => Some(float),
1052 }
1053 }
1054
1055 #[deprecated(since = "0.19.0", note = "Use `block_copy_size` instead.")]
1068 #[must_use]
1069 pub fn block_size(&self, aspect: Option<TextureAspect>) -> Option<u32> {
1070 self.block_copy_size(aspect)
1071 }
1072
1073 #[must_use]
1086 pub fn block_copy_size(&self, aspect: Option<TextureAspect>) -> Option<u32> {
1087 match *self {
1088 Self::R8Unorm | Self::R8Snorm | Self::R8Uint | Self::R8Sint => Some(1),
1089
1090 Self::Rg8Unorm | Self::Rg8Snorm | Self::Rg8Uint | Self::Rg8Sint => Some(2),
1091 Self::R16Unorm | Self::R16Snorm | Self::R16Uint | Self::R16Sint | Self::R16Float => {
1092 Some(2)
1093 }
1094
1095 Self::Rgba8Unorm
1096 | Self::Rgba8UnormSrgb
1097 | Self::Rgba8Snorm
1098 | Self::Rgba8Uint
1099 | Self::Rgba8Sint
1100 | Self::Bgra8Unorm
1101 | Self::Bgra8UnormSrgb => Some(4),
1102 Self::Rg16Unorm
1103 | Self::Rg16Snorm
1104 | Self::Rg16Uint
1105 | Self::Rg16Sint
1106 | Self::Rg16Float => Some(4),
1107 Self::R32Uint | Self::R32Sint | Self::R32Float => Some(4),
1108 Self::Rgb9e5Ufloat | Self::Rgb10a2Uint | Self::Rgb10a2Unorm | Self::Rg11b10Ufloat => {
1109 Some(4)
1110 }
1111
1112 Self::Rgba16Unorm
1113 | Self::Rgba16Snorm
1114 | Self::Rgba16Uint
1115 | Self::Rgba16Sint
1116 | Self::Rgba16Float => Some(8),
1117 Self::R64Uint | Self::Rg32Uint | Self::Rg32Sint | Self::Rg32Float => Some(8),
1118
1119 Self::Rgba32Uint | Self::Rgba32Sint | Self::Rgba32Float => Some(16),
1120
1121 Self::Stencil8 => Some(1),
1122 Self::Depth16Unorm => Some(2),
1123 Self::Depth32Float => Some(4),
1124 Self::Depth24Plus => None,
1125 Self::Depth24PlusStencil8 => match aspect {
1126 Some(TextureAspect::DepthOnly) => None,
1127 Some(TextureAspect::StencilOnly) => Some(1),
1128 _ => None,
1129 },
1130 Self::Depth32FloatStencil8 => match aspect {
1131 Some(TextureAspect::DepthOnly) => Some(4),
1132 Some(TextureAspect::StencilOnly) => Some(1),
1133 _ => None,
1134 },
1135
1136 Self::NV12 => match aspect {
1137 Some(TextureAspect::Plane0) => Some(1),
1138 Some(TextureAspect::Plane1) => Some(2),
1139 _ => None,
1140 },
1141
1142 Self::P010 => match aspect {
1143 Some(TextureAspect::Plane0) => Some(2),
1144 Some(TextureAspect::Plane1) => Some(4),
1145 _ => None,
1146 },
1147
1148 Self::Bc1RgbaUnorm | Self::Bc1RgbaUnormSrgb | Self::Bc4RUnorm | Self::Bc4RSnorm => {
1149 Some(8)
1150 }
1151 Self::Bc2RgbaUnorm
1152 | Self::Bc2RgbaUnormSrgb
1153 | Self::Bc3RgbaUnorm
1154 | Self::Bc3RgbaUnormSrgb
1155 | Self::Bc5RgUnorm
1156 | Self::Bc5RgSnorm
1157 | Self::Bc6hRgbUfloat
1158 | Self::Bc6hRgbFloat
1159 | Self::Bc7RgbaUnorm
1160 | Self::Bc7RgbaUnormSrgb => Some(16),
1161
1162 Self::Etc2Rgb8Unorm
1163 | Self::Etc2Rgb8UnormSrgb
1164 | Self::Etc2Rgb8A1Unorm
1165 | Self::Etc2Rgb8A1UnormSrgb
1166 | Self::EacR11Unorm
1167 | Self::EacR11Snorm => Some(8),
1168 Self::Etc2Rgba8Unorm
1169 | Self::Etc2Rgba8UnormSrgb
1170 | Self::EacRg11Unorm
1171 | Self::EacRg11Snorm => Some(16),
1172
1173 Self::Astc { .. } => Some(16),
1174 }
1175 }
1176
1177 pub const MAX_TARGET_PIXEL_BYTE_COST: u32 = 16;
1179
1180 #[must_use]
1183 pub fn target_pixel_byte_cost(&self) -> Option<u32> {
1184 match *self {
1185 Self::R8Unorm | Self::R8Snorm | Self::R8Uint | Self::R8Sint => Some(1),
1186 Self::Rg8Unorm
1187 | Self::Rg8Snorm
1188 | Self::Rg8Uint
1189 | Self::Rg8Sint
1190 | Self::R16Uint
1191 | Self::R16Sint
1192 | Self::R16Unorm
1193 | Self::R16Snorm
1194 | Self::R16Float => Some(2),
1195 Self::Rgba8Uint
1196 | Self::Rgba8Sint
1197 | Self::Rg16Uint
1198 | Self::Rg16Sint
1199 | Self::Rg16Unorm
1200 | Self::Rg16Snorm
1201 | Self::Rg16Float
1202 | Self::R32Uint
1203 | Self::R32Sint
1204 | Self::R32Float => Some(4),
1205 Self::Rgba8Unorm
1207 | Self::Rgba8UnormSrgb
1208 | Self::Rgba8Snorm
1209 | Self::Bgra8Unorm
1210 | Self::Bgra8UnormSrgb
1211 | Self::Rgba16Uint
1213 | Self::Rgba16Sint
1214 | Self::Rgba16Unorm
1215 | Self::Rgba16Snorm
1216 | Self::Rgba16Float
1217 | Self::R64Uint
1218 | Self::Rg32Uint
1219 | Self::Rg32Sint
1220 | Self::Rg32Float
1221 | Self::Rgb10a2Uint
1222 | Self::Rgb10a2Unorm
1223 | Self::Rg11b10Ufloat => Some(8),
1224 Self::Rgba32Uint | Self::Rgba32Sint | Self::Rgba32Float => Some(16),
1225 Self::Stencil8
1227 | Self::Depth16Unorm
1228 | Self::Depth24Plus
1229 | Self::Depth24PlusStencil8
1230 | Self::Depth32Float
1231 | Self::Depth32FloatStencil8
1232 | Self::NV12
1233 | Self::P010
1234 | Self::Rgb9e5Ufloat
1235 | Self::Bc1RgbaUnorm
1236 | Self::Bc1RgbaUnormSrgb
1237 | Self::Bc2RgbaUnorm
1238 | Self::Bc2RgbaUnormSrgb
1239 | Self::Bc3RgbaUnorm
1240 | Self::Bc3RgbaUnormSrgb
1241 | Self::Bc4RUnorm
1242 | Self::Bc4RSnorm
1243 | Self::Bc5RgUnorm
1244 | Self::Bc5RgSnorm
1245 | Self::Bc6hRgbUfloat
1246 | Self::Bc6hRgbFloat
1247 | Self::Bc7RgbaUnorm
1248 | Self::Bc7RgbaUnormSrgb
1249 | Self::Etc2Rgb8Unorm
1250 | Self::Etc2Rgb8UnormSrgb
1251 | Self::Etc2Rgb8A1Unorm
1252 | Self::Etc2Rgb8A1UnormSrgb
1253 | Self::Etc2Rgba8Unorm
1254 | Self::Etc2Rgba8UnormSrgb
1255 | Self::EacR11Unorm
1256 | Self::EacR11Snorm
1257 | Self::EacRg11Unorm
1258 | Self::EacRg11Snorm
1259 | Self::Astc { .. } => None,
1260 }
1261 }
1262
1263 #[must_use]
1265 pub fn target_component_alignment(&self) -> Option<u32> {
1266 match *self {
1267 Self::R8Unorm
1268 | Self::R8Snorm
1269 | Self::R8Uint
1270 | Self::R8Sint
1271 | Self::Rg8Unorm
1272 | Self::Rg8Snorm
1273 | Self::Rg8Uint
1274 | Self::Rg8Sint
1275 | Self::Rgba8Unorm
1276 | Self::Rgba8UnormSrgb
1277 | Self::Rgba8Snorm
1278 | Self::Rgba8Uint
1279 | Self::Rgba8Sint
1280 | Self::Bgra8Unorm
1281 | Self::Bgra8UnormSrgb => Some(1),
1282 Self::R16Uint
1283 | Self::R16Sint
1284 | Self::R16Unorm
1285 | Self::R16Snorm
1286 | Self::R16Float
1287 | Self::Rg16Uint
1288 | Self::Rg16Sint
1289 | Self::Rg16Unorm
1290 | Self::Rg16Snorm
1291 | Self::Rg16Float
1292 | Self::Rgba16Uint
1293 | Self::Rgba16Sint
1294 | Self::Rgba16Unorm
1295 | Self::Rgba16Snorm
1296 | Self::Rgba16Float => Some(2),
1297 Self::R32Uint
1298 | Self::R32Sint
1299 | Self::R32Float
1300 | Self::R64Uint
1301 | Self::Rg32Uint
1302 | Self::Rg32Sint
1303 | Self::Rg32Float
1304 | Self::Rgba32Uint
1305 | Self::Rgba32Sint
1306 | Self::Rgba32Float
1307 | Self::Rgb10a2Uint
1308 | Self::Rgb10a2Unorm
1309 | Self::Rg11b10Ufloat => Some(4),
1310 Self::Stencil8
1311 | Self::Depth16Unorm
1312 | Self::Depth24Plus
1313 | Self::Depth24PlusStencil8
1314 | Self::Depth32Float
1315 | Self::Depth32FloatStencil8
1316 | Self::NV12
1317 | Self::P010
1318 | Self::Rgb9e5Ufloat
1319 | Self::Bc1RgbaUnorm
1320 | Self::Bc1RgbaUnormSrgb
1321 | Self::Bc2RgbaUnorm
1322 | Self::Bc2RgbaUnormSrgb
1323 | Self::Bc3RgbaUnorm
1324 | Self::Bc3RgbaUnormSrgb
1325 | Self::Bc4RUnorm
1326 | Self::Bc4RSnorm
1327 | Self::Bc5RgUnorm
1328 | Self::Bc5RgSnorm
1329 | Self::Bc6hRgbUfloat
1330 | Self::Bc6hRgbFloat
1331 | Self::Bc7RgbaUnorm
1332 | Self::Bc7RgbaUnormSrgb
1333 | Self::Etc2Rgb8Unorm
1334 | Self::Etc2Rgb8UnormSrgb
1335 | Self::Etc2Rgb8A1Unorm
1336 | Self::Etc2Rgb8A1UnormSrgb
1337 | Self::Etc2Rgba8Unorm
1338 | Self::Etc2Rgba8UnormSrgb
1339 | Self::EacR11Unorm
1340 | Self::EacR11Snorm
1341 | Self::EacRg11Unorm
1342 | Self::EacRg11Snorm
1343 | Self::Astc { .. } => None,
1344 }
1345 }
1346
1347 #[must_use]
1349 pub fn components(&self) -> u8 {
1350 self.components_with_aspect(TextureAspect::All)
1351 }
1352
1353 #[must_use]
1357 pub fn components_with_aspect(&self, aspect: TextureAspect) -> u8 {
1358 match *self {
1359 Self::R8Unorm
1360 | Self::R8Snorm
1361 | Self::R8Uint
1362 | Self::R8Sint
1363 | Self::R16Unorm
1364 | Self::R16Snorm
1365 | Self::R16Uint
1366 | Self::R16Sint
1367 | Self::R16Float
1368 | Self::R32Uint
1369 | Self::R32Sint
1370 | Self::R32Float
1371 | Self::R64Uint => 1,
1372
1373 Self::Rg8Unorm
1374 | Self::Rg8Snorm
1375 | Self::Rg8Uint
1376 | Self::Rg8Sint
1377 | Self::Rg16Unorm
1378 | Self::Rg16Snorm
1379 | Self::Rg16Uint
1380 | Self::Rg16Sint
1381 | Self::Rg16Float
1382 | Self::Rg32Uint
1383 | Self::Rg32Sint
1384 | Self::Rg32Float => 2,
1385
1386 Self::Rgba8Unorm
1387 | Self::Rgba8UnormSrgb
1388 | Self::Rgba8Snorm
1389 | Self::Rgba8Uint
1390 | Self::Rgba8Sint
1391 | Self::Bgra8Unorm
1392 | Self::Bgra8UnormSrgb
1393 | Self::Rgba16Unorm
1394 | Self::Rgba16Snorm
1395 | Self::Rgba16Uint
1396 | Self::Rgba16Sint
1397 | Self::Rgba16Float
1398 | Self::Rgba32Uint
1399 | Self::Rgba32Sint
1400 | Self::Rgba32Float => 4,
1401
1402 Self::Rgb9e5Ufloat | Self::Rg11b10Ufloat => 3,
1403 Self::Rgb10a2Uint | Self::Rgb10a2Unorm => 4,
1404
1405 Self::Stencil8 | Self::Depth16Unorm | Self::Depth24Plus | Self::Depth32Float => 1,
1406
1407 Self::Depth24PlusStencil8 | Self::Depth32FloatStencil8 => match aspect {
1408 TextureAspect::DepthOnly | TextureAspect::StencilOnly => 1,
1409 _ => 2,
1410 },
1411
1412 Self::NV12 | Self::P010 => match aspect {
1413 TextureAspect::Plane0 => 1,
1414 TextureAspect::Plane1 => 2,
1415 _ => 3,
1416 },
1417
1418 Self::Bc4RUnorm | Self::Bc4RSnorm => 1,
1419 Self::Bc5RgUnorm | Self::Bc5RgSnorm => 2,
1420 Self::Bc6hRgbUfloat | Self::Bc6hRgbFloat => 3,
1421 Self::Bc1RgbaUnorm
1422 | Self::Bc1RgbaUnormSrgb
1423 | Self::Bc2RgbaUnorm
1424 | Self::Bc2RgbaUnormSrgb
1425 | Self::Bc3RgbaUnorm
1426 | Self::Bc3RgbaUnormSrgb
1427 | Self::Bc7RgbaUnorm
1428 | Self::Bc7RgbaUnormSrgb => 4,
1429
1430 Self::EacR11Unorm | Self::EacR11Snorm => 1,
1431 Self::EacRg11Unorm | Self::EacRg11Snorm => 2,
1432 Self::Etc2Rgb8Unorm | Self::Etc2Rgb8UnormSrgb => 3,
1433 Self::Etc2Rgb8A1Unorm
1434 | Self::Etc2Rgb8A1UnormSrgb
1435 | Self::Etc2Rgba8Unorm
1436 | Self::Etc2Rgba8UnormSrgb => 4,
1437
1438 Self::Astc { .. } => 4,
1439 }
1440 }
1441
1442 #[must_use]
1444 pub fn remove_srgb_suffix(&self) -> TextureFormat {
1445 match *self {
1446 Self::Rgba8UnormSrgb => Self::Rgba8Unorm,
1447 Self::Bgra8UnormSrgb => Self::Bgra8Unorm,
1448 Self::Bc1RgbaUnormSrgb => Self::Bc1RgbaUnorm,
1449 Self::Bc2RgbaUnormSrgb => Self::Bc2RgbaUnorm,
1450 Self::Bc3RgbaUnormSrgb => Self::Bc3RgbaUnorm,
1451 Self::Bc7RgbaUnormSrgb => Self::Bc7RgbaUnorm,
1452 Self::Etc2Rgb8UnormSrgb => Self::Etc2Rgb8Unorm,
1453 Self::Etc2Rgb8A1UnormSrgb => Self::Etc2Rgb8A1Unorm,
1454 Self::Etc2Rgba8UnormSrgb => Self::Etc2Rgba8Unorm,
1455 Self::Astc {
1456 block,
1457 channel: AstcChannel::UnormSrgb,
1458 } => Self::Astc {
1459 block,
1460 channel: AstcChannel::Unorm,
1461 },
1462 _ => *self,
1463 }
1464 }
1465
1466 #[must_use]
1468 pub fn add_srgb_suffix(&self) -> TextureFormat {
1469 match *self {
1470 Self::Rgba8Unorm => Self::Rgba8UnormSrgb,
1471 Self::Bgra8Unorm => Self::Bgra8UnormSrgb,
1472 Self::Bc1RgbaUnorm => Self::Bc1RgbaUnormSrgb,
1473 Self::Bc2RgbaUnorm => Self::Bc2RgbaUnormSrgb,
1474 Self::Bc3RgbaUnorm => Self::Bc3RgbaUnormSrgb,
1475 Self::Bc7RgbaUnorm => Self::Bc7RgbaUnormSrgb,
1476 Self::Etc2Rgb8Unorm => Self::Etc2Rgb8UnormSrgb,
1477 Self::Etc2Rgb8A1Unorm => Self::Etc2Rgb8A1UnormSrgb,
1478 Self::Etc2Rgba8Unorm => Self::Etc2Rgba8UnormSrgb,
1479 Self::Astc {
1480 block,
1481 channel: AstcChannel::Unorm,
1482 } => Self::Astc {
1483 block,
1484 channel: AstcChannel::UnormSrgb,
1485 },
1486 _ => *self,
1487 }
1488 }
1489
1490 #[must_use]
1492 pub fn is_srgb(&self) -> bool {
1493 *self != self.remove_srgb_suffix()
1494 }
1495
1496 #[must_use]
1500 pub fn theoretical_memory_footprint(&self, size: crate::Extent3d) -> u64 {
1501 let (block_width, block_height) = self.block_dimensions();
1502
1503 let block_size = self.block_copy_size(None);
1504
1505 let approximate_block_size = match block_size {
1506 Some(size) => size,
1507 None => match self {
1508 Self::Depth16Unorm => 2,
1510 Self::Depth24Plus => 4,
1512 Self::Depth24PlusStencil8 => 4,
1514 Self::Depth32Float => 4,
1516 Self::Depth32FloatStencil8 => 8,
1518 Self::Stencil8 => 1,
1520 Self::NV12 => 3,
1522 Self::P010 => 6,
1524 f => {
1525 unimplemented!("Memory footprint for format {f:?} is not implemented");
1526 }
1527 },
1528 };
1529
1530 let width_blocks = size.width.div_ceil(block_width) as u64;
1531 let height_blocks = size.height.div_ceil(block_height) as u64;
1532
1533 let total_blocks = width_blocks * height_blocks * size.depth_or_array_layers as u64;
1534
1535 total_blocks * approximate_block_size as u64
1536 }
1537}
1538
1539#[cfg(any(feature = "serde", test))]
1540impl<'de> Deserialize<'de> for TextureFormat {
1541 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1542 where
1543 D: serde::Deserializer<'de>,
1544 {
1545 use serde::de::{self, Error, Unexpected};
1546
1547 struct TextureFormatVisitor;
1548
1549 impl de::Visitor<'_> for TextureFormatVisitor {
1550 type Value = TextureFormat;
1551
1552 fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
1553 formatter.write_str("a valid texture format")
1554 }
1555
1556 fn visit_str<E: Error>(self, s: &str) -> Result<Self::Value, E> {
1557 let format = match s {
1558 "r8unorm" => TextureFormat::R8Unorm,
1559 "r8snorm" => TextureFormat::R8Snorm,
1560 "r8uint" => TextureFormat::R8Uint,
1561 "r8sint" => TextureFormat::R8Sint,
1562 "r16uint" => TextureFormat::R16Uint,
1563 "r16sint" => TextureFormat::R16Sint,
1564 "r16unorm" => TextureFormat::R16Unorm,
1565 "r16snorm" => TextureFormat::R16Snorm,
1566 "r16float" => TextureFormat::R16Float,
1567 "rg8unorm" => TextureFormat::Rg8Unorm,
1568 "rg8snorm" => TextureFormat::Rg8Snorm,
1569 "rg8uint" => TextureFormat::Rg8Uint,
1570 "rg8sint" => TextureFormat::Rg8Sint,
1571 "r32uint" => TextureFormat::R32Uint,
1572 "r32sint" => TextureFormat::R32Sint,
1573 "r32float" => TextureFormat::R32Float,
1574 "rg16uint" => TextureFormat::Rg16Uint,
1575 "rg16sint" => TextureFormat::Rg16Sint,
1576 "rg16unorm" => TextureFormat::Rg16Unorm,
1577 "rg16snorm" => TextureFormat::Rg16Snorm,
1578 "rg16float" => TextureFormat::Rg16Float,
1579 "rgba8unorm" => TextureFormat::Rgba8Unorm,
1580 "rgba8unorm-srgb" => TextureFormat::Rgba8UnormSrgb,
1581 "rgba8snorm" => TextureFormat::Rgba8Snorm,
1582 "rgba8uint" => TextureFormat::Rgba8Uint,
1583 "rgba8sint" => TextureFormat::Rgba8Sint,
1584 "bgra8unorm" => TextureFormat::Bgra8Unorm,
1585 "bgra8unorm-srgb" => TextureFormat::Bgra8UnormSrgb,
1586 "rgb10a2uint" => TextureFormat::Rgb10a2Uint,
1587 "rgb10a2unorm" => TextureFormat::Rgb10a2Unorm,
1588 "rg11b10ufloat" => TextureFormat::Rg11b10Ufloat,
1589 "r64uint" => TextureFormat::R64Uint,
1590 "rg32uint" => TextureFormat::Rg32Uint,
1591 "rg32sint" => TextureFormat::Rg32Sint,
1592 "rg32float" => TextureFormat::Rg32Float,
1593 "rgba16uint" => TextureFormat::Rgba16Uint,
1594 "rgba16sint" => TextureFormat::Rgba16Sint,
1595 "rgba16unorm" => TextureFormat::Rgba16Unorm,
1596 "rgba16snorm" => TextureFormat::Rgba16Snorm,
1597 "rgba16float" => TextureFormat::Rgba16Float,
1598 "rgba32uint" => TextureFormat::Rgba32Uint,
1599 "rgba32sint" => TextureFormat::Rgba32Sint,
1600 "rgba32float" => TextureFormat::Rgba32Float,
1601 "stencil8" => TextureFormat::Stencil8,
1602 "depth32float" => TextureFormat::Depth32Float,
1603 "depth32float-stencil8" => TextureFormat::Depth32FloatStencil8,
1604 "depth16unorm" => TextureFormat::Depth16Unorm,
1605 "depth24plus" => TextureFormat::Depth24Plus,
1606 "depth24plus-stencil8" => TextureFormat::Depth24PlusStencil8,
1607 "nv12" => TextureFormat::NV12,
1608 "p010" => TextureFormat::P010,
1609 "rgb9e5ufloat" => TextureFormat::Rgb9e5Ufloat,
1610 "bc1-rgba-unorm" => TextureFormat::Bc1RgbaUnorm,
1611 "bc1-rgba-unorm-srgb" => TextureFormat::Bc1RgbaUnormSrgb,
1612 "bc2-rgba-unorm" => TextureFormat::Bc2RgbaUnorm,
1613 "bc2-rgba-unorm-srgb" => TextureFormat::Bc2RgbaUnormSrgb,
1614 "bc3-rgba-unorm" => TextureFormat::Bc3RgbaUnorm,
1615 "bc3-rgba-unorm-srgb" => TextureFormat::Bc3RgbaUnormSrgb,
1616 "bc4-r-unorm" => TextureFormat::Bc4RUnorm,
1617 "bc4-r-snorm" => TextureFormat::Bc4RSnorm,
1618 "bc5-rg-unorm" => TextureFormat::Bc5RgUnorm,
1619 "bc5-rg-snorm" => TextureFormat::Bc5RgSnorm,
1620 "bc6h-rgb-ufloat" => TextureFormat::Bc6hRgbUfloat,
1621 "bc6h-rgb-float" => TextureFormat::Bc6hRgbFloat,
1622 "bc7-rgba-unorm" => TextureFormat::Bc7RgbaUnorm,
1623 "bc7-rgba-unorm-srgb" => TextureFormat::Bc7RgbaUnormSrgb,
1624 "etc2-rgb8unorm" => TextureFormat::Etc2Rgb8Unorm,
1625 "etc2-rgb8unorm-srgb" => TextureFormat::Etc2Rgb8UnormSrgb,
1626 "etc2-rgb8a1unorm" => TextureFormat::Etc2Rgb8A1Unorm,
1627 "etc2-rgb8a1unorm-srgb" => TextureFormat::Etc2Rgb8A1UnormSrgb,
1628 "etc2-rgba8unorm" => TextureFormat::Etc2Rgba8Unorm,
1629 "etc2-rgba8unorm-srgb" => TextureFormat::Etc2Rgba8UnormSrgb,
1630 "eac-r11unorm" => TextureFormat::EacR11Unorm,
1631 "eac-r11snorm" => TextureFormat::EacR11Snorm,
1632 "eac-rg11unorm" => TextureFormat::EacRg11Unorm,
1633 "eac-rg11snorm" => TextureFormat::EacRg11Snorm,
1634 other => {
1635 if let Some(parts) = other.strip_prefix("astc-") {
1636 let (block, channel) = parts
1637 .split_once('-')
1638 .ok_or_else(|| E::invalid_value(Unexpected::Str(s), &self))?;
1639
1640 let block = match block {
1641 "4x4" => AstcBlock::B4x4,
1642 "5x4" => AstcBlock::B5x4,
1643 "5x5" => AstcBlock::B5x5,
1644 "6x5" => AstcBlock::B6x5,
1645 "6x6" => AstcBlock::B6x6,
1646 "8x5" => AstcBlock::B8x5,
1647 "8x6" => AstcBlock::B8x6,
1648 "8x8" => AstcBlock::B8x8,
1649 "10x5" => AstcBlock::B10x5,
1650 "10x6" => AstcBlock::B10x6,
1651 "10x8" => AstcBlock::B10x8,
1652 "10x10" => AstcBlock::B10x10,
1653 "12x10" => AstcBlock::B12x10,
1654 "12x12" => AstcBlock::B12x12,
1655 _ => return Err(E::invalid_value(Unexpected::Str(s), &self)),
1656 };
1657
1658 let channel = match channel {
1659 "unorm" => AstcChannel::Unorm,
1660 "unorm-srgb" => AstcChannel::UnormSrgb,
1661 "hdr" => AstcChannel::Hdr,
1662 _ => return Err(E::invalid_value(Unexpected::Str(s), &self)),
1663 };
1664
1665 TextureFormat::Astc { block, channel }
1666 } else {
1667 return Err(E::invalid_value(Unexpected::Str(s), &self));
1668 }
1669 }
1670 };
1671
1672 Ok(format)
1673 }
1674 }
1675
1676 deserializer.deserialize_str(TextureFormatVisitor)
1677 }
1678}
1679
1680#[cfg(any(feature = "serde", test))]
1681impl Serialize for TextureFormat {
1682 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1683 where
1684 S: serde::Serializer,
1685 {
1686 let s: alloc::string::String;
1687 let name = match *self {
1688 TextureFormat::R8Unorm => "r8unorm",
1689 TextureFormat::R8Snorm => "r8snorm",
1690 TextureFormat::R8Uint => "r8uint",
1691 TextureFormat::R8Sint => "r8sint",
1692 TextureFormat::R16Uint => "r16uint",
1693 TextureFormat::R16Sint => "r16sint",
1694 TextureFormat::R16Unorm => "r16unorm",
1695 TextureFormat::R16Snorm => "r16snorm",
1696 TextureFormat::R16Float => "r16float",
1697 TextureFormat::Rg8Unorm => "rg8unorm",
1698 TextureFormat::Rg8Snorm => "rg8snorm",
1699 TextureFormat::Rg8Uint => "rg8uint",
1700 TextureFormat::Rg8Sint => "rg8sint",
1701 TextureFormat::R32Uint => "r32uint",
1702 TextureFormat::R32Sint => "r32sint",
1703 TextureFormat::R32Float => "r32float",
1704 TextureFormat::Rg16Uint => "rg16uint",
1705 TextureFormat::Rg16Sint => "rg16sint",
1706 TextureFormat::Rg16Unorm => "rg16unorm",
1707 TextureFormat::Rg16Snorm => "rg16snorm",
1708 TextureFormat::Rg16Float => "rg16float",
1709 TextureFormat::Rgba8Unorm => "rgba8unorm",
1710 TextureFormat::Rgba8UnormSrgb => "rgba8unorm-srgb",
1711 TextureFormat::Rgba8Snorm => "rgba8snorm",
1712 TextureFormat::Rgba8Uint => "rgba8uint",
1713 TextureFormat::Rgba8Sint => "rgba8sint",
1714 TextureFormat::Bgra8Unorm => "bgra8unorm",
1715 TextureFormat::Bgra8UnormSrgb => "bgra8unorm-srgb",
1716 TextureFormat::Rgb10a2Uint => "rgb10a2uint",
1717 TextureFormat::Rgb10a2Unorm => "rgb10a2unorm",
1718 TextureFormat::Rg11b10Ufloat => "rg11b10ufloat",
1719 TextureFormat::R64Uint => "r64uint",
1720 TextureFormat::Rg32Uint => "rg32uint",
1721 TextureFormat::Rg32Sint => "rg32sint",
1722 TextureFormat::Rg32Float => "rg32float",
1723 TextureFormat::Rgba16Uint => "rgba16uint",
1724 TextureFormat::Rgba16Sint => "rgba16sint",
1725 TextureFormat::Rgba16Unorm => "rgba16unorm",
1726 TextureFormat::Rgba16Snorm => "rgba16snorm",
1727 TextureFormat::Rgba16Float => "rgba16float",
1728 TextureFormat::Rgba32Uint => "rgba32uint",
1729 TextureFormat::Rgba32Sint => "rgba32sint",
1730 TextureFormat::Rgba32Float => "rgba32float",
1731 TextureFormat::Stencil8 => "stencil8",
1732 TextureFormat::Depth32Float => "depth32float",
1733 TextureFormat::Depth16Unorm => "depth16unorm",
1734 TextureFormat::Depth32FloatStencil8 => "depth32float-stencil8",
1735 TextureFormat::Depth24Plus => "depth24plus",
1736 TextureFormat::Depth24PlusStencil8 => "depth24plus-stencil8",
1737 TextureFormat::NV12 => "nv12",
1738 TextureFormat::P010 => "p010",
1739 TextureFormat::Rgb9e5Ufloat => "rgb9e5ufloat",
1740 TextureFormat::Bc1RgbaUnorm => "bc1-rgba-unorm",
1741 TextureFormat::Bc1RgbaUnormSrgb => "bc1-rgba-unorm-srgb",
1742 TextureFormat::Bc2RgbaUnorm => "bc2-rgba-unorm",
1743 TextureFormat::Bc2RgbaUnormSrgb => "bc2-rgba-unorm-srgb",
1744 TextureFormat::Bc3RgbaUnorm => "bc3-rgba-unorm",
1745 TextureFormat::Bc3RgbaUnormSrgb => "bc3-rgba-unorm-srgb",
1746 TextureFormat::Bc4RUnorm => "bc4-r-unorm",
1747 TextureFormat::Bc4RSnorm => "bc4-r-snorm",
1748 TextureFormat::Bc5RgUnorm => "bc5-rg-unorm",
1749 TextureFormat::Bc5RgSnorm => "bc5-rg-snorm",
1750 TextureFormat::Bc6hRgbUfloat => "bc6h-rgb-ufloat",
1751 TextureFormat::Bc6hRgbFloat => "bc6h-rgb-float",
1752 TextureFormat::Bc7RgbaUnorm => "bc7-rgba-unorm",
1753 TextureFormat::Bc7RgbaUnormSrgb => "bc7-rgba-unorm-srgb",
1754 TextureFormat::Etc2Rgb8Unorm => "etc2-rgb8unorm",
1755 TextureFormat::Etc2Rgb8UnormSrgb => "etc2-rgb8unorm-srgb",
1756 TextureFormat::Etc2Rgb8A1Unorm => "etc2-rgb8a1unorm",
1757 TextureFormat::Etc2Rgb8A1UnormSrgb => "etc2-rgb8a1unorm-srgb",
1758 TextureFormat::Etc2Rgba8Unorm => "etc2-rgba8unorm",
1759 TextureFormat::Etc2Rgba8UnormSrgb => "etc2-rgba8unorm-srgb",
1760 TextureFormat::EacR11Unorm => "eac-r11unorm",
1761 TextureFormat::EacR11Snorm => "eac-r11snorm",
1762 TextureFormat::EacRg11Unorm => "eac-rg11unorm",
1763 TextureFormat::EacRg11Snorm => "eac-rg11snorm",
1764 TextureFormat::Astc { block, channel } => {
1765 let block = match block {
1766 AstcBlock::B4x4 => "4x4",
1767 AstcBlock::B5x4 => "5x4",
1768 AstcBlock::B5x5 => "5x5",
1769 AstcBlock::B6x5 => "6x5",
1770 AstcBlock::B6x6 => "6x6",
1771 AstcBlock::B8x5 => "8x5",
1772 AstcBlock::B8x6 => "8x6",
1773 AstcBlock::B8x8 => "8x8",
1774 AstcBlock::B10x5 => "10x5",
1775 AstcBlock::B10x6 => "10x6",
1776 AstcBlock::B10x8 => "10x8",
1777 AstcBlock::B10x10 => "10x10",
1778 AstcBlock::B12x10 => "12x10",
1779 AstcBlock::B12x12 => "12x12",
1780 };
1781
1782 let channel = match channel {
1783 AstcChannel::Unorm => "unorm",
1784 AstcChannel::UnormSrgb => "unorm-srgb",
1785 AstcChannel::Hdr => "hdr",
1786 };
1787
1788 s = alloc::format!("astc-{block}-{channel}");
1789 &s
1790 }
1791 };
1792 serializer.serialize_str(name)
1793 }
1794}
1795
1796bitflags::bitflags! {
1797 #[repr(transparent)]
1799 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1800 #[cfg_attr(feature = "serde", serde(transparent))]
1801 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1802 pub struct TextureFormatFeatureFlags: u32 {
1803 const FILTERABLE = 1 << 0;
1806 const MULTISAMPLE_X2 = 1 << 1;
1808 const MULTISAMPLE_X4 = 1 << 2 ;
1810 const MULTISAMPLE_X8 = 1 << 3 ;
1812 const MULTISAMPLE_X16 = 1 << 4;
1814 const MULTISAMPLE_RESOLVE = 1 << 5;
1817 const STORAGE_READ_ONLY = 1 << 6;
1820 const STORAGE_WRITE_ONLY = 1 << 7;
1823 const STORAGE_READ_WRITE = 1 << 8;
1826 const STORAGE_ATOMIC = 1 << 9;
1829 const BLENDABLE = 1 << 10;
1831 }
1832}
1833
1834impl TextureFormatFeatureFlags {
1835 #[must_use]
1839 pub fn sample_count_supported(&self, count: u32) -> bool {
1840 use TextureFormatFeatureFlags as tfsc;
1841
1842 match count {
1843 1 => true,
1844 2 => self.contains(tfsc::MULTISAMPLE_X2),
1845 4 => self.contains(tfsc::MULTISAMPLE_X4),
1846 8 => self.contains(tfsc::MULTISAMPLE_X8),
1847 16 => self.contains(tfsc::MULTISAMPLE_X16),
1848 _ => false,
1849 }
1850 }
1851
1852 #[must_use]
1854 pub fn supported_sample_counts(&self) -> Vec<u32> {
1855 let all_possible_sample_counts: [u32; 5] = [1, 2, 4, 8, 16];
1856 all_possible_sample_counts
1857 .into_iter()
1858 .filter(|&sc| self.sample_count_supported(sc))
1859 .collect()
1860 }
1861}
1862
1863#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
1867#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1868pub struct TextureFormatFeatures {
1869 pub allowed_usages: TextureUsages,
1871 pub flags: TextureFormatFeatureFlags,
1873}
1874
1875#[cfg(test)]
1876mod tests {
1877 use super::*;
1878
1879 #[test]
1880 fn texture_format_serialize() {
1881 use alloc::string::ToString;
1882
1883 assert_eq!(
1884 serde_json::to_string(&TextureFormat::R8Unorm).unwrap(),
1885 "\"r8unorm\"".to_string()
1886 );
1887 assert_eq!(
1888 serde_json::to_string(&TextureFormat::R8Snorm).unwrap(),
1889 "\"r8snorm\"".to_string()
1890 );
1891 assert_eq!(
1892 serde_json::to_string(&TextureFormat::R8Uint).unwrap(),
1893 "\"r8uint\"".to_string()
1894 );
1895 assert_eq!(
1896 serde_json::to_string(&TextureFormat::R8Sint).unwrap(),
1897 "\"r8sint\"".to_string()
1898 );
1899 assert_eq!(
1900 serde_json::to_string(&TextureFormat::R16Uint).unwrap(),
1901 "\"r16uint\"".to_string()
1902 );
1903 assert_eq!(
1904 serde_json::to_string(&TextureFormat::R16Sint).unwrap(),
1905 "\"r16sint\"".to_string()
1906 );
1907 assert_eq!(
1908 serde_json::to_string(&TextureFormat::R16Unorm).unwrap(),
1909 "\"r16unorm\"".to_string()
1910 );
1911 assert_eq!(
1912 serde_json::to_string(&TextureFormat::R16Snorm).unwrap(),
1913 "\"r16snorm\"".to_string()
1914 );
1915 assert_eq!(
1916 serde_json::to_string(&TextureFormat::R16Float).unwrap(),
1917 "\"r16float\"".to_string()
1918 );
1919 assert_eq!(
1920 serde_json::to_string(&TextureFormat::Rg8Unorm).unwrap(),
1921 "\"rg8unorm\"".to_string()
1922 );
1923 assert_eq!(
1924 serde_json::to_string(&TextureFormat::Rg8Snorm).unwrap(),
1925 "\"rg8snorm\"".to_string()
1926 );
1927 assert_eq!(
1928 serde_json::to_string(&TextureFormat::Rg8Uint).unwrap(),
1929 "\"rg8uint\"".to_string()
1930 );
1931 assert_eq!(
1932 serde_json::to_string(&TextureFormat::Rg8Sint).unwrap(),
1933 "\"rg8sint\"".to_string()
1934 );
1935 assert_eq!(
1936 serde_json::to_string(&TextureFormat::R32Uint).unwrap(),
1937 "\"r32uint\"".to_string()
1938 );
1939 assert_eq!(
1940 serde_json::to_string(&TextureFormat::R32Sint).unwrap(),
1941 "\"r32sint\"".to_string()
1942 );
1943 assert_eq!(
1944 serde_json::to_string(&TextureFormat::R32Float).unwrap(),
1945 "\"r32float\"".to_string()
1946 );
1947 assert_eq!(
1948 serde_json::to_string(&TextureFormat::Rg16Uint).unwrap(),
1949 "\"rg16uint\"".to_string()
1950 );
1951 assert_eq!(
1952 serde_json::to_string(&TextureFormat::Rg16Sint).unwrap(),
1953 "\"rg16sint\"".to_string()
1954 );
1955 assert_eq!(
1956 serde_json::to_string(&TextureFormat::Rg16Unorm).unwrap(),
1957 "\"rg16unorm\"".to_string()
1958 );
1959 assert_eq!(
1960 serde_json::to_string(&TextureFormat::Rg16Snorm).unwrap(),
1961 "\"rg16snorm\"".to_string()
1962 );
1963 assert_eq!(
1964 serde_json::to_string(&TextureFormat::Rg16Float).unwrap(),
1965 "\"rg16float\"".to_string()
1966 );
1967 assert_eq!(
1968 serde_json::to_string(&TextureFormat::Rgba8Unorm).unwrap(),
1969 "\"rgba8unorm\"".to_string()
1970 );
1971 assert_eq!(
1972 serde_json::to_string(&TextureFormat::Rgba8UnormSrgb).unwrap(),
1973 "\"rgba8unorm-srgb\"".to_string()
1974 );
1975 assert_eq!(
1976 serde_json::to_string(&TextureFormat::Rgba8Snorm).unwrap(),
1977 "\"rgba8snorm\"".to_string()
1978 );
1979 assert_eq!(
1980 serde_json::to_string(&TextureFormat::Rgba8Uint).unwrap(),
1981 "\"rgba8uint\"".to_string()
1982 );
1983 assert_eq!(
1984 serde_json::to_string(&TextureFormat::Rgba8Sint).unwrap(),
1985 "\"rgba8sint\"".to_string()
1986 );
1987 assert_eq!(
1988 serde_json::to_string(&TextureFormat::Bgra8Unorm).unwrap(),
1989 "\"bgra8unorm\"".to_string()
1990 );
1991 assert_eq!(
1992 serde_json::to_string(&TextureFormat::Bgra8UnormSrgb).unwrap(),
1993 "\"bgra8unorm-srgb\"".to_string()
1994 );
1995 assert_eq!(
1996 serde_json::to_string(&TextureFormat::Rgb10a2Uint).unwrap(),
1997 "\"rgb10a2uint\"".to_string()
1998 );
1999 assert_eq!(
2000 serde_json::to_string(&TextureFormat::Rgb10a2Unorm).unwrap(),
2001 "\"rgb10a2unorm\"".to_string()
2002 );
2003 assert_eq!(
2004 serde_json::to_string(&TextureFormat::Rg11b10Ufloat).unwrap(),
2005 "\"rg11b10ufloat\"".to_string()
2006 );
2007 assert_eq!(
2008 serde_json::to_string(&TextureFormat::R64Uint).unwrap(),
2009 "\"r64uint\"".to_string()
2010 );
2011 assert_eq!(
2012 serde_json::to_string(&TextureFormat::Rg32Uint).unwrap(),
2013 "\"rg32uint\"".to_string()
2014 );
2015 assert_eq!(
2016 serde_json::to_string(&TextureFormat::Rg32Sint).unwrap(),
2017 "\"rg32sint\"".to_string()
2018 );
2019 assert_eq!(
2020 serde_json::to_string(&TextureFormat::Rg32Float).unwrap(),
2021 "\"rg32float\"".to_string()
2022 );
2023 assert_eq!(
2024 serde_json::to_string(&TextureFormat::Rgba16Uint).unwrap(),
2025 "\"rgba16uint\"".to_string()
2026 );
2027 assert_eq!(
2028 serde_json::to_string(&TextureFormat::Rgba16Sint).unwrap(),
2029 "\"rgba16sint\"".to_string()
2030 );
2031 assert_eq!(
2032 serde_json::to_string(&TextureFormat::Rgba16Unorm).unwrap(),
2033 "\"rgba16unorm\"".to_string()
2034 );
2035 assert_eq!(
2036 serde_json::to_string(&TextureFormat::Rgba16Snorm).unwrap(),
2037 "\"rgba16snorm\"".to_string()
2038 );
2039 assert_eq!(
2040 serde_json::to_string(&TextureFormat::Rgba16Float).unwrap(),
2041 "\"rgba16float\"".to_string()
2042 );
2043 assert_eq!(
2044 serde_json::to_string(&TextureFormat::Rgba32Uint).unwrap(),
2045 "\"rgba32uint\"".to_string()
2046 );
2047 assert_eq!(
2048 serde_json::to_string(&TextureFormat::Rgba32Sint).unwrap(),
2049 "\"rgba32sint\"".to_string()
2050 );
2051 assert_eq!(
2052 serde_json::to_string(&TextureFormat::Rgba32Float).unwrap(),
2053 "\"rgba32float\"".to_string()
2054 );
2055 assert_eq!(
2056 serde_json::to_string(&TextureFormat::Stencil8).unwrap(),
2057 "\"stencil8\"".to_string()
2058 );
2059 assert_eq!(
2060 serde_json::to_string(&TextureFormat::Depth32Float).unwrap(),
2061 "\"depth32float\"".to_string()
2062 );
2063 assert_eq!(
2064 serde_json::to_string(&TextureFormat::Depth16Unorm).unwrap(),
2065 "\"depth16unorm\"".to_string()
2066 );
2067 assert_eq!(
2068 serde_json::to_string(&TextureFormat::Depth32FloatStencil8).unwrap(),
2069 "\"depth32float-stencil8\"".to_string()
2070 );
2071 assert_eq!(
2072 serde_json::to_string(&TextureFormat::Depth24Plus).unwrap(),
2073 "\"depth24plus\"".to_string()
2074 );
2075 assert_eq!(
2076 serde_json::to_string(&TextureFormat::Depth24PlusStencil8).unwrap(),
2077 "\"depth24plus-stencil8\"".to_string()
2078 );
2079 assert_eq!(
2080 serde_json::to_string(&TextureFormat::Rgb9e5Ufloat).unwrap(),
2081 "\"rgb9e5ufloat\"".to_string()
2082 );
2083 assert_eq!(
2084 serde_json::to_string(&TextureFormat::Bc1RgbaUnorm).unwrap(),
2085 "\"bc1-rgba-unorm\"".to_string()
2086 );
2087 assert_eq!(
2088 serde_json::to_string(&TextureFormat::Bc1RgbaUnormSrgb).unwrap(),
2089 "\"bc1-rgba-unorm-srgb\"".to_string()
2090 );
2091 assert_eq!(
2092 serde_json::to_string(&TextureFormat::Bc2RgbaUnorm).unwrap(),
2093 "\"bc2-rgba-unorm\"".to_string()
2094 );
2095 assert_eq!(
2096 serde_json::to_string(&TextureFormat::Bc2RgbaUnormSrgb).unwrap(),
2097 "\"bc2-rgba-unorm-srgb\"".to_string()
2098 );
2099 assert_eq!(
2100 serde_json::to_string(&TextureFormat::Bc3RgbaUnorm).unwrap(),
2101 "\"bc3-rgba-unorm\"".to_string()
2102 );
2103 assert_eq!(
2104 serde_json::to_string(&TextureFormat::Bc3RgbaUnormSrgb).unwrap(),
2105 "\"bc3-rgba-unorm-srgb\"".to_string()
2106 );
2107 assert_eq!(
2108 serde_json::to_string(&TextureFormat::Bc4RUnorm).unwrap(),
2109 "\"bc4-r-unorm\"".to_string()
2110 );
2111 assert_eq!(
2112 serde_json::to_string(&TextureFormat::Bc4RSnorm).unwrap(),
2113 "\"bc4-r-snorm\"".to_string()
2114 );
2115 assert_eq!(
2116 serde_json::to_string(&TextureFormat::Bc5RgUnorm).unwrap(),
2117 "\"bc5-rg-unorm\"".to_string()
2118 );
2119 assert_eq!(
2120 serde_json::to_string(&TextureFormat::Bc5RgSnorm).unwrap(),
2121 "\"bc5-rg-snorm\"".to_string()
2122 );
2123 assert_eq!(
2124 serde_json::to_string(&TextureFormat::Bc6hRgbUfloat).unwrap(),
2125 "\"bc6h-rgb-ufloat\"".to_string()
2126 );
2127 assert_eq!(
2128 serde_json::to_string(&TextureFormat::Bc6hRgbFloat).unwrap(),
2129 "\"bc6h-rgb-float\"".to_string()
2130 );
2131 assert_eq!(
2132 serde_json::to_string(&TextureFormat::Bc7RgbaUnorm).unwrap(),
2133 "\"bc7-rgba-unorm\"".to_string()
2134 );
2135 assert_eq!(
2136 serde_json::to_string(&TextureFormat::Bc7RgbaUnormSrgb).unwrap(),
2137 "\"bc7-rgba-unorm-srgb\"".to_string()
2138 );
2139 assert_eq!(
2140 serde_json::to_string(&TextureFormat::Etc2Rgb8Unorm).unwrap(),
2141 "\"etc2-rgb8unorm\"".to_string()
2142 );
2143 assert_eq!(
2144 serde_json::to_string(&TextureFormat::Etc2Rgb8UnormSrgb).unwrap(),
2145 "\"etc2-rgb8unorm-srgb\"".to_string()
2146 );
2147 assert_eq!(
2148 serde_json::to_string(&TextureFormat::Etc2Rgb8A1Unorm).unwrap(),
2149 "\"etc2-rgb8a1unorm\"".to_string()
2150 );
2151 assert_eq!(
2152 serde_json::to_string(&TextureFormat::Etc2Rgb8A1UnormSrgb).unwrap(),
2153 "\"etc2-rgb8a1unorm-srgb\"".to_string()
2154 );
2155 assert_eq!(
2156 serde_json::to_string(&TextureFormat::Etc2Rgba8Unorm).unwrap(),
2157 "\"etc2-rgba8unorm\"".to_string()
2158 );
2159 assert_eq!(
2160 serde_json::to_string(&TextureFormat::Etc2Rgba8UnormSrgb).unwrap(),
2161 "\"etc2-rgba8unorm-srgb\"".to_string()
2162 );
2163 assert_eq!(
2164 serde_json::to_string(&TextureFormat::EacR11Unorm).unwrap(),
2165 "\"eac-r11unorm\"".to_string()
2166 );
2167 assert_eq!(
2168 serde_json::to_string(&TextureFormat::EacR11Snorm).unwrap(),
2169 "\"eac-r11snorm\"".to_string()
2170 );
2171 assert_eq!(
2172 serde_json::to_string(&TextureFormat::EacRg11Unorm).unwrap(),
2173 "\"eac-rg11unorm\"".to_string()
2174 );
2175 assert_eq!(
2176 serde_json::to_string(&TextureFormat::EacRg11Snorm).unwrap(),
2177 "\"eac-rg11snorm\"".to_string()
2178 );
2179 }
2180
2181 #[test]
2182 fn texture_format_deserialize() {
2183 assert_eq!(
2184 serde_json::from_str::<TextureFormat>("\"r8unorm\"").unwrap(),
2185 TextureFormat::R8Unorm
2186 );
2187 assert_eq!(
2188 serde_json::from_str::<TextureFormat>("\"r8snorm\"").unwrap(),
2189 TextureFormat::R8Snorm
2190 );
2191 assert_eq!(
2192 serde_json::from_str::<TextureFormat>("\"r8uint\"").unwrap(),
2193 TextureFormat::R8Uint
2194 );
2195 assert_eq!(
2196 serde_json::from_str::<TextureFormat>("\"r8sint\"").unwrap(),
2197 TextureFormat::R8Sint
2198 );
2199 assert_eq!(
2200 serde_json::from_str::<TextureFormat>("\"r16uint\"").unwrap(),
2201 TextureFormat::R16Uint
2202 );
2203 assert_eq!(
2204 serde_json::from_str::<TextureFormat>("\"r16sint\"").unwrap(),
2205 TextureFormat::R16Sint
2206 );
2207 assert_eq!(
2208 serde_json::from_str::<TextureFormat>("\"r16unorm\"").unwrap(),
2209 TextureFormat::R16Unorm
2210 );
2211 assert_eq!(
2212 serde_json::from_str::<TextureFormat>("\"r16snorm\"").unwrap(),
2213 TextureFormat::R16Snorm
2214 );
2215 assert_eq!(
2216 serde_json::from_str::<TextureFormat>("\"r16float\"").unwrap(),
2217 TextureFormat::R16Float
2218 );
2219 assert_eq!(
2220 serde_json::from_str::<TextureFormat>("\"rg8unorm\"").unwrap(),
2221 TextureFormat::Rg8Unorm
2222 );
2223 assert_eq!(
2224 serde_json::from_str::<TextureFormat>("\"rg8snorm\"").unwrap(),
2225 TextureFormat::Rg8Snorm
2226 );
2227 assert_eq!(
2228 serde_json::from_str::<TextureFormat>("\"rg8uint\"").unwrap(),
2229 TextureFormat::Rg8Uint
2230 );
2231 assert_eq!(
2232 serde_json::from_str::<TextureFormat>("\"rg8sint\"").unwrap(),
2233 TextureFormat::Rg8Sint
2234 );
2235 assert_eq!(
2236 serde_json::from_str::<TextureFormat>("\"r32uint\"").unwrap(),
2237 TextureFormat::R32Uint
2238 );
2239 assert_eq!(
2240 serde_json::from_str::<TextureFormat>("\"r32sint\"").unwrap(),
2241 TextureFormat::R32Sint
2242 );
2243 assert_eq!(
2244 serde_json::from_str::<TextureFormat>("\"r32float\"").unwrap(),
2245 TextureFormat::R32Float
2246 );
2247 assert_eq!(
2248 serde_json::from_str::<TextureFormat>("\"rg16uint\"").unwrap(),
2249 TextureFormat::Rg16Uint
2250 );
2251 assert_eq!(
2252 serde_json::from_str::<TextureFormat>("\"rg16sint\"").unwrap(),
2253 TextureFormat::Rg16Sint
2254 );
2255 assert_eq!(
2256 serde_json::from_str::<TextureFormat>("\"rg16unorm\"").unwrap(),
2257 TextureFormat::Rg16Unorm
2258 );
2259 assert_eq!(
2260 serde_json::from_str::<TextureFormat>("\"rg16snorm\"").unwrap(),
2261 TextureFormat::Rg16Snorm
2262 );
2263 assert_eq!(
2264 serde_json::from_str::<TextureFormat>("\"rg16float\"").unwrap(),
2265 TextureFormat::Rg16Float
2266 );
2267 assert_eq!(
2268 serde_json::from_str::<TextureFormat>("\"rgba8unorm\"").unwrap(),
2269 TextureFormat::Rgba8Unorm
2270 );
2271 assert_eq!(
2272 serde_json::from_str::<TextureFormat>("\"rgba8unorm-srgb\"").unwrap(),
2273 TextureFormat::Rgba8UnormSrgb
2274 );
2275 assert_eq!(
2276 serde_json::from_str::<TextureFormat>("\"rgba8snorm\"").unwrap(),
2277 TextureFormat::Rgba8Snorm
2278 );
2279 assert_eq!(
2280 serde_json::from_str::<TextureFormat>("\"rgba8uint\"").unwrap(),
2281 TextureFormat::Rgba8Uint
2282 );
2283 assert_eq!(
2284 serde_json::from_str::<TextureFormat>("\"rgba8sint\"").unwrap(),
2285 TextureFormat::Rgba8Sint
2286 );
2287 assert_eq!(
2288 serde_json::from_str::<TextureFormat>("\"bgra8unorm\"").unwrap(),
2289 TextureFormat::Bgra8Unorm
2290 );
2291 assert_eq!(
2292 serde_json::from_str::<TextureFormat>("\"bgra8unorm-srgb\"").unwrap(),
2293 TextureFormat::Bgra8UnormSrgb
2294 );
2295 assert_eq!(
2296 serde_json::from_str::<TextureFormat>("\"rgb10a2uint\"").unwrap(),
2297 TextureFormat::Rgb10a2Uint
2298 );
2299 assert_eq!(
2300 serde_json::from_str::<TextureFormat>("\"rgb10a2unorm\"").unwrap(),
2301 TextureFormat::Rgb10a2Unorm
2302 );
2303 assert_eq!(
2304 serde_json::from_str::<TextureFormat>("\"rg11b10ufloat\"").unwrap(),
2305 TextureFormat::Rg11b10Ufloat
2306 );
2307 assert_eq!(
2308 serde_json::from_str::<TextureFormat>("\"r64uint\"").unwrap(),
2309 TextureFormat::R64Uint
2310 );
2311 assert_eq!(
2312 serde_json::from_str::<TextureFormat>("\"rg32uint\"").unwrap(),
2313 TextureFormat::Rg32Uint
2314 );
2315 assert_eq!(
2316 serde_json::from_str::<TextureFormat>("\"rg32sint\"").unwrap(),
2317 TextureFormat::Rg32Sint
2318 );
2319 assert_eq!(
2320 serde_json::from_str::<TextureFormat>("\"rg32float\"").unwrap(),
2321 TextureFormat::Rg32Float
2322 );
2323 assert_eq!(
2324 serde_json::from_str::<TextureFormat>("\"rgba16uint\"").unwrap(),
2325 TextureFormat::Rgba16Uint
2326 );
2327 assert_eq!(
2328 serde_json::from_str::<TextureFormat>("\"rgba16sint\"").unwrap(),
2329 TextureFormat::Rgba16Sint
2330 );
2331 assert_eq!(
2332 serde_json::from_str::<TextureFormat>("\"rgba16unorm\"").unwrap(),
2333 TextureFormat::Rgba16Unorm
2334 );
2335 assert_eq!(
2336 serde_json::from_str::<TextureFormat>("\"rgba16snorm\"").unwrap(),
2337 TextureFormat::Rgba16Snorm
2338 );
2339 assert_eq!(
2340 serde_json::from_str::<TextureFormat>("\"rgba16float\"").unwrap(),
2341 TextureFormat::Rgba16Float
2342 );
2343 assert_eq!(
2344 serde_json::from_str::<TextureFormat>("\"rgba32uint\"").unwrap(),
2345 TextureFormat::Rgba32Uint
2346 );
2347 assert_eq!(
2348 serde_json::from_str::<TextureFormat>("\"rgba32sint\"").unwrap(),
2349 TextureFormat::Rgba32Sint
2350 );
2351 assert_eq!(
2352 serde_json::from_str::<TextureFormat>("\"rgba32float\"").unwrap(),
2353 TextureFormat::Rgba32Float
2354 );
2355 assert_eq!(
2356 serde_json::from_str::<TextureFormat>("\"stencil8\"").unwrap(),
2357 TextureFormat::Stencil8
2358 );
2359 assert_eq!(
2360 serde_json::from_str::<TextureFormat>("\"depth32float\"").unwrap(),
2361 TextureFormat::Depth32Float
2362 );
2363 assert_eq!(
2364 serde_json::from_str::<TextureFormat>("\"depth16unorm\"").unwrap(),
2365 TextureFormat::Depth16Unorm
2366 );
2367 assert_eq!(
2368 serde_json::from_str::<TextureFormat>("\"depth32float-stencil8\"").unwrap(),
2369 TextureFormat::Depth32FloatStencil8
2370 );
2371 assert_eq!(
2372 serde_json::from_str::<TextureFormat>("\"depth24plus\"").unwrap(),
2373 TextureFormat::Depth24Plus
2374 );
2375 assert_eq!(
2376 serde_json::from_str::<TextureFormat>("\"depth24plus-stencil8\"").unwrap(),
2377 TextureFormat::Depth24PlusStencil8
2378 );
2379 assert_eq!(
2380 serde_json::from_str::<TextureFormat>("\"rgb9e5ufloat\"").unwrap(),
2381 TextureFormat::Rgb9e5Ufloat
2382 );
2383 assert_eq!(
2384 serde_json::from_str::<TextureFormat>("\"bc1-rgba-unorm\"").unwrap(),
2385 TextureFormat::Bc1RgbaUnorm
2386 );
2387 assert_eq!(
2388 serde_json::from_str::<TextureFormat>("\"bc1-rgba-unorm-srgb\"").unwrap(),
2389 TextureFormat::Bc1RgbaUnormSrgb
2390 );
2391 assert_eq!(
2392 serde_json::from_str::<TextureFormat>("\"bc2-rgba-unorm\"").unwrap(),
2393 TextureFormat::Bc2RgbaUnorm
2394 );
2395 assert_eq!(
2396 serde_json::from_str::<TextureFormat>("\"bc2-rgba-unorm-srgb\"").unwrap(),
2397 TextureFormat::Bc2RgbaUnormSrgb
2398 );
2399 assert_eq!(
2400 serde_json::from_str::<TextureFormat>("\"bc3-rgba-unorm\"").unwrap(),
2401 TextureFormat::Bc3RgbaUnorm
2402 );
2403 assert_eq!(
2404 serde_json::from_str::<TextureFormat>("\"bc3-rgba-unorm-srgb\"").unwrap(),
2405 TextureFormat::Bc3RgbaUnormSrgb
2406 );
2407 assert_eq!(
2408 serde_json::from_str::<TextureFormat>("\"bc4-r-unorm\"").unwrap(),
2409 TextureFormat::Bc4RUnorm
2410 );
2411 assert_eq!(
2412 serde_json::from_str::<TextureFormat>("\"bc4-r-snorm\"").unwrap(),
2413 TextureFormat::Bc4RSnorm
2414 );
2415 assert_eq!(
2416 serde_json::from_str::<TextureFormat>("\"bc5-rg-unorm\"").unwrap(),
2417 TextureFormat::Bc5RgUnorm
2418 );
2419 assert_eq!(
2420 serde_json::from_str::<TextureFormat>("\"bc5-rg-snorm\"").unwrap(),
2421 TextureFormat::Bc5RgSnorm
2422 );
2423 assert_eq!(
2424 serde_json::from_str::<TextureFormat>("\"bc6h-rgb-ufloat\"").unwrap(),
2425 TextureFormat::Bc6hRgbUfloat
2426 );
2427 assert_eq!(
2428 serde_json::from_str::<TextureFormat>("\"bc6h-rgb-float\"").unwrap(),
2429 TextureFormat::Bc6hRgbFloat
2430 );
2431 assert_eq!(
2432 serde_json::from_str::<TextureFormat>("\"bc7-rgba-unorm\"").unwrap(),
2433 TextureFormat::Bc7RgbaUnorm
2434 );
2435 assert_eq!(
2436 serde_json::from_str::<TextureFormat>("\"bc7-rgba-unorm-srgb\"").unwrap(),
2437 TextureFormat::Bc7RgbaUnormSrgb
2438 );
2439 assert_eq!(
2440 serde_json::from_str::<TextureFormat>("\"etc2-rgb8unorm\"").unwrap(),
2441 TextureFormat::Etc2Rgb8Unorm
2442 );
2443 assert_eq!(
2444 serde_json::from_str::<TextureFormat>("\"etc2-rgb8unorm-srgb\"").unwrap(),
2445 TextureFormat::Etc2Rgb8UnormSrgb
2446 );
2447 assert_eq!(
2448 serde_json::from_str::<TextureFormat>("\"etc2-rgb8a1unorm\"").unwrap(),
2449 TextureFormat::Etc2Rgb8A1Unorm
2450 );
2451 assert_eq!(
2452 serde_json::from_str::<TextureFormat>("\"etc2-rgb8a1unorm-srgb\"").unwrap(),
2453 TextureFormat::Etc2Rgb8A1UnormSrgb
2454 );
2455 assert_eq!(
2456 serde_json::from_str::<TextureFormat>("\"etc2-rgba8unorm\"").unwrap(),
2457 TextureFormat::Etc2Rgba8Unorm
2458 );
2459 assert_eq!(
2460 serde_json::from_str::<TextureFormat>("\"etc2-rgba8unorm-srgb\"").unwrap(),
2461 TextureFormat::Etc2Rgba8UnormSrgb
2462 );
2463 assert_eq!(
2464 serde_json::from_str::<TextureFormat>("\"eac-r11unorm\"").unwrap(),
2465 TextureFormat::EacR11Unorm
2466 );
2467 assert_eq!(
2468 serde_json::from_str::<TextureFormat>("\"eac-r11snorm\"").unwrap(),
2469 TextureFormat::EacR11Snorm
2470 );
2471 assert_eq!(
2472 serde_json::from_str::<TextureFormat>("\"eac-rg11unorm\"").unwrap(),
2473 TextureFormat::EacRg11Unorm
2474 );
2475 assert_eq!(
2476 serde_json::from_str::<TextureFormat>("\"eac-rg11snorm\"").unwrap(),
2477 TextureFormat::EacRg11Snorm
2478 );
2479 }
2480}