From 9ddca9cef5c1ea480469d20fc16d472182bce1e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Capucho?= Date: Sun, 16 May 2021 18:42:01 +0100 Subject: [PATCH] [glsl-in] Fix input/output handling Previously we passed a struct with the input bindings and just ignored the outputs. Now we handle them the same way we do with builtins, by creating function local globals that are read and written in a wrapper entry point. --- src/front/glsl/ast.rs | 47 ++----------------- src/front/glsl/functions.rs | 83 +++++++++++++++++++++------------- src/front/glsl/parser.rs | 4 +- src/front/glsl/parser_tests.rs | 15 ++++++ src/front/glsl/variables.rs | 82 ++++++++++----------------------- 5 files changed, 96 insertions(+), 135 deletions(-) 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!() - } - } }