diff --git a/src/front/glsl/ast.rs b/src/front/glsl/ast.rs index 7c67ddac59..5da25fbf57 100644 --- a/src/front/glsl/ast.rs +++ b/src/front/glsl/ast.rs @@ -1,6 +1,6 @@ use super::{super::Typifier, constants::ConstantSolver, error::ErrorKind, SourceMetadata}; use crate::{ - proc::ResolveContext, Arena, BinaryOperator, Block, BuiltIn, Constant, Expression, FastHashMap, + proc::ResolveContext, Arena, BinaryOperator, Binding, Block, Constant, Expression, FastHashMap, Function, FunctionArgument, GlobalVariable, Handle, Interpolation, LocalVariable, Module, RelationalFunction, ResourceBinding, Sampling, ShaderStage, Statement, StorageClass, Type, TypeInner, UnaryOperator, @@ -9,7 +9,6 @@ use crate::{ #[derive(Debug)] pub enum GlobalLookup { Variable(Handle), - InOutSelect(u32), BlockSelect(Handle, u32), } @@ -38,19 +37,14 @@ pub struct Program<'a> { pub lookup_global_variables: FastHashMap, pub lookup_constants: FastHashMap>, - pub built_ins: Vec<(BuiltIn, Handle)>, + pub entry_args: Vec<(Binding, bool, Handle)>, pub entries: Vec<(String, ShaderStage, Handle)>, - pub input_struct: Handle, - pub output_struct: Handle, - pub module: Module, } impl<'a> Program<'a> { pub fn new(entry_points: &'a FastHashMap) -> Program<'a> { - let mut module = Module::default(); - Program { version: 0, profile: Profile::Core, @@ -61,27 +55,10 @@ impl<'a> Program<'a> { lookup_global_variables: FastHashMap::default(), lookup_constants: FastHashMap::default(), - built_ins: Vec::new(), + entry_args: Vec::new(), entries: Vec::new(), - input_struct: module.types.append(Type { - name: None, - inner: TypeInner::Struct { - level: crate::StructLevel::Root, - members: Vec::new(), - span: 0, - }, - }), - output_struct: module.types.append(Type { - name: None, - inner: TypeInner::Struct { - level: crate::StructLevel::Root, - members: Vec::new(), - span: 0, - }, - }), - - module, + module: Module::default(), } } @@ -155,17 +132,6 @@ impl<'a> Program<'a> { solver.solve(root).map_err(|e| (meta, e).into()) } - - pub fn function_args_prelude(&self) -> (Vec, Vec) { - ( - vec![FunctionArgument { - name: None, - ty: self.input_struct, - binding: None, - }], - vec![ParameterQualifier::In], - ) - } } #[derive(Debug, PartialEq)] @@ -223,11 +189,6 @@ impl<'function> Context<'function> { self.lookup_global_var_exps.get(name).cloned().or_else(|| { let expr = match *program.lookup_global_variables.get(name)? { GlobalLookup::Variable(v) => Expression::GlobalVariable(v), - GlobalLookup::InOutSelect(index) => { - let base = self.expressions.append(Expression::FunctionArgument(0)); - - Expression::AccessIndex { base, index } - } GlobalLookup::BlockSelect(handle, index) => { let base = self.expressions.append(Expression::GlobalVariable(handle)); diff --git a/src/front/glsl/functions.rs b/src/front/glsl/functions.rs index d210aa96cd..be4fcfca6c 100644 --- a/src/front/glsl/functions.rs +++ b/src/front/glsl/functions.rs @@ -1,8 +1,8 @@ use crate::{ proc::ensure_block_returns, Arena, BinaryOperator, Binding, Block, BuiltIn, EntryPoint, Expression, Function, FunctionArgument, FunctionResult, Handle, MathFunction, - RelationalFunction, SampleLevel, ScalarKind, ShaderStage, Statement, StorageClass, Type, - TypeInner, + RelationalFunction, SampleLevel, ScalarKind, ShaderStage, Statement, StorageClass, + StructMember, Type, TypeInner, }; use super::{ast::*, error::ErrorKind, SourceMetadata}; @@ -223,14 +223,15 @@ impl Program<'_> { self.parse_relational_fun(ctx, name, &args, RelationalFunction::Any, meta) } _ => { - let sig = FunctionSignature { - name, - parameters: args - .iter() - .zip(raw_args.iter().map(|e| e.meta.clone())) - .map(|(e, meta)| self.resolve_handle(ctx, *e, meta)) - .collect::>()?, - }; + let mut parameters = Vec::new(); + + for (e, meta) in args.iter().zip(raw_args.iter().map(|e| e.meta.clone())) { + let handle = self.resolve_handle(ctx, *e, meta)?; + + parameters.push(handle) + } + + let sig = FunctionSignature { name, parameters }; let function = self .lookup_function @@ -390,20 +391,19 @@ impl Program<'_> { let mut expressions = Arena::new(); let mut body = Vec::new(); - arguments.push(FunctionArgument { - name: None, - ty: self.input_struct, - binding: None, - }); + for (binding, input, handle) in self.entry_args.iter().cloned() { + match binding { + Binding::Location { .. } if !input => continue, + _ => {} + } - for (built_in, handle) in self.built_ins.iter().copied() { let ty = self.module.global_variables[handle].ty; let arg = arguments.len() as u32; arguments.push(FunctionArgument { name: None, ty, - binding: Some(Binding::BuiltIn(built_in)), + binding: Some(binding), }); let pointer = expressions.append(Expression::GlobalVariable(handle)); @@ -412,25 +412,49 @@ impl Program<'_> { body.push(Statement::Store { pointer, value }); } - let res = expressions.append(Expression::Call(function)); - body.push(Statement::Call { function, - arguments: vec![expressions.append(Expression::FunctionArgument(0))], - result: Some(res), + arguments: Vec::new(), + result: None, }); - for (i, (built_in, handle)) in self.built_ins.iter().copied().enumerate() { - if !should_write(built_in, stage) { - continue; + let mut span = 0; + let mut members = Vec::new(); + let mut components = Vec::new(); + + for (binding, input, handle) in self.entry_args.iter().cloned() { + match binding { + Binding::Location { .. } if input => continue, + Binding::BuiltIn(builtin) if !should_write(builtin, stage) => continue, + _ => {} } - let value = expressions.append(Expression::GlobalVariable(handle)); - let pointer = expressions.append(Expression::FunctionArgument(i as u32 + 1)); + let ty = self.module.global_variables[handle].ty; - body.push(Statement::Store { pointer, value }); + members.push(StructMember { + name: None, + ty, + binding: Some(binding), + offset: span, + }); + + span += self.module.types[ty].inner.span(&self.module.constants); + + let pointer = expressions.append(Expression::GlobalVariable(handle)); + let load = expressions.append(Expression::Load { pointer }); + components.push(load) } + let ty = self.module.types.append(Type { + name: None, + inner: TypeInner::Struct { + top_level: true, + members, + span, + }, + }); + + let res = expressions.append(Expression::Compose { ty, components }); body.push(Statement::Return { value: Some(res) }); self.module.entry_points.push(EntryPoint { @@ -443,10 +467,7 @@ impl Program<'_> { arguments, expressions, body, - result: Some(FunctionResult { - ty: self.output_struct, - binding: None, - }), + result: Some(FunctionResult { ty, binding: None }), ..Default::default() }, }); diff --git a/src/front/glsl/parser.rs b/src/front/glsl/parser.rs index a3debee8c1..bd90a66e3f 100644 --- a/src/front/glsl/parser.rs +++ b/src/front/glsl/parser.rs @@ -569,8 +569,8 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> { let result = ty.map(|ty| FunctionResult { ty, binding: None }); let mut expressions = Arena::new(); let mut local_variables = Arena::new(); - let (mut arguments, mut parameters) = - self.program.function_args_prelude(); + let mut arguments = Vec::new(); + let mut parameters = Vec::new(); let mut context = Context::new( &mut expressions, diff --git a/src/front/glsl/parser_tests.rs b/src/front/glsl/parser_tests.rs index cb8844e47e..3a165ab331 100644 --- a/src/front/glsl/parser_tests.rs +++ b/src/front/glsl/parser_tests.rs @@ -337,6 +337,21 @@ fn functions() { println!(); + let _program = parse_program( + r#" + # version 450 + float callee(uint q) { + return float(q); + } + + float caller() { + callee(1u); + } + "#, + &entry_points, + ) + .unwrap(); + // Nested function call let _program = parse_program( r#" diff --git a/src/front/glsl/variables.rs b/src/front/glsl/variables.rs index b4dcda53b6..7985633c28 100644 --- a/src/front/glsl/variables.rs +++ b/src/front/glsl/variables.rs @@ -1,6 +1,6 @@ use crate::{ Binding, BuiltIn, Constant, Expression, GlobalVariable, Handle, LocalVariable, ScalarKind, - StorageAccess, StorageClass, StructMember, Type, TypeInner, VectorSize, + StorageAccess, StorageClass, Type, TypeInner, VectorSize, }; use super::ast::*; @@ -50,7 +50,8 @@ impl Program<'_> { storage_access: StorageAccess::all(), }); - self.built_ins.push((BuiltIn::Position, handle)); + self.entry_args + .push((Binding::BuiltIn(BuiltIn::Position), true, handle)); self.lookup_global_variables .insert(name.into(), GlobalLookup::Variable(handle)); @@ -75,7 +76,8 @@ impl Program<'_> { storage_access: StorageAccess::all(), }); - self.built_ins.push((BuiltIn::VertexIndex, handle)); + self.entry_args + .push((Binding::BuiltIn(BuiltIn::VertexIndex), true, handle)); self.lookup_global_variables .insert(name.into(), GlobalLookup::Variable(handle)); @@ -100,7 +102,8 @@ impl Program<'_> { storage_access: StorageAccess::all(), }); - self.built_ins.push((BuiltIn::InstanceIndex, handle)); + self.entry_args + .push((Binding::BuiltIn(BuiltIn::InstanceIndex), true, handle)); self.lookup_global_variables .insert(name.into(), GlobalLookup::Variable(handle)); @@ -312,24 +315,29 @@ impl Program<'_> { if let Some(location) = location { let input = StorageQualifier::Input == storage; - let index = self.add_member( - input, - Some(name.clone()), + let handle = self.module.global_variables.append(GlobalVariable { + name: Some(name.clone()), + class: StorageClass::Function, + binding: None, ty, - Some(Binding::Location { + init, + storage_access: StorageAccess::all(), + }); + + self.entry_args.push(( + Binding::Location { location, interpolation, sampling, - }), - ); + }, + input, + handle, + )); self.lookup_global_variables - .insert(name, GlobalLookup::InOutSelect(index)); + .insert(name, GlobalLookup::Variable(handle)); - let base = ctx.expressions.append(Expression::FunctionArgument(0)); - return Ok(ctx - .expressions - .append(Expression::AccessIndex { base, index })); + return Ok(ctx.expressions.append(Expression::GlobalVariable(handle))); } else if let StorageQualifier::Const = storage { let handle = init.ok_or_else(|| { ErrorKind::SemanticError(meta, "Constant must have a initializer".into()) @@ -405,48 +413,4 @@ impl Program<'_> { Ok(expr) } - - fn add_member( - &mut self, - input: bool, - name: Option, - ty: Handle, - binding: Option, - ) -> u32 { - let handle = match input { - true => self.input_struct, - false => self.output_struct, - }; - - let offset = if let TypeInner::Struct { ref members, .. } = self.module.types[handle].inner - { - members - .last() - .map(|member| { - member.offset - + self.module.types[member.ty] - .inner - .span(&self.module.constants) - }) - .unwrap_or(0) - } else { - 0 - }; - - if let TypeInner::Struct { - ref mut members, .. - } = self.module.types.get_mut(handle).inner - { - members.push(StructMember { - name, - ty, - binding, - offset, - }); - - members.len() as u32 - 1 - } else { - unreachable!() - } - } }