Skip to content

Commit 1adbf95

Browse files
WIP: feat(wgsl-in)!: allow opt-out of wgpu-specific enable-extensions
TODO: `CHANGELOG` TODO: document TODO: Explain new error surface on opt-out
2 parents 8efeb12 + ff0dbcc commit 1adbf95

2 files changed

Lines changed: 123 additions & 18 deletions

File tree

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

Lines changed: 104 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,33 +17,70 @@ pub struct EnableExtensions {
1717
/// Whether `enable clip_distances;` was written earlier in the shader module.
1818
clip_distances: bool,
1919
/// Native-only extensions.
20-
wgpu: WgpuEnableExtensions,
20+
wgpu: NativeOnly<WgpuEnableExtensions>,
2121
}
2222

2323
impl EnableExtensions {
24-
pub(crate) const fn empty() -> Self {
24+
pub(crate) const fn empty(native_only: NativeOnly<()>) -> Self {
25+
// TODO: It'd be nice to use a `const` `map` helper here, once
26+
// <https://github.com/rust-lang/rust/issues/73255> has landed.
27+
let wgpu = match native_only {
28+
NativeOnly::NotAllowed {
29+
can_suggest_in_diagnostics,
30+
} => NativeOnly::NotAllowed {
31+
can_suggest_in_diagnostics,
32+
},
33+
NativeOnly::Allowed(()) => NativeOnly::Allowed(WgpuEnableExtensions::empty()),
34+
};
2535
Self {
26-
wgpu: WgpuEnableExtensions::empty(),
36+
wgpu,
2737
f16: false,
2838
dual_source_blending: false,
2939
clip_distances: false,
3040
}
3141
}
3242

3343
/// Add an enable-extension to the set requested by a module.
34-
pub(crate) fn add(&mut self, ext: ImplementedEnableExtension) {
44+
pub(crate) fn enable(
45+
&mut self,
46+
span: Span,
47+
ext: ImplementedEnableExtension,
48+
) -> core::result::Result<(), EnableExtensionNotAvailableError> {
49+
macro_rules! check_wgpu {
50+
($f:expr) => {{
51+
let f: fn(&mut WgpuEnableExtensions) -> &mut bool = $f;
52+
match &mut self.wgpu {
53+
&mut NativeOnly::Allowed(ref mut wgpu) => Ok(f(wgpu)),
54+
&mut NativeOnly::NotAllowed {
55+
can_suggest_in_diagnostics,
56+
} => Err(EnableExtensionNotAvailableError {
57+
span,
58+
extension: ext,
59+
reason: EnableExtensionNotAvailableErrorReason::NotAllowed {
60+
can_suggest_in_diagnostics,
61+
},
62+
}),
63+
}
64+
}};
65+
}
3566
let field = match ext {
36-
ImplementedEnableExtension::WgpuMeshShader => &mut self.wgpu.mesh_shader,
37-
ImplementedEnableExtension::WgpuRayQuery => &mut self.wgpu.ray_query,
67+
ImplementedEnableExtension::WgpuMeshShader => {
68+
check_wgpu!(|wgpu| &mut wgpu.mesh_shader)?
69+
}
70+
ImplementedEnableExtension::WgpuRayQuery => check_wgpu!(|wgpu| &mut wgpu.ray_query)?,
3871
ImplementedEnableExtension::WgpuRayQueryVertexReturn => {
39-
&mut self.wgpu.ray_query_vertex_return
72+
check_wgpu!(|wgpu| &mut wgpu.ray_query_vertex_return)?
4073
}
4174
ImplementedEnableExtension::DualSourceBlending => &mut self.dual_source_blending,
4275
ImplementedEnableExtension::F16 => &mut self.f16,
4376
ImplementedEnableExtension::ClipDistances => &mut self.clip_distances,
44-
ImplementedEnableExtension::WgpuCooperativeMatrix => &mut self.wgpu.cooperative_matrix,
77+
ImplementedEnableExtension::WgpuCooperativeMatrix => {
78+
check_wgpu!(|wgpu| &mut wgpu.cooperative_matrix)?
79+
}
4580
};
4681
*field = true;
82+
83+
Ok(())
4784
}
4885

4986
/// Query whether an enable-extension tracked here has been requested.
@@ -52,16 +89,31 @@ impl EnableExtensions {
5289
span: Span,
5390
extension: ImplementedEnableExtension,
5491
) -> core::result::Result<(), EnableExtensionNotAvailableError> {
92+
let check_wgpu = |f: fn(&WgpuEnableExtensions) -> bool| match &self.wgpu {
93+
&NativeOnly::Allowed(ref wgpu) => Ok(f(wgpu)),
94+
&NativeOnly::NotAllowed {
95+
can_suggest_in_diagnostics,
96+
} => Err(EnableExtensionNotAvailableError {
97+
span,
98+
extension,
99+
reason: EnableExtensionNotAvailableErrorReason::NotAllowed {
100+
can_suggest_in_diagnostics,
101+
},
102+
}),
103+
};
104+
55105
let is_enabled = match extension {
56-
ImplementedEnableExtension::WgpuMeshShader => self.wgpu.mesh_shader,
57-
ImplementedEnableExtension::WgpuRayQuery => self.wgpu.ray_query,
106+
ImplementedEnableExtension::WgpuMeshShader => check_wgpu(|wgpu| wgpu.mesh_shader)?,
107+
ImplementedEnableExtension::WgpuRayQuery => check_wgpu(|wgpu| wgpu.ray_query)?,
58108
ImplementedEnableExtension::WgpuRayQueryVertexReturn => {
59-
self.wgpu.ray_query_vertex_return
109+
check_wgpu(|wgpu| wgpu.ray_query_vertex_return)?
60110
}
61111
ImplementedEnableExtension::DualSourceBlending => self.dual_source_blending,
62112
ImplementedEnableExtension::F16 => self.f16,
63113
ImplementedEnableExtension::ClipDistances => self.clip_distances,
64-
ImplementedEnableExtension::WgpuCooperativeMatrix => self.wgpu.cooperative_matrix,
114+
ImplementedEnableExtension::WgpuCooperativeMatrix => {
115+
check_wgpu(|wgpu| wgpu.cooperative_matrix)?
116+
}
65117
};
66118

67119
if is_enabled {
@@ -78,7 +130,45 @@ impl EnableExtensions {
78130

79131
impl Default for EnableExtensions {
80132
fn default() -> Self {
81-
Self::empty()
133+
Self::empty(NativeOnly::default())
134+
}
135+
}
136+
137+
/// Native-only extensions under [`EnableExtensions::wgpu`].
138+
#[derive(Clone, Debug, Eq, PartialEq)]
139+
pub enum NativeOnly<T> {
140+
NotAllowed {
141+
/// Whether the diagnostic of a validation check encountering this case may contain a hint
142+
/// about enabling native-only extensions.
143+
///
144+
/// Set this to `false` when you are running user-provided shaders in non-native
145+
/// environments.
146+
can_suggest_in_diagnostics: bool,
147+
},
148+
Allowed(T),
149+
}
150+
151+
impl<T> NativeOnly<T> {
152+
pub fn map<U, F>(self, f: F) -> NativeOnly<U>
153+
where
154+
F: FnOnce(T) -> U,
155+
{
156+
match self {
157+
Self::NotAllowed {
158+
can_suggest_in_diagnostics,
159+
} => NativeOnly::NotAllowed {
160+
can_suggest_in_diagnostics,
161+
},
162+
Self::Allowed(t) => NativeOnly::Allowed(f(t)),
163+
}
164+
}
165+
}
166+
167+
impl<T> Default for NativeOnly<T> {
168+
fn default() -> Self {
169+
Self::NotAllowed {
170+
can_suggest_in_diagnostics: false,
171+
}
82172
}
83173
}
84174

@@ -124,6 +214,7 @@ pub struct EnableExtensionNotAvailableError {
124214
#[derive(Clone, Debug, Eq, PartialEq)]
125215
pub enum EnableExtensionNotAvailableErrorReason {
126216
NotEnabled,
217+
NotAllowed { can_suggest_in_diagnostics: bool },
127218
}
128219

129220
/// An enable-extension not guaranteed to be present in all environments.

naga/src/front/wgsl/parse/lexer.rs

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use super::{number::consume_number, Error, ExpectedToken, Result};
22
use crate::front::wgsl::error::NumberError;
3-
use crate::front::wgsl::parse::directive::enable_extension::EnableExtensions;
3+
use crate::front::wgsl::parse::directive::enable_extension::{EnableExtensions, NativeOnly};
44
use crate::front::wgsl::parse::{conv, Number};
55
use crate::front::wgsl::Scalar;
66
use crate::Span;
@@ -243,6 +243,17 @@ fn is_word_part(c: char) -> bool {
243243
unicode_ident::is_xid_continue(c)
244244
}
245245

246+
// TODO: document
247+
#[derive(Clone, Eq, PartialEq)]
248+
pub struct LexerConfig {
249+
/// Whether to enable native-only [enable-extensions](EnableExtensions).
250+
native_only_enable_extensions: NativeOnly<()>,
251+
252+
/// Whether or not to ignore doc comments.
253+
/// If `true`, doc comments are treated as [`Token::Trivia`].
254+
ignore_doc_comments: bool,
255+
}
256+
246257
#[derive(Clone)]
247258
pub(in crate::front::wgsl) struct Lexer<'a> {
248259
/// The remaining unconsumed input.
@@ -262,20 +273,23 @@ pub(in crate::front::wgsl) struct Lexer<'a> {
262273
/// statements.
263274
last_end_offset: usize,
264275

265-
/// Whether or not to ignore doc comments.
266-
/// If `true`, doc comments are treated as [`Token::Trivia`].
276+
/// See [`LexerConfig::ignore_doc_comments`].
267277
ignore_doc_comments: bool,
268278

269279
pub(in crate::front::wgsl) enable_extensions: EnableExtensions,
270280
}
271281

272282
impl<'a> Lexer<'a> {
273-
pub(in crate::front::wgsl) const fn new(input: &'a str, ignore_doc_comments: bool) -> Self {
283+
pub(in crate::front::wgsl) const fn new(input: &'a str, config: LexerConfig) -> Self {
284+
let LexerConfig {
285+
native_only_enable_extensions,
286+
ignore_doc_comments,
287+
} = config;
274288
Lexer {
275289
input,
276290
source: input,
277291
last_end_offset: 0,
278-
enable_extensions: EnableExtensions::empty(),
292+
enable_extensions: EnableExtensions::empty(native_only_enable_extensions),
279293
ignore_doc_comments,
280294
}
281295
}

0 commit comments

Comments
 (0)