1use crate::front::wgsl::{Error, Result};
6use crate::Span;
7
8use alloc::boxed::Box;
9
10#[derive(Clone, Copy, Debug, Eq, PartialEq)]
12pub(crate) struct EnableExtensions {
13 wgpu_mesh_shader: bool,
14 wgpu_ray_query: bool,
15 wgpu_ray_query_vertex_return: bool,
16 wgpu_ray_tracing_pipeline: bool,
17 dual_source_blending: bool,
18 f16: bool,
20 wgpu_int16: bool,
22 clip_distances: bool,
23 wgpu_cooperative_matrix: bool,
24 draw_index: bool,
25 primitive_index: bool,
26 per_vertex: bool,
27 wgpu_binding_array: bool,
28 debug_printf: bool,
29}
30
31impl EnableExtensions {
32 pub(crate) const fn empty() -> Self {
33 Self {
34 wgpu_mesh_shader: false,
35 wgpu_ray_query: false,
36 wgpu_ray_query_vertex_return: false,
37 wgpu_ray_tracing_pipeline: false,
38 f16: false,
39 wgpu_int16: false,
40 dual_source_blending: false,
41 clip_distances: false,
42 wgpu_cooperative_matrix: false,
43 draw_index: false,
44 primitive_index: false,
45 per_vertex: false,
46 wgpu_binding_array: false,
47 debug_printf: false,
48 }
49 }
50
51 pub(crate) const fn add(&mut self, ext: ImplementedEnableExtension) {
53 let field = match ext {
54 ImplementedEnableExtension::WgpuMeshShader => &mut self.wgpu_mesh_shader,
55 ImplementedEnableExtension::WgpuRayQuery => &mut self.wgpu_ray_query,
56 ImplementedEnableExtension::WgpuRayQueryVertexReturn => {
57 &mut self.wgpu_ray_query_vertex_return
58 }
59 ImplementedEnableExtension::WgpuRayTracingPipeline => {
60 &mut self.wgpu_ray_tracing_pipeline
61 }
62 ImplementedEnableExtension::DualSourceBlending => &mut self.dual_source_blending,
63 ImplementedEnableExtension::F16 => &mut self.f16,
64 ImplementedEnableExtension::WgpuInt16 => &mut self.wgpu_int16,
65 ImplementedEnableExtension::ClipDistances => &mut self.clip_distances,
66 ImplementedEnableExtension::WgpuCooperativeMatrix => &mut self.wgpu_cooperative_matrix,
67 ImplementedEnableExtension::DrawIndex => &mut self.draw_index,
68 ImplementedEnableExtension::PrimitiveIndex => &mut self.primitive_index,
69 ImplementedEnableExtension::WgpuPerVertex => &mut self.per_vertex,
70 ImplementedEnableExtension::WgpuBindingArray => &mut self.wgpu_binding_array,
71 ImplementedEnableExtension::WgpuDebugPrintf => &mut self.debug_printf,
72 };
73 *field = true;
74 }
75
76 pub(crate) const fn contains(&self, ext: ImplementedEnableExtension) -> bool {
78 match ext {
79 ImplementedEnableExtension::WgpuMeshShader => self.wgpu_mesh_shader,
80 ImplementedEnableExtension::WgpuRayQuery => self.wgpu_ray_query,
81 ImplementedEnableExtension::WgpuRayQueryVertexReturn => {
82 self.wgpu_ray_query_vertex_return
83 }
84 ImplementedEnableExtension::WgpuRayTracingPipeline => self.wgpu_ray_tracing_pipeline,
85 ImplementedEnableExtension::DualSourceBlending => self.dual_source_blending,
86 ImplementedEnableExtension::F16 => self.f16,
87 ImplementedEnableExtension::WgpuInt16 => self.wgpu_int16,
88 ImplementedEnableExtension::ClipDistances => self.clip_distances,
89 ImplementedEnableExtension::WgpuCooperativeMatrix => self.wgpu_cooperative_matrix,
90 ImplementedEnableExtension::DrawIndex => self.draw_index,
91 ImplementedEnableExtension::PrimitiveIndex => self.primitive_index,
92 ImplementedEnableExtension::WgpuPerVertex => self.per_vertex,
93 ImplementedEnableExtension::WgpuBindingArray => self.wgpu_binding_array,
94 ImplementedEnableExtension::WgpuDebugPrintf => self.debug_printf,
95 }
96 }
97
98 pub(crate) fn require(
99 &self,
100 ext: ImplementedEnableExtension,
101 span: Span,
102 ) -> Result<'static, ()> {
103 if !self.contains(ext) {
104 Err(Box::new(Error::EnableExtensionNotEnabled {
105 span,
106 kind: ext.into(),
107 }))
108 } else {
109 Ok(())
110 }
111 }
112}
113
114impl Default for EnableExtensions {
115 fn default() -> Self {
116 Self::empty()
117 }
118}
119
120#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
124pub enum EnableExtension {
125 Implemented(ImplementedEnableExtension),
126 Unimplemented(UnimplementedEnableExtension),
127}
128
129impl From<ImplementedEnableExtension> for EnableExtension {
130 fn from(value: ImplementedEnableExtension) -> Self {
131 Self::Implemented(value)
132 }
133}
134
135impl EnableExtension {
136 const F16: &'static str = "f16";
137 const CLIP_DISTANCES: &'static str = "clip_distances";
138 const DUAL_SOURCE_BLENDING: &'static str = "dual_source_blending";
139 const MESH_SHADER: &'static str = "wgpu_mesh_shader";
140 const RAY_QUERY: &'static str = "wgpu_ray_query";
141 const RAY_QUERY_VERTEX_RETURN: &'static str = "wgpu_ray_query_vertex_return";
142 const RAY_TRACING_PIPELINE: &'static str = "wgpu_ray_tracing_pipeline";
143 const COOPERATIVE_MATRIX: &'static str = "wgpu_cooperative_matrix";
144 const SUBGROUPS: &'static str = "subgroups";
145 const PRIMITIVE_INDEX: &'static str = "primitive_index";
146 const DRAW_INDEX: &'static str = "draw_index";
147 const PER_VERTEX: &'static str = "wgpu_per_vertex";
148 const BINDING_ARRAY: &'static str = "wgpu_binding_array";
149 const INT16: &'static str = "wgpu_int16";
150 const DEBUG_PRINTF: &'static str = "wgpu_debug_printf";
151
152 pub(crate) fn from_ident(word: &str, span: Span) -> Result<'_, Self> {
154 Ok(match word {
155 Self::F16 => Self::Implemented(ImplementedEnableExtension::F16),
156 Self::CLIP_DISTANCES => Self::Implemented(ImplementedEnableExtension::ClipDistances),
157 Self::DUAL_SOURCE_BLENDING => {
158 Self::Implemented(ImplementedEnableExtension::DualSourceBlending)
159 }
160 Self::MESH_SHADER => Self::Implemented(ImplementedEnableExtension::WgpuMeshShader),
161 Self::RAY_QUERY => Self::Implemented(ImplementedEnableExtension::WgpuRayQuery),
162 Self::RAY_QUERY_VERTEX_RETURN => {
163 Self::Implemented(ImplementedEnableExtension::WgpuRayQueryVertexReturn)
164 }
165 Self::RAY_TRACING_PIPELINE => {
166 Self::Implemented(ImplementedEnableExtension::WgpuRayTracingPipeline)
167 }
168 Self::COOPERATIVE_MATRIX => {
169 Self::Implemented(ImplementedEnableExtension::WgpuCooperativeMatrix)
170 }
171 Self::SUBGROUPS => Self::Unimplemented(UnimplementedEnableExtension::Subgroups),
172 Self::DRAW_INDEX => Self::Implemented(ImplementedEnableExtension::DrawIndex),
173 Self::PRIMITIVE_INDEX => Self::Implemented(ImplementedEnableExtension::PrimitiveIndex),
174 Self::PER_VERTEX => Self::Implemented(ImplementedEnableExtension::WgpuPerVertex),
175 Self::BINDING_ARRAY => Self::Implemented(ImplementedEnableExtension::WgpuBindingArray),
176 Self::INT16 => Self::Implemented(ImplementedEnableExtension::WgpuInt16),
177 Self::DEBUG_PRINTF => Self::Implemented(ImplementedEnableExtension::WgpuDebugPrintf),
178 _ => return Err(Box::new(Error::UnknownEnableExtension(span, word))),
179 })
180 }
181
182 pub const fn to_ident(self) -> &'static str {
184 match self {
185 Self::Implemented(kind) => match kind {
186 ImplementedEnableExtension::WgpuMeshShader => Self::MESH_SHADER,
187 ImplementedEnableExtension::WgpuRayQuery => Self::RAY_QUERY,
188 ImplementedEnableExtension::WgpuRayQueryVertexReturn => {
189 Self::RAY_QUERY_VERTEX_RETURN
190 }
191 ImplementedEnableExtension::WgpuCooperativeMatrix => Self::COOPERATIVE_MATRIX,
192 ImplementedEnableExtension::DualSourceBlending => Self::DUAL_SOURCE_BLENDING,
193 ImplementedEnableExtension::F16 => Self::F16,
194 ImplementedEnableExtension::ClipDistances => Self::CLIP_DISTANCES,
195 ImplementedEnableExtension::DrawIndex => Self::DRAW_INDEX,
196 ImplementedEnableExtension::PrimitiveIndex => Self::PRIMITIVE_INDEX,
197 ImplementedEnableExtension::WgpuRayTracingPipeline => Self::RAY_TRACING_PIPELINE,
198 ImplementedEnableExtension::WgpuPerVertex => Self::PER_VERTEX,
199 ImplementedEnableExtension::WgpuBindingArray => Self::BINDING_ARRAY,
200 ImplementedEnableExtension::WgpuInt16 => Self::INT16,
201 ImplementedEnableExtension::WgpuDebugPrintf => Self::DEBUG_PRINTF,
202 },
203 Self::Unimplemented(kind) => match kind {
204 UnimplementedEnableExtension::Subgroups => Self::SUBGROUPS,
205 },
206 }
207 }
208}
209
210#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
212#[cfg_attr(test, derive(strum::VariantArray))]
213pub enum ImplementedEnableExtension {
214 F16,
220 DualSourceBlending,
226 ClipDistances,
232 WgpuMeshShader,
234 WgpuRayQuery,
236 WgpuRayQueryVertexReturn,
238 WgpuRayTracingPipeline,
240 WgpuCooperativeMatrix,
242 DrawIndex,
244 PrimitiveIndex,
250 WgpuPerVertex,
252 WgpuBindingArray,
254 WgpuInt16,
256 WgpuDebugPrintf,
258}
259
260impl ImplementedEnableExtension {
261 pub const VARIANTS: &'static [Self] = &[
263 Self::F16,
264 Self::DualSourceBlending,
265 Self::ClipDistances,
266 Self::WgpuMeshShader,
267 Self::WgpuRayQuery,
268 Self::WgpuRayQueryVertexReturn,
269 Self::WgpuRayTracingPipeline,
270 Self::WgpuCooperativeMatrix,
271 Self::DrawIndex,
272 Self::PrimitiveIndex,
273 Self::WgpuPerVertex,
274 Self::WgpuBindingArray,
275 Self::WgpuInt16,
276 Self::WgpuDebugPrintf,
277 ];
278
279 pub const fn all() -> &'static [Self] {
281 Self::VARIANTS
282 }
283
284 pub const fn capability(self) -> crate::valid::Capabilities {
286 use crate::valid::Capabilities as C;
287 match self {
288 Self::F16 => C::SHADER_FLOAT16,
289 Self::DualSourceBlending => C::DUAL_SOURCE_BLENDING,
290 Self::ClipDistances => C::CLIP_DISTANCES,
291 Self::WgpuMeshShader => C::MESH_SHADER,
292 Self::WgpuRayQuery => C::RAY_QUERY,
293 Self::WgpuRayQueryVertexReturn => C::RAY_HIT_VERTEX_POSITION,
294 Self::WgpuCooperativeMatrix => C::COOPERATIVE_MATRIX,
295 Self::WgpuRayTracingPipeline => C::RAY_TRACING_PIPELINE,
296 Self::DrawIndex => C::DRAW_INDEX,
297 Self::PrimitiveIndex => C::PRIMITIVE_INDEX,
298 Self::WgpuPerVertex => C::PER_VERTEX,
299 Self::WgpuBindingArray => C::BUFFER_BINDING_ARRAY
300 .union(C::BUFFER_BINDING_ARRAY_NON_UNIFORM_INDEXING)
301 .union(C::STORAGE_BUFFER_BINDING_ARRAY)
302 .union(C::STORAGE_BUFFER_BINDING_ARRAY_NON_UNIFORM_INDEXING)
303 .union(C::STORAGE_TEXTURE_BINDING_ARRAY)
304 .union(C::STORAGE_TEXTURE_BINDING_ARRAY_NON_UNIFORM_INDEXING)
305 .union(C::TEXTURE_AND_SAMPLER_BINDING_ARRAY)
306 .union(C::TEXTURE_AND_SAMPLER_BINDING_ARRAY_NON_UNIFORM_INDEXING)
307 .union(C::ACCELERATION_STRUCTURE_BINDING_ARRAY),
308 Self::WgpuInt16 => C::SHADER_INT16,
309 Self::WgpuDebugPrintf => C::DEBUG_PRINTF,
310 }
311 }
312}
313
314#[test]
315fn test_manual_variants_array_is_correct() {
318 assert_eq!(
319 <ImplementedEnableExtension as strum::VariantArray>::VARIANTS,
320 ImplementedEnableExtension::VARIANTS
321 );
322}
323
324#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
326pub enum UnimplementedEnableExtension {
327 Subgroups,
333}
334
335impl UnimplementedEnableExtension {
336 pub(crate) const fn tracking_issue_num(self) -> u16 {
337 match self {
338 Self::Subgroups => 5555,
339 }
340 }
341}