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