naga/front/wgsl/parse/directive/
language_extension.rs

1//! `requires …;` extensions in WGSL.
2//!
3//! The focal point of this module is the [`LanguageExtension`] API.
4
5/// A language extension recognized by Naga, but not guaranteed to be present in all environments.
6///
7/// WGSL spec.: <https://www.w3.org/TR/WGSL/#language-extensions-sec>
8#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
9pub enum LanguageExtension {
10    #[allow(unused)]
11    Implemented(ImplementedLanguageExtension),
12    Unimplemented(UnimplementedLanguageExtension),
13}
14
15impl LanguageExtension {
16    const READONLY_AND_READWRITE_STORAGE_TEXTURES: &'static str =
17        "readonly_and_readwrite_storage_textures";
18    const PACKED4X8_INTEGER_DOT_PRODUCT: &'static str = "packed_4x8_integer_dot_product";
19    const UNRESTRICTED_POINTER_PARAMETERS: &'static str = "unrestricted_pointer_parameters";
20    const POINTER_COMPOSITE_ACCESS: &'static str = "pointer_composite_access";
21
22    /// Convert from a sentinel word in WGSL into its associated [`LanguageExtension`], if possible.
23    pub fn from_ident(s: &str) -> Option<Self> {
24        Some(match s {
25            Self::READONLY_AND_READWRITE_STORAGE_TEXTURES => {
26                Self::Implemented(ImplementedLanguageExtension::ReadOnlyAndReadWriteStorageTextures)
27            }
28            Self::PACKED4X8_INTEGER_DOT_PRODUCT => {
29                Self::Implemented(ImplementedLanguageExtension::Packed4x8IntegerDotProduct)
30            }
31            Self::UNRESTRICTED_POINTER_PARAMETERS => {
32                Self::Unimplemented(UnimplementedLanguageExtension::UnrestrictedPointerParameters)
33            }
34            Self::POINTER_COMPOSITE_ACCESS => {
35                Self::Implemented(ImplementedLanguageExtension::PointerCompositeAccess)
36            }
37            _ => return None,
38        })
39    }
40
41    /// Maps this [`LanguageExtension`] into the sentinel word associated with it in WGSL.
42    pub const fn to_ident(self) -> &'static str {
43        match self {
44            Self::Implemented(kind) => kind.to_ident(),
45            Self::Unimplemented(kind) => match kind {
46                UnimplementedLanguageExtension::UnrestrictedPointerParameters => {
47                    Self::UNRESTRICTED_POINTER_PARAMETERS
48                }
49            },
50        }
51    }
52}
53
54/// A variant of [`LanguageExtension::Implemented`].
55#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
56#[cfg_attr(test, derive(strum::VariantArray))]
57pub enum ImplementedLanguageExtension {
58    ReadOnlyAndReadWriteStorageTextures,
59    Packed4x8IntegerDotProduct,
60    PointerCompositeAccess,
61}
62
63impl ImplementedLanguageExtension {
64    /// A slice of all variants of [`ImplementedLanguageExtension`].
65    pub const VARIANTS: &'static [Self] = &[
66        Self::ReadOnlyAndReadWriteStorageTextures,
67        Self::Packed4x8IntegerDotProduct,
68        Self::PointerCompositeAccess,
69    ];
70
71    /// Returns slice of all variants of [`ImplementedLanguageExtension`].
72    pub const fn all() -> &'static [Self] {
73        Self::VARIANTS
74    }
75
76    /// Maps this [`ImplementedLanguageExtension`] into the sentinel word associated with it in WGSL.
77    pub const fn to_ident(self) -> &'static str {
78        match self {
79            ImplementedLanguageExtension::ReadOnlyAndReadWriteStorageTextures => {
80                LanguageExtension::READONLY_AND_READWRITE_STORAGE_TEXTURES
81            }
82            ImplementedLanguageExtension::Packed4x8IntegerDotProduct => {
83                LanguageExtension::PACKED4X8_INTEGER_DOT_PRODUCT
84            }
85            ImplementedLanguageExtension::PointerCompositeAccess => {
86                LanguageExtension::POINTER_COMPOSITE_ACCESS
87            }
88        }
89    }
90}
91
92#[test]
93/// Asserts that the manual implementation of VARIANTS is the same as the derived strum version would be
94/// while still allowing strum to be a dev-only dependency
95fn test_manual_variants_array_is_correct() {
96    assert_eq!(
97        <ImplementedLanguageExtension as strum::VariantArray>::VARIANTS,
98        ImplementedLanguageExtension::VARIANTS
99    );
100}
101
102/// A variant of [`LanguageExtension::Unimplemented`].
103#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
104pub enum UnimplementedLanguageExtension {
105    UnrestrictedPointerParameters,
106}
107
108impl UnimplementedLanguageExtension {
109    pub(crate) const fn tracking_issue_num(self) -> u16 {
110        match self {
111            Self::UnrestrictedPointerParameters => 5158,
112        }
113    }
114}