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