From d6b172ddcb363402a526e50f0c79448e9f231eaa Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Wed, 19 Aug 2020 14:09:28 -0400 Subject: [PATCH] Add support for array stride to wgsl frontend (#137) * Add support for array stride to wgsl frontend * rename --- src/front/wgsl.rs | 48 ++++++++++++++++++++++++++++++++++++++++---- test-data/boids.wgsl | 2 +- 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/src/front/wgsl.rs b/src/front/wgsl.rs index 6ebf0aea02..6ae1eee23c 100644 --- a/src/front/wgsl.rs +++ b/src/front/wgsl.rs @@ -170,6 +170,8 @@ pub enum Error<'a> { UnknownFunction(&'a str), #[error("missing offset for structure member `{0}`")] MissingMemberOffset(&'a str), + #[error("array stride must not be 0")] + ZeroStride, //MutabilityViolation(&'a str), // TODO: these could be replaced with more detailed errors #[error("other error")] @@ -256,6 +258,22 @@ impl<'a> Lexer<'a> { self.expect(Token::Paren('>'))?; Ok(pair) } + + fn take_until(&mut self, what: Token<'a>) -> Result, Error<'a>> { + let original_input = self.input; + let initial_len = self.input.len(); + let mut used_len = 0; + loop { + if self.next() == what { + break; + } + used_len = initial_len - self.input.len(); + } + + Ok(Lexer { + input: &original_input[..used_len], + }) + } } trait StringValueLookup<'a> { @@ -1000,6 +1018,12 @@ impl Parser { type_arena: &mut Arena, ) -> Result, Error<'a>> { self.scopes.push(Scope::TypeDecl); + let decoration_lexer = if lexer.skip(Token::DoubleParen('[')) { + Some(lexer.take_until(Token::DoubleParen(']'))?) + } else { + None + }; + let inner = match lexer.next() { Token::Word("f32") => crate::TypeInner::Scalar { kind: crate::ScalarKind::Float, @@ -1138,11 +1162,27 @@ impl Parser { Token::Separator('>') => crate::ArraySize::Dynamic, other => return Err(Error::Unexpected(other)), }; - crate::TypeInner::Array { - base, - size, - stride: None, + + let mut stride = None; + if let Some(mut lexer) = decoration_lexer { + self.scopes.push(Scope::Decoration); + loop { + match lexer.next() { + Token::Word("stride") => { + use std::num::NonZeroU32; + stride = Some( + NonZeroU32::new(lexer.next_uint_literal()?) + .ok_or(Error::ZeroStride)?, + ); + } + Token::End => break, + other => return Err(Error::Unexpected(other)), + } + } + self.scopes.pop(); } + + crate::TypeInner::Array { base, size, stride } } Token::Word("struct") => { let members = self.parse_struct_body(lexer, type_arena)?; diff --git a/test-data/boids.wgsl b/test-data/boids.wgsl index a7c13dd63e..b3aeca6e07 100644 --- a/test-data/boids.wgsl +++ b/test-data/boids.wgsl @@ -57,7 +57,7 @@ type SimParams = struct { }; type Particles = struct { - [[offset 0]] particles : array; + [[offset 0]] particles : [[stride 16]] array; }; [[binding 0, set 0]] var params : SimParams;