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

1//! `enable …;` extensions in WGSL.
2//!
3//! The focal point of this module is the [`EnableExtension`] API.
4
5use crate::front::wgsl::{Error, Result};
6use crate::Span;
7
8use alloc::boxed::Box;
9
10/// Tracks the status of every enable-extension known to Naga.
11#[derive(Clone, Debug, Eq, PartialEq)]
12pub struct EnableExtensions {
13    dual_source_blending: bool,
14    /// Whether `enable f16;` was written earlier in the shader module.
15    f16: bool,
16    clip_distances: bool,
17}
18
19impl EnableExtensions {
20    pub(crate) const fn empty() -> Self {
21        Self {
22            f16: false,
23            dual_source_blending: false,
24            clip_distances: false,
25        }
26    }
27
28    /// Add an enable-extension to the set requested by a module.
29    pub(crate) fn add(&mut self, ext: ImplementedEnableExtension) {
30        let field = match ext {
31            ImplementedEnableExtension::DualSourceBlending => &mut self.dual_source_blending,
32            ImplementedEnableExtension::F16 => &mut self.f16,
33            ImplementedEnableExtension::ClipDistances => &mut self.clip_distances,
34        };
35        *field = true;
36    }
37
38    /// Query whether an enable-extension tracked here has been requested.
39    pub(crate) const fn contains(&self, ext: ImplementedEnableExtension) -> bool {
40        match ext {
41            ImplementedEnableExtension::DualSourceBlending => self.dual_source_blending,
42            ImplementedEnableExtension::F16 => self.f16,
43            ImplementedEnableExtension::ClipDistances => self.clip_distances,
44        }
45    }
46}
47
48impl Default for EnableExtensions {
49    fn default() -> Self {
50        Self::empty()
51    }
52}
53
54/// An enable-extension not guaranteed to be present in all environments.
55///
56/// WGSL spec.: <https://www.w3.org/TR/WGSL/#enable-extensions-sec>
57#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
58pub enum EnableExtension {
59    Implemented(ImplementedEnableExtension),
60    Unimplemented(UnimplementedEnableExtension),
61}
62
63impl From<ImplementedEnableExtension> for EnableExtension {
64    fn from(value: ImplementedEnableExtension) -> Self {
65        Self::Implemented(value)
66    }
67}
68
69impl EnableExtension {
70    const F16: &'static str = "f16";
71    const CLIP_DISTANCES: &'static str = "clip_distances";
72    const DUAL_SOURCE_BLENDING: &'static str = "dual_source_blending";
73    const SUBGROUPS: &'static str = "subgroups";
74    const PRIMITIVE_INDEX: &'static str = "primitive_index";
75
76    /// Convert from a sentinel word in WGSL into its associated [`EnableExtension`], if possible.
77    pub(crate) fn from_ident(word: &str, span: Span) -> Result<'_, Self> {
78        Ok(match word {
79            Self::F16 => Self::Implemented(ImplementedEnableExtension::F16),
80            Self::CLIP_DISTANCES => Self::Implemented(ImplementedEnableExtension::ClipDistances),
81            Self::DUAL_SOURCE_BLENDING => {
82                Self::Implemented(ImplementedEnableExtension::DualSourceBlending)
83            }
84            Self::SUBGROUPS => Self::Unimplemented(UnimplementedEnableExtension::Subgroups),
85            Self::PRIMITIVE_INDEX => {
86                Self::Unimplemented(UnimplementedEnableExtension::PrimitiveIndex)
87            }
88            _ => return Err(Box::new(Error::UnknownEnableExtension(span, word))),
89        })
90    }
91
92    /// Maps this [`EnableExtension`] into the sentinel word associated with it in WGSL.
93    pub const fn to_ident(self) -> &'static str {
94        match self {
95            Self::Implemented(kind) => match kind {
96                ImplementedEnableExtension::DualSourceBlending => Self::DUAL_SOURCE_BLENDING,
97                ImplementedEnableExtension::F16 => Self::F16,
98                ImplementedEnableExtension::ClipDistances => Self::CLIP_DISTANCES,
99            },
100            Self::Unimplemented(kind) => match kind {
101                UnimplementedEnableExtension::Subgroups => Self::SUBGROUPS,
102                UnimplementedEnableExtension::PrimitiveIndex => Self::PRIMITIVE_INDEX,
103            },
104        }
105    }
106}
107
108/// A variant of [`EnableExtension::Implemented`].
109#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
110pub enum ImplementedEnableExtension {
111    /// Enables `f16`/`half` primitive support in all shader languages.
112    ///
113    /// In the WGSL standard, this corresponds to [`enable f16;`].
114    ///
115    /// [`enable f16;`]: https://www.w3.org/TR/WGSL/#extension-f16
116    F16,
117    /// Enables the `blend_src` attribute in WGSL.
118    ///
119    /// In the WGSL standard, this corresponds to [`enable dual_source_blending;`].
120    ///
121    /// [`enable dual_source_blending;`]: https://www.w3.org/TR/WGSL/#extension-dual_source_blending
122    DualSourceBlending,
123    /// Enables the `clip_distances` variable in WGSL.
124    ///
125    /// In the WGSL standard, this corresponds to [`enable clip_distances;`].
126    ///
127    /// [`enable clip_distances;`]: https://www.w3.org/TR/WGSL/#extension-clip_distances
128    ClipDistances,
129}
130
131/// A variant of [`EnableExtension::Unimplemented`].
132#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
133pub enum UnimplementedEnableExtension {
134    /// Enables subgroup built-ins in all languages.
135    ///
136    /// In the WGSL standard, this corresponds to [`enable subgroups;`].
137    ///
138    /// [`enable subgroups;`]: https://www.w3.org/TR/WGSL/#extension-subgroups
139    Subgroups,
140    /// Enables the `@builtin(primitive_index)` attribute in WGSL.
141    ///
142    /// In the WGSL standard, this corresponds to [`enable primitive-index;`].
143    ///
144    /// [`enable primitive-index;`]: https://www.w3.org/TR/WGSL/#extension-primitive_index
145    PrimitiveIndex,
146}
147
148impl UnimplementedEnableExtension {
149    pub(crate) const fn tracking_issue_num(self) -> u16 {
150        match self {
151            Self::Subgroups => 5555,
152            Self::PrimitiveIndex => 8236,
153        }
154    }
155}