[glsl-in] Only add builtins with double arguments if needed

This commit is contained in:
João Capucho
2021-08-18 00:14:47 +01:00
committed by Dzmitry Malyshau
parent b05ca6e403
commit 4e181d6af4
5 changed files with 1356 additions and 1187 deletions

View File

@@ -47,7 +47,7 @@ impl fmt::Debug for FunctionKind {
}
#[derive(Debug)]
pub struct FunctionDeclaration {
pub struct Overload {
/// Normalized function parameters, modifiers are not applied
pub parameters: Vec<Handle<Type>>,
pub parameters_info: Vec<ParameterInfo>,
@@ -59,6 +59,16 @@ pub struct FunctionDeclaration {
pub void: bool,
}
#[derive(Debug, Default)]
pub struct FunctionDeclaration {
pub overloads: Vec<Overload>,
/// Wether or not this function has the name of a builtin
pub builtin: bool,
/// In case [`builtin`](Self::builtin) is true, this field indicates wether
/// this function already has double overloads added or not, otherwise is unused
pub double: bool,
}
#[derive(Debug)]
pub struct EntryArg {
pub name: Option<String>,

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
use super::{
ast::*,
builtins::sampled_to_depth,
builtins::{inject_builtin, inject_double_builtin, sampled_to_depth},
context::{Context, StmtContext},
error::{Error, ErrorKind},
types::scalar_components,
@@ -356,17 +356,25 @@ impl Parser {
) -> Result<Option<Handle<Expression>>> {
// If the name for the function hasn't yet been initialized check if any
// builtin can be injected.
//
// NOTE: A name not being initialized is not the same as no declarations
// being existing.
if self.lookup_function.get(&name).is_none() {
self.inject_builtin(name.clone());
let declaration = self.lookup_function.entry(name.clone()).or_default();
inject_builtin(declaration, &mut self.module, &name);
}
let declarations = self.lookup_function.get(&name).ok_or_else(|| Error {
kind: ErrorKind::SemanticError(format!("Unknown function '{}'", name).into()),
meta,
})?;
// Check if any argument uses a double type
let has_double = args
.iter()
.any(|&(expr, meta)| self.resolve_type(ctx, expr, meta).map_or(false, is_double));
// At this point a declaration is guaranteed
let declaration = self.lookup_function.get_mut(&name).unwrap();
if declaration.builtin && !declaration.double && has_double {
inject_double_builtin(declaration, &mut self.module, &name);
}
// Borrow again but without mutability
let declaration = self.lookup_function.get(&name).unwrap();
// Helper enum containing the type of conversion need for a call
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
@@ -389,7 +397,7 @@ impl Parser {
let mut old_conversions = vec![Conversion::None; args.len()];
let mut ambiguous = false;
'outer: for decl in declarations {
'outer: for decl in declaration.overloads.iter() {
if args.len() != decl.parameters.len() {
continue;
}
@@ -660,7 +668,8 @@ impl Parser {
meta: SourceMetadata,
) {
if self.lookup_function.get(&name).is_none() {
self.inject_builtin(name.clone());
let declaration = self.lookup_function.entry(name.clone()).or_default();
inject_builtin(declaration, &mut self.module, &name);
}
ensure_block_returns(&mut body);
@@ -673,7 +682,8 @@ impl Parser {
..
} = self;
let declarations = lookup_function.entry(name.clone()).or_default();
let declaration = lookup_function.entry(name.clone()).or_default();
let Context {
expressions,
locals,
@@ -682,6 +692,16 @@ impl Parser {
parameters_info,
..
} = ctx;
if declaration.builtin
&& !declaration.double
&& parameters
.iter()
.any(|ty| is_double(&module.types[*ty].inner))
{
inject_double_builtin(declaration, module, &name);
}
let function = Function {
name: Some(name),
arguments,
@@ -692,7 +712,7 @@ impl Parser {
body,
};
'outer: for decl in declarations.iter_mut() {
'outer: for decl in declaration.overloads.iter_mut() {
if parameters.len() != decl.parameters.len() {
continue;
}
@@ -726,7 +746,7 @@ impl Parser {
}
let handle = module.functions.append(function, meta.as_span());
declarations.push(FunctionDeclaration {
declaration.overloads.push(Overload {
parameters,
parameters_info,
kind: FunctionKind::Call(handle),
@@ -743,7 +763,8 @@ impl Parser {
meta: SourceMetadata,
) {
if self.lookup_function.get(&name).is_none() {
self.inject_builtin(name.clone());
let declaration = self.lookup_function.entry(name.clone()).or_default();
inject_builtin(declaration, &mut self.module, &name);
}
let void = result.is_none();
@@ -754,7 +775,7 @@ impl Parser {
..
} = self;
let declarations = lookup_function.entry(name.clone()).or_default();
let declaration = lookup_function.entry(name.clone()).or_default();
let Context {
arguments,
@@ -762,6 +783,16 @@ impl Parser {
parameters_info,
..
} = ctx;
if declaration.builtin
&& !declaration.double
&& parameters
.iter()
.any(|ty| is_double(&module.types[*ty].inner))
{
inject_double_builtin(declaration, module, &name);
}
let function = Function {
name: Some(name),
arguments,
@@ -769,7 +800,7 @@ impl Parser {
..Default::default()
};
'outer: for decl in declarations.iter_mut() {
'outer: for decl in declaration.overloads.iter() {
if parameters.len() != decl.parameters.len() {
continue;
}
@@ -790,7 +821,7 @@ impl Parser {
}
let handle = module.functions.append(function, meta.as_span());
declarations.push(FunctionDeclaration {
declaration.overloads.push(Overload {
parameters,
parameters_info,
kind: FunctionKind::Call(handle),
@@ -922,3 +953,13 @@ impl Parser {
});
}
}
fn is_double(ty: &TypeInner) -> bool {
match *ty {
TypeInner::ValuePointer { kind, width, .. }
| TypeInner::Scalar { kind, width }
| TypeInner::Vector { kind, width, .. } => kind == ScalarKind::Float && width == 8,
TypeInner::Matrix { width, .. } => width == 8,
_ => false,
}
}

View File

@@ -159,7 +159,7 @@ impl Default for ShaderMetadata {
pub struct Parser {
meta: ShaderMetadata,
lookup_function: FastHashMap<String, Vec<FunctionDeclaration>>,
lookup_function: FastHashMap<String, FunctionDeclaration>,
lookup_type: FastHashMap<String, Handle<Type>>,
global_variables: Vec<(String, GlobalLookup)>,

View File

@@ -139,13 +139,16 @@ impl<'source> ParsingContext<'source> {
self.parse_external_declaration(parser, &mut ctx, &mut body)?;
}
match parser.lookup_function.get("main").and_then(|declarations| {
declarations.iter().find_map(|decl| match decl.kind {
FunctionKind::Call(handle) if decl.defined && decl.parameters.is_empty() => {
Some(handle)
}
_ => None,
})
match parser.lookup_function.get("main").and_then(|declaration| {
declaration
.overloads
.iter()
.find_map(|decl| match decl.kind {
FunctionKind::Call(handle) if decl.defined && decl.parameters.is_empty() => {
Some(handle)
}
_ => None,
})
}) {
Some(handle) => parser.add_entry_point(handle, body, ctx.expressions),
None => parser.errors.push(Error {