mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-25 00:03:29 +00:00
feat(wgsl-in): create skeleton for enable
directives
Co-Authored-By: FL33TW00D <chris@fleetwood.dev>
This commit is contained in:
parent
54861b712c
commit
bf4cd9cd31
@ -85,7 +85,7 @@ By @bradwerth [#6216](https://github.com/gfx-rs/wgpu/pull/6216).
|
||||
- Support local `const` declarations in WGSL. By @sagudev in [#6156](https://github.com/gfx-rs/wgpu/pull/6156).
|
||||
- Implemented `const_assert` in WGSL. By @sagudev in [#6198](https://github.com/gfx-rs/wgpu/pull/6198).
|
||||
- Support polyfilling `inverse` in WGSL. By @chyyran in [#6385](https://github.com/gfx-rs/wgpu/pull/6385).
|
||||
- Add an internal skeleton for parsing `requires`, `enable`, and `diagnostic` directives that don't yet do anything besides emit nicer errors. By @ErichDonGubler in [#6352](https://github.com/gfx-rs/wgpu/pull/6352).
|
||||
- Add an internal skeleton for parsing `requires`, `enable`, and `diagnostic` directives that don't yet do anything besides emit nicer errors. By @ErichDonGubler in [#6352](https://github.com/gfx-rs/wgpu/pull/6352), [#6424](https://github.com/gfx-rs/wgpu/pull/6424).
|
||||
- Include error chain information as a message and notes in shader compilation messages. By @ErichDonGubler in [#6436](https://github.com/gfx-rs/wgpu/pull/6436).
|
||||
- Unify Naga CLI error output with the format of shader compilation messages. By @ErichDonGubler in [#6436](https://github.com/gfx-rs/wgpu/pull/6436).
|
||||
|
||||
|
@ -1,3 +1,6 @@
|
||||
use crate::front::wgsl::parse::directive::enable_extension::{
|
||||
EnableExtension, UnimplementedEnableExtension,
|
||||
};
|
||||
use crate::front::wgsl::parse::directive::{DirectiveKind, UnimplementedDirectiveKind};
|
||||
use crate::front::wgsl::parse::lexer::Token;
|
||||
use crate::front::wgsl::Scalar;
|
||||
@ -186,6 +189,7 @@ pub(crate) enum Error<'a> {
|
||||
UnknownType(Span),
|
||||
UnknownStorageFormat(Span),
|
||||
UnknownConservativeDepth(Span),
|
||||
UnknownEnableExtension(Span, &'a str),
|
||||
SizeAttributeTooLow(Span, u32),
|
||||
AlignAttributeTooLow(Span, Alignment),
|
||||
NonPowerOfTwoAlignAttribute(Span),
|
||||
@ -275,6 +279,10 @@ pub(crate) enum Error<'a> {
|
||||
DirectiveAfterFirstGlobalDecl {
|
||||
directive_span: Span,
|
||||
},
|
||||
EnableExtensionNotYetImplemented {
|
||||
kind: UnimplementedEnableExtension,
|
||||
span: Span,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
@ -525,6 +533,14 @@ impl<'a> Error<'a> {
|
||||
labels: vec![(bad_span, "unknown type".into())],
|
||||
notes: vec![],
|
||||
},
|
||||
Error::UnknownEnableExtension(span, word) => ParseError {
|
||||
message: format!("unknown enable-extension `{}`", word),
|
||||
labels: vec![(span, "".into())],
|
||||
notes: vec![
|
||||
"See available extensions at <https://www.w3.org/TR/WGSL/#enable-extension>."
|
||||
.into(),
|
||||
],
|
||||
},
|
||||
Error::SizeAttributeTooLow(bad_span, min_size) => ParseError {
|
||||
message: format!("struct member size must be at least {min_size}"),
|
||||
labels: vec![(bad_span, format!("must be at least {min_size}").into())],
|
||||
@ -907,6 +923,28 @@ impl<'a> Error<'a> {
|
||||
)
|
||||
.into()],
|
||||
},
|
||||
Error::EnableExtensionNotYetImplemented { kind, span } => ParseError {
|
||||
message: format!(
|
||||
"the `{}` extension is not yet supported",
|
||||
EnableExtension::Unimplemented(kind).to_ident()
|
||||
),
|
||||
labels: vec![(
|
||||
span,
|
||||
concat!(
|
||||
"this extension specifies standard functionality ",
|
||||
"which is not yet implemented in Naga"
|
||||
)
|
||||
.into(),
|
||||
)],
|
||||
notes: vec![format!(
|
||||
concat!(
|
||||
"Let Naga maintainers know that you ran into this at ",
|
||||
"<https://github.com/gfx-rs/wgpu/issues/{}>, ",
|
||||
"so they can prioritize it!"
|
||||
),
|
||||
kind.tracking_issue_num()
|
||||
)],
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
use crate::front::wgsl::parse::directive::enable_extension::EnableExtensions;
|
||||
use crate::front::wgsl::parse::number::Number;
|
||||
use crate::front::wgsl::Scalar;
|
||||
use crate::{Arena, FastIndexSet, Handle, Span};
|
||||
@ -5,6 +6,7 @@ use std::hash::Hash;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct TranslationUnit<'a> {
|
||||
pub enable_extensions: EnableExtensions,
|
||||
pub decls: Arena<GlobalDecl<'a>>,
|
||||
/// The common expressions arena for the entire translation unit.
|
||||
///
|
||||
|
@ -2,9 +2,13 @@
|
||||
//!
|
||||
//! See also <https://www.w3.org/TR/WGSL/#directives>.
|
||||
|
||||
pub mod enable_extension;
|
||||
|
||||
/// A parsed sentinel word indicating the type of directive to be parsed next.
|
||||
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
|
||||
pub enum DirectiveKind {
|
||||
/// An [`enable_extension`].
|
||||
Enable,
|
||||
Unimplemented(UnimplementedDirectiveKind),
|
||||
}
|
||||
|
||||
@ -17,7 +21,7 @@ impl DirectiveKind {
|
||||
pub fn from_ident(s: &str) -> Option<Self> {
|
||||
Some(match s {
|
||||
Self::DIAGNOSTIC => Self::Unimplemented(UnimplementedDirectiveKind::Diagnostic),
|
||||
Self::ENABLE => Self::Unimplemented(UnimplementedDirectiveKind::Enable),
|
||||
Self::ENABLE => Self::Enable,
|
||||
Self::REQUIRES => Self::Unimplemented(UnimplementedDirectiveKind::Requires),
|
||||
_ => return None,
|
||||
})
|
||||
@ -26,9 +30,9 @@ impl DirectiveKind {
|
||||
/// Maps this [`DirectiveKind`] into the sentinel word associated with it in WGSL.
|
||||
pub const fn to_ident(self) -> &'static str {
|
||||
match self {
|
||||
Self::Enable => Self::ENABLE,
|
||||
Self::Unimplemented(kind) => match kind {
|
||||
UnimplementedDirectiveKind::Diagnostic => Self::DIAGNOSTIC,
|
||||
UnimplementedDirectiveKind::Enable => Self::ENABLE,
|
||||
UnimplementedDirectiveKind::Requires => Self::REQUIRES,
|
||||
},
|
||||
}
|
||||
@ -47,7 +51,6 @@ impl DirectiveKind {
|
||||
#[cfg_attr(test, derive(strum::EnumIter))]
|
||||
pub enum UnimplementedDirectiveKind {
|
||||
Diagnostic,
|
||||
Enable,
|
||||
Requires,
|
||||
}
|
||||
|
||||
@ -56,7 +59,6 @@ impl UnimplementedDirectiveKind {
|
||||
match self {
|
||||
Self::Diagnostic => 5320,
|
||||
Self::Requires => 6350,
|
||||
Self::Enable => 5476,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -86,19 +88,6 @@ error: `diagnostic` is not yet implemented
|
||||
│
|
||||
= note: Let Naga maintainers know that you ran into this at <https://github.com/gfx-rs/wgpu/issues/5320>, so they can prioritize it!
|
||||
|
||||
";
|
||||
}
|
||||
UnimplementedDirectiveKind::Enable => {
|
||||
shader = "enable f16;";
|
||||
expected_msg = "\
|
||||
error: `enable` is not yet implemented
|
||||
┌─ wgsl:1:1
|
||||
│
|
||||
1 │ enable f16;
|
||||
│ ^^^^^^ this global directive is standard, but not yet implemented
|
||||
│
|
||||
= note: Let Naga maintainers know that you ran into this at <https://github.com/gfx-rs/wgpu/issues/5476>, so they can prioritize it!
|
||||
|
||||
";
|
||||
}
|
||||
UnimplementedDirectiveKind::Requires => {
|
||||
@ -139,7 +128,7 @@ error: expected global declaration, but found a global directive
|
||||
|
||||
";
|
||||
}
|
||||
DirectiveKind::Unimplemented(UnimplementedDirectiveKind::Enable) => {
|
||||
DirectiveKind::Enable => {
|
||||
directive = "enable f16";
|
||||
expected_msg = "\
|
||||
error: expected global declaration, but found a global directive
|
||||
|
112
naga/src/front/wgsl/parse/directive/enable_extension.rs
Normal file
112
naga/src/front/wgsl/parse/directive/enable_extension.rs
Normal file
@ -0,0 +1,112 @@
|
||||
//! `enable …;` extensions in WGSL.
|
||||
//!
|
||||
//! The focal point of this module is the [`EnableExtension`] API.
|
||||
use crate::{front::wgsl::error::Error, Span};
|
||||
|
||||
/// Tracks the status of every enable extension known to Naga.
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct EnableExtensions {}
|
||||
|
||||
impl EnableExtensions {
|
||||
pub(crate) const fn empty() -> Self {
|
||||
Self {}
|
||||
}
|
||||
|
||||
/// Add an enable extension to the set requested by a module.
|
||||
#[allow(unreachable_code)]
|
||||
pub(crate) fn add(&mut self, ext: ImplementedEnableExtension) {
|
||||
let _field: &mut bool = match ext {};
|
||||
*_field = true;
|
||||
}
|
||||
|
||||
/// Query whether an enable extension tracked here has been requested.
|
||||
#[allow(unused)]
|
||||
pub(crate) const fn contains(&self, ext: ImplementedEnableExtension) -> bool {
|
||||
match ext {}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for EnableExtensions {
|
||||
fn default() -> Self {
|
||||
Self::empty()
|
||||
}
|
||||
}
|
||||
|
||||
/// A shader language extension not guaranteed to be present in all environments.
|
||||
///
|
||||
/// WGSL spec.: <https://www.w3.org/TR/WGSL/#enable-extensions-sec>
|
||||
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
|
||||
pub enum EnableExtension {
|
||||
#[allow(unused)]
|
||||
Implemented(ImplementedEnableExtension),
|
||||
Unimplemented(UnimplementedEnableExtension),
|
||||
}
|
||||
|
||||
impl EnableExtension {
|
||||
const F16: &'static str = "f16";
|
||||
const CLIP_DISTANCES: &'static str = "clip_distances";
|
||||
const DUAL_SOURCE_BLENDING: &'static str = "dual_source_blending";
|
||||
|
||||
/// Convert from a sentinel word in WGSL into its associated [`EnableExtension`], if possible.
|
||||
pub(crate) fn from_ident(word: &str, span: Span) -> Result<Self, Error<'_>> {
|
||||
Ok(match word {
|
||||
Self::F16 => Self::Unimplemented(UnimplementedEnableExtension::F16),
|
||||
Self::CLIP_DISTANCES => {
|
||||
Self::Unimplemented(UnimplementedEnableExtension::ClipDistances)
|
||||
}
|
||||
Self::DUAL_SOURCE_BLENDING => {
|
||||
Self::Unimplemented(UnimplementedEnableExtension::DualSourceBlending)
|
||||
}
|
||||
_ => return Err(Error::UnknownEnableExtension(span, word)),
|
||||
})
|
||||
}
|
||||
|
||||
/// Maps this [`EnableExtension`] into the sentinel word associated with it in WGSL.
|
||||
pub const fn to_ident(self) -> &'static str {
|
||||
match self {
|
||||
Self::Implemented(kind) => match kind {},
|
||||
Self::Unimplemented(kind) => match kind {
|
||||
UnimplementedEnableExtension::F16 => Self::F16,
|
||||
UnimplementedEnableExtension::ClipDistances => Self::CLIP_DISTANCES,
|
||||
UnimplementedEnableExtension::DualSourceBlending => Self::DUAL_SOURCE_BLENDING,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A variant of [`EnableExtension::Implemented`].
|
||||
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
|
||||
pub enum ImplementedEnableExtension {}
|
||||
|
||||
/// A variant of [`EnableExtension::Unimplemented`].
|
||||
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
|
||||
pub enum UnimplementedEnableExtension {
|
||||
/// Enables `f16`/`half` primitive support in all shader languages.
|
||||
///
|
||||
/// In the WGSL standard, this corresponds to [`enable f16;`].
|
||||
///
|
||||
/// [`enable f16;`]: https://www.w3.org/TR/WGSL/#extension-f16
|
||||
F16,
|
||||
/// Enables the `clip_distances` variable in WGSL.
|
||||
///
|
||||
/// In the WGSL standard, this corresponds to [`enable clip_distances;`].
|
||||
///
|
||||
/// [`enable clip_distances;`]: https://www.w3.org/TR/WGSL/#extension-f16
|
||||
ClipDistances,
|
||||
/// Enables the `blend_src` attribute in WGSL.
|
||||
///
|
||||
/// In the WGSL standard, this corresponds to [`enable dual_source_blending;`].
|
||||
///
|
||||
/// [`enable dual_source_blending;`]: https://www.w3.org/TR/WGSL/#extension-f16
|
||||
DualSourceBlending,
|
||||
}
|
||||
|
||||
impl UnimplementedEnableExtension {
|
||||
pub(crate) const fn tracking_issue_num(self) -> u16 {
|
||||
match self {
|
||||
Self::F16 => 4384,
|
||||
Self::ClipDistances => 6236,
|
||||
Self::DualSourceBlending => 6402,
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
use super::{number::consume_number, Error, ExpectedToken};
|
||||
use crate::front::wgsl::error::NumberError;
|
||||
use crate::front::wgsl::parse::directive::enable_extension::EnableExtensions;
|
||||
use crate::front::wgsl::parse::{conv, Number};
|
||||
use crate::front::wgsl::Scalar;
|
||||
use crate::Span;
|
||||
@ -204,6 +205,8 @@ pub(in crate::front::wgsl) struct Lexer<'a> {
|
||||
pub(in crate::front::wgsl) source: &'a str,
|
||||
// The byte offset of the end of the last non-trivia token.
|
||||
last_end_offset: usize,
|
||||
#[allow(dead_code)]
|
||||
pub(in crate::front::wgsl) enable_extensions: EnableExtensions,
|
||||
}
|
||||
|
||||
impl<'a> Lexer<'a> {
|
||||
@ -212,6 +215,7 @@ impl<'a> Lexer<'a> {
|
||||
input,
|
||||
source: input,
|
||||
last_end_offset: 0,
|
||||
enable_extensions: EnableExtensions::empty(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
use crate::front::wgsl::error::{Error, ExpectedToken};
|
||||
use crate::front::wgsl::parse::directive::enable_extension::{EnableExtension, EnableExtensions};
|
||||
use crate::front::wgsl::parse::directive::DirectiveKind;
|
||||
use crate::front::wgsl::parse::lexer::{Lexer, Token};
|
||||
use crate::front::wgsl::parse::number::Number;
|
||||
@ -2258,7 +2259,6 @@ impl Parser {
|
||||
Ok(fun)
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
fn directive_ident_list<'a>(
|
||||
&self,
|
||||
lexer: &mut Lexer<'a>,
|
||||
@ -2510,14 +2510,30 @@ impl Parser {
|
||||
|
||||
let mut lexer = Lexer::new(source);
|
||||
let mut tu = ast::TranslationUnit::default();
|
||||
let mut enable_extensions = EnableExtensions::empty();
|
||||
|
||||
// Parse directives.
|
||||
#[allow(clippy::never_loop, unreachable_code)]
|
||||
while let Ok((ident, span)) = lexer.peek_ident_with_span() {
|
||||
if let Some(kind) = DirectiveKind::from_ident(ident) {
|
||||
self.push_rule_span(Rule::Directive, &mut lexer);
|
||||
let _ = lexer.next_ident_with_span().unwrap();
|
||||
match kind {
|
||||
DirectiveKind::Enable => {
|
||||
self.directive_ident_list(&mut lexer, |ident, span| {
|
||||
let kind = EnableExtension::from_ident(ident, span)?;
|
||||
let extension = match kind {
|
||||
EnableExtension::Implemented(kind) => kind,
|
||||
EnableExtension::Unimplemented(kind) => {
|
||||
return Err(Error::EnableExtensionNotYetImplemented {
|
||||
kind,
|
||||
span,
|
||||
})
|
||||
}
|
||||
};
|
||||
enable_extensions.add(extension);
|
||||
Ok(())
|
||||
})?;
|
||||
}
|
||||
DirectiveKind::Unimplemented(kind) => {
|
||||
return Err(Error::DirectiveNotYetImplemented { kind, span })
|
||||
}
|
||||
@ -2528,6 +2544,9 @@ impl Parser {
|
||||
}
|
||||
}
|
||||
|
||||
lexer.enable_extensions = enable_extensions.clone();
|
||||
tu.enable_extensions = enable_extensions;
|
||||
|
||||
loop {
|
||||
match self.global_decl(&mut lexer, &mut tu) {
|
||||
Err(error) => return Err(error),
|
||||
|
Loading…
Reference in New Issue
Block a user