From e6d142f28f51dfcd3d2ca8a7db458c8d9578f77d Mon Sep 17 00:00:00 2001 From: Frizi Date: Tue, 15 Jun 2021 12:09:35 +0200 Subject: [PATCH] [glsl-in] treat const globals as constants allow them in array size exprs --- src/front/glsl/ast.rs | 8 ++++++- src/front/glsl/parser.rs | 43 ++++++++++++++++++++++------------- src/front/glsl/variables.rs | 45 ++++++++++++++++++++----------------- tests/out/quad-glsl.wgsl | 10 ++++----- 4 files changed, 63 insertions(+), 43 deletions(-) diff --git a/src/front/glsl/ast.rs b/src/front/glsl/ast.rs index 5367fc74ed..00e72e8852 100644 --- a/src/front/glsl/ast.rs +++ b/src/front/glsl/ast.rs @@ -14,6 +14,7 @@ use crate::{ #[derive(Debug, Clone, Copy)] pub enum GlobalLookupKind { Variable(Handle), + Constant(Handle), BlockSelect(Handle, u32), } @@ -279,6 +280,11 @@ impl<'function> Context<'function> { } }) } + GlobalLookupKind::Constant(v) => { + let res = (this.expressions.append(Expression::Constant(v)), false); + this.emit_start(); + res + } }; let var = VariableReference { @@ -485,7 +491,7 @@ impl<'function> Context<'function> { let handle = match kind { HirExprKind::Access { base, index } => { - let base = self.lower_expect(program, base, lhs, body)?.0; + let base = self.lower_expect(program, base, true, body)?.0; let index = self.lower_expect(program, index, false, body)?.0; let pointer = self.add_expression(Expression::Access { base, index }, body); diff --git a/src/front/glsl/parser.rs b/src/front/glsl/parser.rs index 0caa16dd1a..575aa27bec 100644 --- a/src/front/glsl/parser.rs +++ b/src/front/glsl/parser.rs @@ -7,7 +7,7 @@ use super::{ error::ErrorKind, lex::Lexer, token::{SourceMetadata, Token, TokenValue}, - variables::VarDeclaration, + variables::{GlobalOrConstant, VarDeclaration}, Program, }; use crate::{ @@ -115,13 +115,14 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> { /// Parses an optional array_specifier returning `Ok(None)` if there is no /// LeftBracket fn parse_array_specifier(&mut self) -> Result> { - // TODO: expressions - if let Some(&TokenValue::LeftBracket) = self.lexer.peek().map(|t| &t.value) { - self.bump()?; + if self.bump_if(TokenValue::LeftBracket).is_some() { + if self.bump_if(TokenValue::RightBracket).is_some() { + return Ok(Some(ArraySize::Dynamic)); + } + let (constant, _) = self.parse_constant_expression()?; self.expect(TokenValue::RightBracket)?; - - Ok(Some(ArraySize::Dynamic)) + Ok(Some(ArraySize::Constant(constant))) } else { Ok(None) } @@ -801,7 +802,7 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> { }; meta = meta.union(&token.meta); - let handle = self.program.add_global_var(VarDeclaration { + let global = self.program.add_global_var(VarDeclaration { qualifiers, ty, name, @@ -817,7 +818,12 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> { self.program.global_variables.push(( k, GlobalLookup { - kind: GlobalLookupKind::BlockSelect(handle, i), + kind: match global { + GlobalOrConstant::Global(handle) => { + GlobalLookupKind::BlockSelect(handle, i) + } + GlobalOrConstant::Constant(handle) => GlobalLookupKind::Constant(handle), + }, entry_arg: None, mutable: true, }, @@ -832,13 +838,18 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> { let mut span = 0; loop { - // TODO: type_qualifier - if !self.peek_type_name() { + if let TokenValue::RightBrace = self.expect_peek()?.value { break; } + // TODO: type_qualifier + let ty = self.parse_type_non_void()?.0; let name = self.expect_ident()?.0; + + let array_specifier = self.parse_array_specifier()?; + let ty = self.maybe_array(ty, array_specifier); + self.expect(TokenValue::Semicolon)?; members.push(StructMember { @@ -848,7 +859,7 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> { offset: span, }); - span = self.program.module.types[ty] + span += self.program.module.types[ty] .inner .span(&self.program.module.constants); } @@ -1691,10 +1702,12 @@ impl<'ctx, 'fun> DeclarationContext<'ctx, 'fun> { match self.external { true => { - let handle = program.add_global_var(decl)?; - Ok(self - .ctx - .add_expression(Expression::GlobalVariable(handle), self.body)) + let global = program.add_global_var(decl)?; + let expr = match global { + GlobalOrConstant::Global(handle) => Expression::GlobalVariable(handle), + GlobalOrConstant::Constant(handle) => Expression::Constant(handle), + }; + Ok(self.ctx.add_expression(expr, self.body)) } false => program.add_local_var(self.ctx, self.body, decl), } diff --git a/src/front/glsl/variables.rs b/src/front/glsl/variables.rs index 9636281cef..3129081e5a 100644 --- a/src/front/glsl/variables.rs +++ b/src/front/glsl/variables.rs @@ -16,6 +16,11 @@ pub struct VarDeclaration<'a> { pub meta: SourceMetadata, } +pub enum GlobalOrConstant { + Global(Handle), + Constant(Handle), +} + impl Program<'_> { pub fn lookup_variable( &mut self, @@ -232,7 +237,7 @@ impl Program<'_> { init, meta, }: VarDeclaration, - ) -> Result, ErrorKind> { + ) -> Result { let mut storage = StorageQualifier::StorageClass(StorageClass::Private); let mut interpolation = None; let mut binding = None; @@ -384,29 +389,27 @@ impl Program<'_> { )); } - return Ok(handle); + return Ok(GlobalOrConstant::Global(handle)); } else if let StorageQualifier::Const = storage { - let handle = self.module.global_variables.append(GlobalVariable { - name: name.clone(), - class: StorageClass::Private, - binding: None, - ty, - init, - storage_access: StorageAccess::empty(), - }); + if let Some(init) = init { + if let Some(name) = name { + self.global_variables.push(( + name, + GlobalLookup { + kind: GlobalLookupKind::Constant(init), + entry_arg: None, + mutable: false, + }, + )); + } - if let Some(name) = name { - self.global_variables.push(( - name, - GlobalLookup { - kind: GlobalLookupKind::Variable(handle), - entry_arg: None, - mutable: false, - }, + return Ok(GlobalOrConstant::Constant(init)); + } else { + return Err(ErrorKind::SemanticError( + meta, + "const values must have an initializer".into(), )); } - - return Ok(handle); } let (class, storage_access) = match self.module.types[ty].inner { @@ -456,7 +459,7 @@ impl Program<'_> { )); } - Ok(handle) + Ok(GlobalOrConstant::Global(handle)) } pub fn add_local_var( diff --git a/tests/out/quad-glsl.wgsl b/tests/out/quad-glsl.wgsl index 22a9b9b707..fccd8cc2ab 100644 --- a/tests/out/quad-glsl.wgsl +++ b/tests/out/quad-glsl.wgsl @@ -7,7 +7,6 @@ struct FragmentOutput { [[location(0), interpolate(perspective)]] member2: vec4; }; -var c_scale: f32 = 1.2000000476837158; var a_pos: vec2; var a_uv: vec2; var v_uv: vec2; @@ -16,11 +15,10 @@ var v_uv1: vec2; var o_color: vec4; fn vert_main() { - let _e1: f32 = c_scale; - let _e3: vec2 = a_pos; - let _e5: vec2 = a_uv; - v_uv = _e5; - gl_Position = vec4((_e1 * _e3), 0.0, 1.0); + let _e2: vec2 = a_pos; + let _e4: vec2 = a_uv; + v_uv = _e4; + gl_Position = vec4((1.2000000476837158 * _e2), 0.0, 1.0); return; }