From 7bdcac83e5836241f6d1a603795d0385295fd183 Mon Sep 17 00:00:00 2001 From: Pelle Johnsen Date: Mon, 21 Sep 2020 15:10:17 +0000 Subject: [PATCH] [glsl-in] Support anonymous global uniforms Partly fixes #210 --- src/front/glsl/ast.rs | 2 +- src/front/glsl/parser.rs | 19 +++++++++++-------- src/front/glsl/variables.rs | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 9 deletions(-) diff --git a/src/front/glsl/ast.rs b/src/front/glsl/ast.rs index bd8f12595e..ce63dee0be 100644 --- a/src/front/glsl/ast.rs +++ b/src/front/glsl/ast.rs @@ -159,7 +159,7 @@ pub enum TypeQualifier { #[derive(Debug)] pub struct VarDeclaration { pub type_qualifiers: Vec, - pub ids_initializers: Vec<(String, Option)>, + pub ids_initializers: Vec<(Option, Option)>, pub ty: Handle, } diff --git a/src/front/glsl/parser.rs b/src/front/glsl/parser.rs index e0dff7325d..f39e1b985a 100644 --- a/src/front/glsl/parser.rs +++ b/src/front/glsl/parser.rs @@ -475,7 +475,7 @@ pomelo! { struct_declaration_list(sdl) RightBrace Semicolon { VarDeclaration{ type_qualifiers: t, - ids_initializers: vec![], + ids_initializers: vec![(None, None)], ty: extra.module.types.fetch_or_append(Type{ name: Some(i.1), inner: TypeInner::Struct { @@ -489,7 +489,7 @@ pomelo! { struct_declaration_list(sdl) RightBrace Identifier(i2) Semicolon { VarDeclaration{ type_qualifiers: t, - ids_initializers: vec![(i2.1, None)], + ids_initializers: vec![(Some(i2.1), None)], ty: extra.module.types.fetch_or_append(Type{ name: Some(i1.1), inner: TypeInner::Struct { @@ -504,13 +504,13 @@ pomelo! { init_declarator_list ::= single_declaration; init_declarator_list ::= init_declarator_list(mut idl) Comma Identifier(i) { - idl.ids_initializers.push((i.1, None)); + idl.ids_initializers.push((Some(i.1), None)); idl } // init_declarator_list ::= init_declarator_list Comma Identifier array_specifier; // init_declarator_list ::= init_declarator_list Comma Identifier array_specifier Equal initializer; init_declarator_list ::= init_declarator_list(mut idl) Comma Identifier(i) Equal initializer(init) { - idl.ids_initializers.push((i.1, Some(init))); + idl.ids_initializers.push((Some(i.1), Some(init))); idl } @@ -528,7 +528,7 @@ pomelo! { VarDeclaration{ type_qualifiers: t.0, - ids_initializers: vec![(i.1, None)], + ids_initializers: vec![(Some(i.1), None)], ty, } } @@ -539,7 +539,7 @@ pomelo! { VarDeclaration{ type_qualifiers: t.0, - ids_initializers: vec![(i.1, Some(init))], + ids_initializers: vec![(Some(i.1), Some(init))], ty, } } @@ -705,6 +705,7 @@ pomelo! { let mut statements = Vec::::new(); // local variables for (id, initializer) in d.ids_initializers { + let id = id.ok_or(ErrorKind::SemanticError("local var must be named"))?; // check if already declared in current scope #[cfg(feature = "glsl-validate")] { @@ -871,7 +872,7 @@ pomelo! { for (id, initializer) in d.ids_initializers { let h = extra.module.global_variables.fetch_or_append( GlobalVariable { - name: Some(id.clone()), + name: id.clone(), class, binding: binding.clone(), ty: d.ty, @@ -879,7 +880,9 @@ pomelo! { storage_access: StorageAccess::empty(), //TODO }, ); - extra.lookup_global_variables.insert(id, h); + if let Some(id) = id { + extra.lookup_global_variables.insert(id, h); + } } } diff --git a/src/front/glsl/variables.rs b/src/front/glsl/variables.rs index 834f787651..14d91ca4ca 100644 --- a/src/front/glsl/variables.rs +++ b/src/front/glsl/variables.rs @@ -7,6 +7,41 @@ use super::ast::*; use super::error::ErrorKind; impl Program { + fn lookup_global_struct_member(&mut self, name: &str) -> Option> { + let global_struct_member = self + .module + .global_variables + .iter() + // find globals without name + .filter(|(_, var)| var.name.is_none()) + // find those of struct type and map to their members + .filter_map(|(h, var)| { + let ty = &self.module.types[var.ty]; + if let TypeInner::Struct { members } = &ty.inner { + Some((h, members)) + } else { + None + } + }) + // find member matching name + .find_map(|(h, members)| { + members + .iter() + .position(|m| m.name == Some(name.into())) + .map(|idx| (h, idx)) + }); + global_struct_member.map(|(h, idx)| { + let base = self + .context + .expressions + .append(Expression::GlobalVariable(h)); + self.context.expressions.append(Expression::AccessIndex { + base, + index: idx as u32, + }) + }) + } + pub fn lookup_variable(&mut self, name: &str) -> Result>, ErrorKind> { let mut expression: Option> = None; match name { @@ -92,6 +127,8 @@ impl Program { Ok(Some(local_var)) } else if let Some(global_var) = self.context.lookup_global_var_exps.get(name) { Ok(Some(*global_var)) + } else if let Some(global_member) = self.lookup_global_struct_member(name) { + Ok(Some(global_member)) } else { Ok(None) }