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    wgpu_mesh_shader: bool,
14    wgpu_ray_query: bool,
15    wgpu_ray_query_vertex_return: bool,
16    dual_source_blending: bool,
17    /// Whether `enable f16;` was written earlier in the shader module.
18    f16: bool,
19    clip_distances: bool,
20}
21
22impl EnableExtensions {
23    pub(crate) const fn empty() -> Self {
24        Self {
25            wgpu_mesh_shader: false,
26            wgpu_ray_query: false,
27            wgpu_ray_query_vertex_return: false,
28            f16: false,
29            dual_source_blending: false,
30            clip_distances: false,
31        }
32    }
33
34    /// Add an enable-extension to the set requested by a module.
35    pub(crate) fn add(&mut self, ext: ImplementedEnableExtension) {
36        let field = match ext {
37            ImplementedEnableExtension::WgpuMeshShader => &mut self.wgpu_mesh_shader,
38            ImplementedEnableExtension::WgpuRayQuery => &mut self.wgpu_ray_query,
39            ImplementedEnableExtension::WgpuRayQueryVertexReturn => {
40                &mut self.wgpu_ray_query_vertex_return
41            }
42            ImplementedEnableExtension::DualSourceBlending => &mut self.dual_source_blending,
43            ImplementedEnableExtension::F16 => &mut self.f16,
44            ImplementedEnableExtension::ClipDistances => &mut self.clip_distances,
45        };
46        *field = true;
47    }
48
49    /// Query whether an enable-extension tracked here has been requested.
50    pub(crate) const fn contains(&self, ext: ImplementedEnableExtension) -> bool {
51        match ext {
52            ImplementedEnableExtension::WgpuMeshShader => self.wgpu_mesh_shader,
53            ImplementedEnableExtension::WgpuRayQuery => self.wgpu_ray_query,
54            ImplementedEnableExtension::WgpuRayQueryVertexReturn => {
55                self.wgpu_ray_query_vertex_return
56            }
57            ImplementedEnableExtension::DualSourceBlending => self.dual_source_blending,
58            ImplementedEnableExtension::F16 => self.f16,
59            ImplementedEnableExtension::ClipDistances => self.clip_distances,
60        }
61    }
62}
63
64impl Default for EnableExtensions {
65    fn default() -> Self {
66        Self::empty()
67    }
68}
69
70/// An enable-extension not guaranteed to be present in all environments.
71///
72/// WGSL spec.: <https://www.w3.org/TR/WGSL/#enable-extensions-sec>
73#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
74pub enum EnableExtension {
75    Implemented(ImplementedEnableExtension),
76    Unimplemented(UnimplementedEnableExtension),
77}
78
79impl From<ImplementedEnableExtension> for EnableExtension {
80    fn from(value: ImplementedEnableExtension) -> Self {
81        Self::Implemented(value)
82    }
83}
84
85impl EnableExtension {
86    const F16: &'static str = "f16";
87    const CLIP_DISTANCES: &'static str = "clip_distances";
88    const DUAL_SOURCE_BLENDING: &'static str = "dual_source_blending";
89    const MESH_SHADER: &'static str = "wgpu_mesh_shader";
90    const RAY_QUERY: &'static str = "wgpu_ray_query";
91    const RAY_QUERY_VERTEX_RETURN: &'static str = "wgpu_ray_query_vertex_return";
92    const SUBGROUPS: &'static str = "subgroups";
93    const PRIMITIVE_INDEX: &'static str = "primitive_index";
94
95    /// Convert from a sentinel word in WGSL into its associated [`EnableExtension`], if possible.
96    pub(crate) fn from_ident(word: &str, span: Span) -> Result<'_, Self> {
97        Ok(match word {
98            Self::F16 => Self::Implemented(ImplementedEnableExtension::F16),
99            Self::CLIP_DISTANCES => Self::Implemented(ImplementedEnableExtension::ClipDistances),
100            Self::DUAL_SOURCE_BLENDING => {
101                Self::Implemented(ImplementedEnableExtension::DualSourceBlending)
102            }
103            Self::MESH_SHADER => Self::Implemented(ImplementedEnableExtension::WgpuMeshShader),
104            Self::RAY_QUERY => Self::Implemented(ImplementedEnableExtension::WgpuRayQuery),
105            Self::RAY_QUERY_VERTEX_RETURN => {
106                Self::Implemented(ImplementedEnableExtension::WgpuRayQueryVertexReturn)
107            }
108            Self::SUBGROUPS => Self::Unimplemented(UnimplementedEnableExtension::Subgroups),
109            Self::PRIMITIVE_INDEX => {
110                Self::Unimplemented(UnimplementedEnableExtension::PrimitiveIndex)
111            }
112            _ => return Err(Box::new(Error::UnknownEnableExtension(span, word))),
113        })
114    }
115
116    /// Maps this [`EnableExtension`] into the sentinel word associated with it in WGSL.
117    pub const fn to_ident(self) -> &'static str {
118        match self {
119            Self::Implemented(kind) => match kind {
120                ImplementedEnableExtension::WgpuMeshShader => Self::MESH_SHADER,
121                ImplementedEnableExtension::WgpuRayQuery => Self::RAY_QUERY,
122                ImplementedEnableExtension::WgpuRayQueryVertexReturn => {
123                    Self::RAY_QUERY_VERTEX_RETURN
124                }
125                ImplementedEnableExtension::DualSourceBlending => Self::DUAL_SOURCE_BLENDING,
126                ImplementedEnableExtension::F16 => Self::F16,
127                ImplementedEnableExtension::ClipDistances => Self::CLIP_DISTANCES,
128            },
129            Self::Unimplemented(kind) => match kind {
130                UnimplementedEnableExtension::Subgroups => Self::SUBGROUPS,
131                UnimplementedEnableExtension::PrimitiveIndex => Self::PRIMITIVE_INDEX,
132            },
133        }
134    }
135}
136
137/// A variant of [`EnableExtension::Implemented`].
138#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
139pub enum ImplementedEnableExtension {
140    /// Enables `f16`/`half` primitive support in all shader languages.
141    ///
142    /// In the WGSL standard, this corresponds to [`enable f16;`].
143    ///
144    /// [`enable f16;`]: https://www.w3.org/TR/WGSL/#extension-f16
145    F16,
146    /// Enables the `blend_src` attribute in WGSL.
147    ///
148    /// In the WGSL standard, this corresponds to [`enable dual_source_blending;`].
149    ///
150    /// [`enable dual_source_blending;`]: https://www.w3.org/TR/WGSL/#extension-dual_source_blending
151    DualSourceBlending,
152    /// Enables the `clip_distances` variable in WGSL.
153    ///
154    /// In the WGSL standard, this corresponds to [`enable clip_distances;`].
155    ///
156    /// [`enable clip_distances;`]: https://www.w3.org/TR/WGSL/#extension-clip_distances
157    ClipDistances,
158    /// Enables the `wgpu_mesh_shader` extension, native only
159    WgpuMeshShader,
160    /// Enables the `wgpu_ray_query` extension, native only.
161    WgpuRayQuery,
162    /// Enables the `wgpu_ray_query_vertex_return` extension, native only.
163    WgpuRayQueryVertexReturn,
164}
165
166/// A variant of [`EnableExtension::Unimplemented`].
167#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
168pub enum UnimplementedEnableExtension {
169    /// Enables subgroup built-ins in all languages.
170    ///
171    /// In the WGSL standard, this corresponds to [`enable subgroups;`].
172    ///
173    /// [`enable subgroups;`]: https://www.w3.org/TR/WGSL/#extension-subgroups
174    Subgroups,
175    /// Enables the `@builtin(primitive_index)` attribute in WGSL.
176    ///
177    /// In the WGSL standard, this corresponds to [`enable primitive-index;`].
178    ///
179    /// [`enable primitive-index;`]: https://www.w3.org/TR/WGSL/#extension-primitive_index
180    PrimitiveIndex,
181}
182
183impl UnimplementedEnableExtension {
184    pub(crate) const fn tracking_issue_num(self) -> u16 {
185        match self {
186            Self::Subgroups => 5555,
187            Self::PrimitiveIndex => 8236,
188        }
189    }
190}